A unified sidecar for agent-to-agent communication via MCP (Model Context Protocol). Operates in two modes: hub (HTTP/SSE server) and channel (MCP stdio server for Claude Code). Enables multi-agent collaboration with handoffs, interrupts, permissions, and shared chat.
A2AChannel defines 8 tools with complete JSON schemas and descriptions. Naming follows verb_noun convention (post, send_handoff, accept_handoff). Descriptions are substantive (100-500 chars), explaining WHAT each tool does and WHEN to use it. All parameters have type definitions and descriptions. However, output schemas are not formally documented, responses are inferred from handler code (e.g., 'posted', 'handoff_id=...'). Error handling is minimal: toolError() is called but recovery guidance is absent. No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite 7 of 8 tools being WRITE operations. Parameter validation is basic (pattern matching for IDs, minLength/maxLength for strings) but lacks enum constraints where applicable (e.g., 'to' parameter accepts free-form strings instead of enumerating valid recipients). Composition is strong: tools are single-responsibility and chain well (send_handoff → accept_handoff/decline_handoff). Security: no secrets in parameters, but no explicit permission checks visible in tool definitions.
Accept a pending handoff addressed to you.
Acknowledge a pending interrupt addressed to you.
Withdraw a pending handoff you created. Reason optional. Only the sender (or the human) may cancel.
Decline a pending handoff addressed to you. A reason is required so the sender can re-route.
Post a free-text message to the shared chat room.
Upload a file from your local filesystem and post it as a chat message. The file's extension must match the hub's allowlist (default: jpg, jpeg, png, pdf, md). Returns the absolute filesystem path of the stored attachment (the same path recipients see via the [attachment: ...] marker) — safe to reference in a subsequent send_handoff.context.
Output schemas not formally documented. Handlers return text-only responses ('posted', 'handoff_id=...') without structured field definitions. LLMs cannot reliably extract handoff_id or file paths for downstream tool chaining.
No tool annotations despite 7 of 8 tools being destructive (WRITE operations). Missing destructiveHint and idempotentHint annotations prevent LLMs from reasoning about retry safety and side effects.
Error handling lacks recovery guidance. toolError() function called but no actionable error messages returned to LLM. E.g., HTTP 400 on send_handoff does not explain why (invalid recipient? task too long?) or what to do next.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 63 | 2026-07-28+ | v2 |
Transfer a bounded unit of work to another participant. Returns a handoff_id the recipient will accept or decline.
Send a high-visibility attention flag to another participant. The recipient's channel surfaces it prominently; they acknowledge via ack_interrupt when they've read it. Use sparingly — reserve for 'wait, re-read this before continuing' moments, not for regular chat.
'to' parameter in post, post_file, send_interrupt accepts free-form strings without enum constraint. LLMs may hallucinate invalid recipient names. Should enumerate valid recipients or document resolution logic.
No dry-run or confirmation step for irreversible operations (send_handoff, post_file). Agents cannot preview or confirm before executing. Pattern:confirmation-request recommends confirm_before_execute for destructive tools.