Architecture
Overview
opensage-acp sits between an ACP client (acpx) and opensage's web server, translating between protocols.
acpx (or any ACP client)
| JSON-RPC 2.0 / NDJSON on stdin/stdout
v
opensage-acp (this adapter)
| HTTP + SSE to localhost:<port>
v
opensage web (one process per ACP session)
| ADK Runner + OpenSageSession
v
Docker sandboxes, Neo4j (optional), LLM backends (via LiteLLM)
Session lifecycle
- acpx spawns
opensage-acpas a subprocess. - On
session/new, the adapter allocates a free port, writes a per-sessionconfig.toml(merging anymcpServers[]from the ACP request), and spawnsopensage web --agent <dir> --config <generated_toml>on that port. - On
session/prompt, the adapter POSTs to opensage-web's/run_sseendpoint and streams the SSE response back as ACPsession/updatenotifications. - On
session/cancel, the adapter POSTs to/control/stop_turn. - On
session/load, the adapter restarts opensage-web with--resume, restoring chat history from the persisted session snapshot. - On teardown, the adapter terminates the opensage-web process and cleans up the generated config file.
Key modules
| Module | Responsibility |
|---|---|
server.py |
ACP agent protocol implementation, process management |
bridge.py |
HTTP/SSE communication with opensage-web |
config.py |
Configuration loading (TOML + env vars) |
protocol.py |
ACP JSON-RPC message types |
cli.py |
CLI entry point |
Design decisions
Architecture Decision Records are in docs/adr/.