Unified Python interface for AI coding agents. Send a message, get a response — regardless of whether the backend is Claude Code, Codex, or OpenCode.
from agent_bridge import send_message
output, session_id = send_message(
"explain this codebase",
workspace="/path/to/project",
backend="claude", # "claude", "codex", or "opencode"
permission_allow_all=True, # auto-approve tool use
)
print(output)
# Resume conversation
output2, _ = send_message("now add tests", workspace="/path/to/project",
backend="claude", session_id=session_id)python demo.py --backend claude --workspace /tmp/test "hello"
python demo.py --backend codex --workspace . --allow-all "create hello.py"
python demo.py --backend opencode --workspace . "explain main.go"AgentBackend (base.py) — ABC with single abstract method: run()
├── JsonRpcBackend (jsonrpc.py) — owns JsonRpcTransport, notification drain loop
│ ├── AcpBackend (acp.py) — OpenCode (and any future ACP agent)
│ └── McpBackend (mcp.py) — Codex
└── ClaudeCliBackend (claude.py) — Claude Code (streaming JSON, not JSON-RPC)
All backends implement run(message, cwd, session_id, allow_all) → AgentResponse.
-
JSON-RPC backends (ACP, MCP) inherit from
JsonRpcBackend, which provides subprocess management viaJsonRpcTransportand a concurrent notification processing loop. Subclasses only implement protocol-specific hooks:initialize,start_session,send_prompt,handle_notification,get_session_id. -
Non-JSON-RPC backends (Claude CLI) inherit from
AgentBackenddirectly and manage their own subprocess lifecycle insiderun().
| File | Purpose |
|---|---|
__init__.py |
Public API: send_message() + backend factory |
base.py |
AgentBackend ABC + _clean_env() helper |
jsonrpc.py |
JsonRpcTransport (JSON-RPC over stdio) + JsonRpcBackend (abstract) |
acp.py |
AcpBackend — ACP protocol (OpenCode, etc.) |
mcp.py |
McpBackend — MCP protocol (Codex) |
claude.py |
ClaudeCliBackend — Claude Code streaming JSON |
config.py |
AgentConfig dataclass + PRESETS dict |
types.py |
AgentResponse dataclass |
demo.py |
CLI demo script |
Just add a config preset in config.py — zero new files, zero new classes:
"cursor": AgentConfig(
name="cursor",
spawn_cmd=("cursor-agent", "acp"),
protocol="acp",
),It will automatically use AcpBackend which handles the full ACP lifecycle.
Same idea, set protocol="mcp":
"my-mcp-agent": AgentConfig(
name="my-mcp-agent",
spawn_cmd=("my-agent", "mcp-server"),
protocol="mcp",
),- Create a new file (e.g.
my_agent.py) - Subclass
AgentBackendand implementrun() - Register the protocol in
_create_backend()in__init__.py - Add a config preset
By default, agent-bridge produces no log output. Set AGENT_BRIDGE_DEBUG for diagnostics:
| Level | Output |
|---|---|
0 (default) |
Silent |
1 |
Key events: spawn, pid, session, request/response, errors |
2 |
Verbose: every notification, raw I/O, subprocess stderr |
AGENT_BRIDGE_DEBUG=1 python demo.py --backend codex --workspace . "hello"
AGENT_BRIDGE_DEBUG=2 python demo.py --backend codex --workspace . "hello"