diff options
Diffstat (limited to 'A2A_protocol_spec.md')
| -rw-r--r-- | A2A_protocol_spec.md | 115 |
1 files changed, 62 insertions, 53 deletions
diff --git a/A2A_protocol_spec.md b/A2A_protocol_spec.md index bb3d713..3c4d7ac 100644 --- a/A2A_protocol_spec.md +++ b/A2A_protocol_spec.md @@ -1,69 +1,78 @@ -# A2A Protocol Specification v0.2 +# A2A Protocol Specification v0.3 ## Overview -Agent-to-Agent (A2A) is a decentralized message protocol for agent negotiation within newOS4. Agents discover each other via VFS registrations and communicate through a VFS mailbox system. No central broker. +Agent-to-Agent (A2A) is a decentralized message protocol for agent negotiation within newOS4. Agents communicate through a **shared VFS scratchpad** (`/_agents/scratchpad.json`). No central broker — discovery is via VFS registrations. -## Message Format -All messages are JSON with this envelope: +## Scratchpad Data Structure + +All messages live in a single JSON file at `/_agents/scratchpad.json`: ```json { - "a2a_version": "0.1", - "msg_id": "<uuid>", - "type": "request" | "response" | "broadcast" | "lease" | "heartbeat", - "from": "<agent_id>", - "to": "<agent_id>" | "*", - "timestamp": "<ISO 8601>", - "ttl_seconds": 30, - "contract": { - "capabilities": ["list_files", "read_file", "web_search"], - "constraints": { - "max_tool_turns": 8, - "max_duration_seconds": 60 + "messages": [ + { + "id": "msg_001", + "from": "user", + "to": "researcher", + "type": "request", + "capability": "code.search", + "payload": { "query": "test" }, + "ttl": 300000, + "status": "pending", + "ts": 1234567890, + "reply_to": null + } + ], + "seq": 1, + "agents": { + "researcher": { + "last_poll": 1234567890, + "capabilities": ["coder", "reader", "writer"] } - }, - "payload": { } + } } ``` -## Transport Layer (VFS Mailbox) -Each agent has a VFS mailbox: -- **Inbox** — `/agents/<agent_id>/inbox.json` — receives incoming A2A messages -- **Outbox** — `/agents/<agent_id>/outbox.json` — agent writes results here after execution - -The orchestrator polls all agent inboxes every **500ms** via `_pollAgentMailboxes()`. When a new A2A message appears, it: -1. Reads the message envelope -2. Routes by type: - - `request` — task delegation, checks outbox for completion - - `response` — task result from agent - - `broadcast` — capability advertisement - - `heartbeat` — updates agent's lastHeartbeat timestamp -3. Marks messages as `_processed` to avoid re-routing - -## Message Types -- **request**: Point-to-point task delegation. From=orchestrator, To=worker. -- **response**: Task result. From=worker, To=orchestrator. -- **broadcast**: Discovery / capability advertisement. To="*". -- **lease**: Time-bound contract granting a worker exclusive task rights. -- **heartbeat**: Alive signal. Every 5 seconds. Missing 3 consecutive = presumed dead. +### Message Statuses +| Status | Meaning | +|---|---| +| `pending` | Not yet delivered | +| `delivered` | Read by recipient via poll | +| `completed` | Acknowledged with result | +| `failed` | Rejected with error | ## Commands -- `a2a-send <agent-id> <json-message>` — Send an A2A message to an agent's inbox -- `a2a-list` — Show all A2A messages across agents with status + +| Command | Description | +|---|---| +| `a2a-post <to> <type> <capability> <payload...>` | Post a message to an agent | +| `a2a-poll [agentId]` | Poll for pending messages (default: current agent or "user") | +| `a2a-ack <msgId> <result...>` | Mark message completed with result | +| `a2a-reject <msgId> <error...>` | Mark message failed with error | +| `a2a-status` | Show scratchpad stats per agent | +| `a2a-prune` | Clean up expired and old completed messages | ## Lifecycle -1. Orchestrator sends `request` to agent's inbox via `a2a-send` -2. AI module receives delegated task, executes it -3. Result written to agent's outbox -4. Polling loop detects outbox completion, sends `response` message -5. Orchestrator marks lease as complete, agent returns to idle pool + +1. **Register** — `agent-register <name> <capabilities>` creates agent dir + auto-registers in scratchpad +2. **Post** — `a2a-post <to> <type> <capability> <payload>` writes to scratchpad with `status: pending` +3. **Poll** — `a2a-poll <agentId>` returns pending messages, marks them `delivered` +4. **Ack/Reject** — Recipient acknowledges with result or rejects with error +5. **Unregister** — `agent-unregister <id>` removes agent from scratchpad + deletes VFS dir +6. **Auto-prune** — Every 60 seconds, expired messages (past TTL) and completed messages older than 1 hour are removed + +## Integration Points + +- **Orchestrator** — auto-calls `a2aRegister` on agent spawn, `a2aUnregister` on kill +- **Lease system** — posts A2A messages on lease create and lease revoke +- **Garbage collection** — `_a2aCleanup()` removes orphaned agent entries when agent dirs are deleted ## Implementation Status -- ✅ Message format (v0.1 envelope) -- ✅ VFS mailbox transport (inbox.json / outbox.json) -- ✅ 500ms polling loop in orchestrator -- ✅ Type routing (request, response, broadcast, heartbeat) -- ✅ a2a-send / a2a-list CLI commands -- ⬜ Heartbeat sending from worker agents -- ⬜ Full broadcast discovery flow -- ⬜ Lease revocation via A2A message (currently uses separate LeaseModule)
\ No newline at end of file +- ✅ Scratchpad data structure (/_agents/scratchpad.json) +- ✅ a2a-post / a2a-poll / a2a-ack / a2a-reject / a2a-status / a2a-prune CLI commands +- ✅ Auto-register on agent spawn +- ✅ Auto-unregister on agent kill +- ✅ A2A messages on lease create/revoke +- ✅ Auto-prune timer (60s interval) +- ✅ Garbage collection for orphaned agent entries +- ✅ Security whitelist (all A2A commands whitelisted, not destructive) |