feat(orchestrator): let an orchestrator read a worker session's output

Author: thadlevinCreated Sep 18, 2026Updated Sep 19, 2026

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 N bounds 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; --json emits 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).
  • --follow over 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