# Mission: Adopt A2A as Internal Agent Communication Protocol ## Metadata - **Created:** 2026-05-08 - **Status:** Proposed (not started) - **Source:** Research from 4+ model consultations + codebase analysis + cross-repo pattern study - **Plans:** `docs/plans/A2A_ADOPTION_PLAN.md`, `docs/plans/UNIFIED_DISPATCH_V2.md`, `docs/plans/dispatch-orchestration-architecture.md` --- ## Goal Consolidate SF's 5 dispatch mechanisms + MessageBus into a unified dispatch architecture using A2A as the semantic communication layer, with MessageBus as the transport. --- ## Context ### Problem SF has accumulated 5 dispatch mechanisms without a unifying abstraction: 1. **subagent tool** — inline delegation, 4 tools, no project DB 2. **parallel-orchestrator** — milestone-level parallelism, full tools, shared SQLite WAL 3. **slice-parallel-orchestrator** — same pattern at slice scope (~80% duplicate) 4. **UOK kernel** — autonomous loop controller 5. **MessageBus** — SQLite-backed durable messaging (well-implemented but not wired) 6. **Cmux** — surface integration (keep separate) ### Evidence - `parallel-orchestrator.js` + `slice-parallel-orchestrator.js` share ~80% logic - MessageBus has zero references in parallel-orchestrator (coordination via file-based IPC) - `@a2a-js/sdk@0.3.11` already in node_modules (transitive dep of `@google/gemini-cli-core`) - All 4 consulted models converged: merge the orchestrators first, wire MessageBus, keep subagent constraint ### Constraints - Must preserve existing behavior throughout migration (feature-flagged rollout) - `SF_A2A_ENABLED=0` must disable all new A2A behavior instantly - subagent isolation (4 tools, no project DB writes) is NOT changed - File-based IPC (`session-status-io.js`) stays as permanent crash-recovery fallback - DB is authoritative; A2A messages are hints --- ## Mission Tasks ### Phase 1 — A2A Type Definitions (Week 1-2) - [ ] Create `dispatch/a2a-types.ts` — A2A types + SF extensions (A2ATaskState, SFTaskExtension, MessagePriority, SFAgentCapabilities, SFAgentCard) - [ ] Create `dispatch/a2a-task.ts` — Task creation + state mapping functions - [ ] Create `dispatch/a2a-errors.ts` — DeliveryError + error codes - [ ] Run: `npx tsc --noEmit` on new types - [ ] Run: `npx vitest run dispatch/a2a-task.test.ts` ### Phase 2 — AgentRegistry (Week 2-3) - [ ] Create `dispatch/capability-registry.ts` — AgentRegistry + SF_CAPABILITY_DEFINITIONS - [ ] Create `dispatch/index.ts` — barrel exports - [ ] Wire registry into `DispatchService` (opt-in via `SF_A2A_ENABLED=1`) - [ ] Run: unit tests pass - [ ] Run: existing tests pass with `SF_A2A_ENABLED=0` ### Phase 3 — MessageBus Wiring (Week 3-4) - [ ] Create `dispatch/a2a-service.ts` — A2AMessageService wrapping MessageBus - [ ] Create `dispatch/metrics.ts` — A2A Prometheus metrics - [ ] Create `dispatch/logger.ts` — structured JSONL logging - [ ] Create `dispatch/validation.ts` — message body validation - [ ] Create `dispatch/auth.ts` — agent token generation + verification - [ ] Replace file-based IPC with MessageBus.send() for pause/resume/stop - [ ] Keep file-based IPC as crash-recovery fallback - [ ] Run: integration tests with `SF_A2A_ENABLED=1` - [ ] Run: existing tests pass with `SF_A2A_ENABLED=0` ### Phase 4 — Subagent A2A (Week 4-5) - [ ] Refactor `subagent/index.ts` to use DispatchService - [ ] Remove ~600 LOC spawn management (replaced by `dispatch.start()`) - [ ] Verify all 4 subagent modes work identically - [ ] Add optional MessageBus inbox for subagents (`useMessageBus: true`) - [ ] Run: subagent tests with `SF_A2A_ENABLED=1` ### Phase 5 — UOK Kernel A2A (Week 5-6) - [ ] Register coordinator AgentCard in `uok/kernel.ts` - [ ] Replace `startParallel`/`startSliceParallel` calls with DispatchService - [ ] Verify `sf headless autonomous` works identically - [ ] Run: integration tests with `SF_A2A_ENABLED=1` ### Phase 6 — A2A Default On (Week 6-7) - [ ] Set `SF_A2A_ENABLED=1` as default in preferences - [ ] Monitor for 1 week - [ ] Promote to stable --- ## Verification Criteria 1. `npx vitest run src/resources/extensions/sf/tests/uok-message-bus.test.mjs` passes throughout 2. `SF_A2A_ENABLED=0 npm run test:unit` passes throughout (legacy preserved) 3. Pause/resume works via MessageBus with `SF_A2A_ENABLED=1` 4. All 4 subagent modes work identically (parallel, debate, chain, single) 5. `sf headless autonomous` works with `SF_A2A_ENABLED=1` 6. Worker AgentCards visible in dashboard 7. Panic mode activates correctly (3 consecutive delivery failures → file-based fallback) 8. `sf uok messages compact` works 9. `sf dispatch agents list` shows registered agents with capabilities --- ## Key Files | File | Role | |---|---| | `src/resources/extensions/sf/uok/message-bus.js` | Existing MessageBus (transport) | | `src/resources/extensions/sf/dispatch/service.js` | DispatchService (A2A coordinator client) | | `src/resources/extensions/sf/worktree-orchestrator.js` | Worker spawner (A2A agent) | | `src/resources/extensions/sf/uok/kernel.js` | UOK kernel (A2A coordinator) | | `src/resources/extensions/subagent/index.js` | Subagent tool (A2A constrained agent) | | `docs/plans/A2A_ADOPTION_PLAN.md` | Full production-grade plan | --- ## Exit Criteria Mission is complete when: - All 6 phases are merged to main - `SF_A2A_ENABLED=1` is the default - `SF_A2A_ENABLED=0` still passes all tests (legacy preserved) - 0 P0/P1 bugs in dispatch layer for 2 consecutive weeks - A2A observability dashboard shows healthy metrics (delivery latency < 500ms p99)