feat(orchestrator): let an orchestrator read a worker session's output
Problem
An orchestrator can spawn workers and message them, but it cannot see what they produced. ao orchestrator implements only ls (backend/internal/cli/orchestrator.go), and no CLI path reaches a worker's conversation. When a worker stalls, contradicts itself, or reports a success the orchestrator cannot verify, the only recourse is ao send asking the worker to describe its own state — the source already in doubt, and it fails exactly when the worker is confused. In practice the orchestrator either respawns work that was fine or relays an unverified claim to the human.
The data already exists server-side: GET /api/v1/sessions/{sessionId}/conversation returns a snapshot built from ConversationTurnResponse / ConversationMessageResponse, alongside the SSE stream and terminal mux. The gap is consumption, not capture.
This affects orchestrator-driven fleets, CI/review follow-up routing, and headless/API consumers that have no desktop UI to read.
Proposed contract
- Add
ao session output <session-id>reading the existing session conversation snapshot; no new capture path. --tail Nbounds how many recent turns are returned, defaulting to a small number. Pull with an explicit bound is deliberate: the orchestrator decides how much enters its context, so worker output cannot flood it unrequested.- Default rendering is the recent assistant and tool turns in readable form;
--jsonemits the structured turns for programmatic use, matching existing CLI JSON conventions. - Reuse the existing conversation route and service operation as the single implementation; no orchestrator-specific server path.
- Preserve daemon error envelopes and request IDs, and return the standard not-found envelope for an unknown session id.
- No DTO change expected. If a harness turns out not to populate the snapshot fields the command needs, that is reported before extending
dto.go, since it pulls in OpenAPI/TS regeneration (npm run api). --followover the existing SSE stream is explicitly out of scope here and remains possible later.
Verification
Cover CLI happy path, --tail bounding and --json shape against a fake daemon; unknown-session and daemon-error envelope propagation; and one end-to-end check that the command returns real turns from a live session, since the main risk is the snapshot-payload assumption rather than command logic.
Happy to implement this if maintainers agree on the shape.
Source: Untrivial-ai/agent-orchestrator