Skip to content

feat: Add Codex subagent (CollabAgent) support #40

@OpenSource03

Description

@OpenSource03

Summary

Add support for Codex subagents (CollabAgent system) in Harnss, bringing feature parity with how we already handle Claude subagents via the Task tool.

Codex CLI and the Codex Desktop app support multi-agent orchestration through collabAgentToolCall items — spawning parallel subagents, routing instructions between threads, waiting for results, and closing threads. Harnss already has the protocol types generated but doesn't process or render these events.

Background: How Codex Subagents Work

The Codex app-server protocol supports a CollabAgent system with five operations:

Tool Purpose
spawnAgent Creates a new subagent thread with a prompt
sendInput Routes follow-up instructions to an active agent thread
resumeAgent Reopens a paused/completed agent
wait (wait_agent) Synchronizes — blocks until agent(s) finish
closeAgent Terminates a finished agent thread

Each collabAgentToolCall item includes:

  • senderThreadId — the parent thread that spawned/messaged the agent
  • receiverThreadIds — the target thread(s)
  • prompt — the instruction sent
  • agentsStates — a map of agent nicknames → { status, message } tracking lifecycle
  • status — overall call status (inProgress | completed | failed)

Subagent threads are identified by sourceKind: "subAgentThreadSpawn" and carry metadata like agent_nickname, agent_role, and depth via the SubAgentSource type.

Configuration (Codex CLI)

  • max_threads: Max concurrent open threads (default: 6)
  • max_depth: Nesting depth (default: 1 — child can't spawn grandchildren)
  • Custom agent files define name, description, developer_instructions + optional model/sandbox overrides
  • spawn_agents_on_csv: Batch fan-out for processing rows in parallel

What We Already Have

Protocol types (fully generated)

  • shared/types/codex-protocol/v2/ThreadItem.tscollabAgentToolCall item type
  • shared/types/codex-protocol/v2/CollabAgentTool.ts"spawnAgent" | "sendInput" | "resumeAgent" | "wait" | "closeAgent"
  • shared/types/codex-protocol/v2/CollabAgentStatus.ts"pendingInit" | "running" | "completed" | "errored" | "shutdown" | "notFound"
  • shared/types/codex-protocol/v2/CollabAgentState.ts{ status, message }
  • shared/types/codex-protocol/v2/CollabAgentToolCallStatus.ts"inProgress" | "completed" | "failed"
  • shared/types/codex-protocol/SubAgentSource.ts — spawn metadata (parent_thread_id, depth, agent_nickname, agent_role)
  • shared/types/codex-protocol/CollabAgentSpawnBeginEvent.ts / CollabAgentSpawnEndEvent.ts

Claude subagent infrastructure (reference implementation)

  • parentToolMap (Map<parentToolId, msgId>) for routing child events to parent Task messages
  • SubagentToolStep type with toolName, toolInput, toolResult, toolUseId, toolError
  • handleSubagentEvent() in useClaude.ts — processes assistant + tool_result events from subagents
  • background-claude-handler.ts — mirrors subagent routing for background sessions
  • TaskTool.tsx — rich collapsible UI card with live step count, duration, prompt, and step list

Shared infrastructure

  • BackgroundSessionStore.InternalState.parentToolMap — already shared across all engines
  • codex-adapter.ts — translates Codex items to UIMessage tool calls (extensible)

What Needs to Be Built

1. Event Handling in useCodex.ts

Handle collabAgentToolCall items in the Codex event loop:

  • item/started with type: "collabAgentToolCall":

    • Create a tool_call UIMessage for the collab operation
    • Register itemId → msgId in parentToolMap for spawnAgent calls
    • Track agent nicknames and lifecycle states from agentsStates
  • item/completed with type: "collabAgentToolCall":

    • Finalize the tool message with result/status
    • For spawnAgent: mark with subagentStatus: "completed" when the spawned thread finishes
    • Update agentsStates to reflect final CollabAgentStatus
  • Subagent thread events: Items from spawned threads should be routed to the parent spawnAgent message as subagentSteps[], similar to how Claude routes via parent_tool_use_id

2. Background Handler (background-codex-handler.ts)

Mirror the active session handling for background sessions:

  • Process collabAgentToolCall items in handleCodexBackgroundEvent()
  • Maintain parentToolMap entries for spawn operations
  • Accumulate subagentSteps on the parent message

3. Codex Adapter (codex-adapter.ts)

Add collabAgentToolCall → UIMessage mapping:

  • Map tool operations to display names (e.g., spawnAgent → "Spawn Agent", wait → "Wait for Agent")
  • Extract prompt, agent nicknames, and states for tool input display
  • Format final agentsStates map as the tool result

4. UI Rendering

Create a CodexSubagentTool renderer (or extend TaskTool.tsx) to display:

  • Agent nickname and role
  • Operation type (spawnAgent / sendInput / wait / closeAgent)
  • Live agent status badges (pendingInitrunningcompleted / errored)
  • Nested subagent steps (reusing SubagentStepRow pattern)
  • Multi-agent state dashboard when multiple agents are tracked in agentsStates
  • Prompt text (collapsible for long prompts)
  • Duration tracking

5. Sidebar / Session Indicators

  • Show active subagent count on Codex sessions in the sidebar
  • Visual indicator when subagents are running (spinner/badge)

Implementation Notes

  • The collabAgentToolCall item has a different shape from Claude's parent_tool_use_id routing — Codex uses explicit senderThreadId / receiverThreadIds instead. The adapter layer needs to bridge this to the existing parentToolMap pattern.
  • Multiple agents can run in parallel (up to max_threads: 6), so the UI should handle concurrent subagent cards gracefully.
  • Agent nicknames (from SubAgentSource.thread_spawn.agent_nickname) should be displayed prominently — Codex CLI uses these instead of opaque thread IDs.
  • The wait tool is a synchronization primitive — it should render as a "Waiting for agents..." state rather than a tool execution.

References

Metadata

Metadata

Assignees

Labels

area: codexCodex / OpenAI enginearea: uiUI, layout, and visual designenhancementNew feature or request

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions