aboutsummaryrefslogtreecommitdiff
path: root/A2A_protocol_spec.md
diff options
context:
space:
mode:
Diffstat (limited to 'A2A_protocol_spec.md')
-rw-r--r--A2A_protocol_spec.md115
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)