A2A Test Skill
A2A (Agent-to-Agent) tests verify real runtime behavior against live LLM backends. They are interactive CLI tests using the aw CLI tool — not automated TS scripts.
Test plans
All a2a test procedures are documented as markdown:
packages/loop/test/a2a/loop-tests.md— Loop-level tests per runtime (AiSdkLoop, ClaudeCodeLoop, CodexLoop, CursorLoop)packages/agent/test/a2a/agent-tests.md— Agent-level end-to-end tests across all providerspackages/agent/test/a2a/messaging.md— Async messaging pipeline tests (batching, interleaving, state transitions)
How to run
A2A tests are run manually using the unified aw CLI (packages/agent-worker/src/cli/index.ts):
# 1. Add an agent with a specific runtime (daemon auto-starts)
aw add test-agent --runtime ai-sdk --model anthropic:claude-haiku-4-5-20251001
aw add test-agent --runtime claude-code --model sonnet
aw add test-agent --runtime codex
aw add test-agent --runtime cursor
aw add test-agent --runtime mock # test without API keys
# 3. Send messages and observe behavior
aw send test-agent "Reply with exactly: HELLO_A2A_TEST"
aw read test-agent # View responses
aw log --json # View debug events
aw state test-agent # View agent state
# 4. Clean up
aw rm test-agent # Remove agent
aw daemon stop # Stop daemon
Test flow
For each runtime, verify in order:
- Preflight — Agent added successfully (
aw add, daemon auto-starts) - Simple prompt — Send a trivial prompt, verify text response contains marker
- Event structure —
aw log --jsonentries have correct type/shape - Result structure —
run_endhas durationMs > 0, usage tracking (where supported) - Status transitions —
aw log -fshows idle → processing → idle - Cancel —
aw rmduring processing terminates cleanly - Tool calls —
tool_call_start/tool_call_endpairing (where supported)
Unit tests (separate from a2a)
Unit tests are mock-based and run with bun test:
bun test packages/loop/test/
bun test packages/agent/test/
Loop APIs under test
Each loop class exposes:
preflight()→PreflightResult— env/config checkrun(prompt)→LoopRun— streamingLoopEvent+.result: Promise<LoopResult>cancel()— abort in-flight runstatus—"idle" | "running" | "completed" | "failed" | "cancelled"
Event types
text— text outputthinking— reasoning/chain-of-thoughttool_call_start— tool invocation begins (name, callId, args)tool_call_end— tool invocation completes (name, callId, result, durationMs, error)error— error occurredunknown— unrecognized event from provider
Runtime capability matrix
| Capability | AiSdkLoop | ClaudeCodeLoop | CodexLoop | CursorLoop |
|---|---|---|---|---|
| tool_call_end | Yes | Yes | Yes | No |
| callId in events | Yes | Yes | No | Yes |
| thinking events | Yes | No | No | No |
| usage tracking | Yes | Yes | No | No |
Verdicts
When running a2a tests, record results as pass/fail/skip in the test matrix at the bottom of each markdown file.