Bus Protocol
April 18, 2026 ยท View on GitHub
This document is the source of truth for the local instance-to-instance bus protocol.
The project currently speaks a compatibility-first v1 protocol:
- new clients send
protocolVersion: 1 - new servers reply with
protocolVersion: 1 - parsers still accept the legacy unversioned shape
Goals
- Keep local delegation between instances explicit and inspectable.
- Allow mixed old/new processes during upgrade.
- Give callers structured failure semantics instead of plain text only.
Transport
- Endpoint:
POST /api/talk - Scope: loopback-only local HTTP
- Auth:
Authorization: Bearer <bus secret>when a secret is configured - Health check:
GET /api/health
Request Shape
Legacy request and v1 request share the same payload fields. v1 adds protocol metadata.
{
"fromInstance": "reviewer",
"prompt": "Please verify this answer",
"depth": 1,
"protocolVersion": 1,
"capabilities": ["structured-errors", "retryable-errors"]
}
Rules:
fromInstancemust be a non-empty string.promptis the delegated prompt body.depthis a non-negative integer.depthis incremented by the caller before sending across the bus.
Response Shape
New servers always emit a v1 envelope, even for pre-handler failures such as auth or peer denial.
{
"success": false,
"text": "",
"fromInstance": "worker",
"error": "Budget exhausted: \$1.2000 used of \$1.00.",
"errorCode": "budget_exhausted",
"retryable": false,
"durationMs": 12,
"protocolVersion": 1,
"capabilities": ["structured-errors", "retryable-errors"]
}
Success responses use the same envelope:
{
"success": true,
"text": "Looks correct overall.",
"fromInstance": "worker",
"durationMs": 241,
"protocolVersion": 1,
"capabilities": ["structured-errors", "retryable-errors"]
}
Compatibility notes:
- parsers still accept legacy success responses without
protocolVersion - parsers still accept legacy failure responses that only contain
success: falseanderror
Error Codes
The bus protocol uses stable, additive string codes. Existing codes:
invalid_requestrequest_too_largebus_disabledauth_failedpeer_not_allowedmax_depth_exceededinvalid_handler_responseinternal_errorinstance_unavailableinvalid_responsetimeoutbudget_exhaustedauthwrite_permissiontelegram_conflicttelegram_deliveryengine_clifile_workflowworkflow_statesession_stateunknown
Rules:
- Add new codes; do not silently rename existing ones.
- Prefer machine-readable codes over parsing
errortext. - Keep
errorhuman-readable because Telegram and CLI paths still surface it directly.
Retry Semantics
retryable answers the narrow question:
Can the caller reasonably try the same delegation again without local operator action?
Current policy:
falsePermanent/configuration/state failures:invalid_request,bus_disabled,auth_failed,peer_not_allowed,max_depth_exceeded,budget_exhausted,auth,write_permission,file_workflow,workflow_state,session_statetrueAvailability/transient failures:invalid_handler_response,internal_error,instance_unavailable,invalid_response,timeout,telegram_conflict,telegram_delivery,engine_cli,unknown
Important clarification:
- remote
authmeans the target instance could not authenticate its own provider CLI - the caller cannot repair that automatically, so it is
retryable: false - remote
budget_exhaustedmeans the target instance itself is over budget, not the caller
Capability Flags
Current capabilities:
structured-errorsretryable-errors
Rules:
- capability lists are additive
- do not remove capabilities without a version bump
- only advertise behavior the process actually implements
Change Rules
- Treat the bus as a protocol, not an internal helper.
- Keep request/response parsing backward-compatible by default.
- Prefer adding fields over changing meaning of existing fields.
- When changing error semantics, update this file and the corresponding tests in:
tests/bus.test.tstests/bus-handler.test.ts