Date: 2026-06-02 Status: Accepted
Context
Codex subagents use explicit fan-out: a parent agent spawns specialized workers, those workers run in parallel with their own context, and the parent collects concise results instead of absorbing every intermediate log line. The pattern is valuable because it reduces context pollution and makes independent exploration, review, and test work parallel.
The 2026-06-02 OpenAI Codex docs describe the same useful shape: subagents are spawned
explicitly, run specialized workers in parallel, inherit the current sandbox policy,
and are commonly bounded with [agents] max_threads = 6 and max_depth = 1. Codex also
documents custom-agent TOML files with name, description, optional model fields,
optional sandbox_mode, and developer_instructions.
Pixir already models a conversation as a supervised Session whose Turn runs in a Task. On BEAM, spawning many supervised processes is cheap and observable, so Subagents should be a runtime primitive rather than prompt-only convention.
Decision
A Subagent is a delegated child Session created for a bounded task. It is distinct from a Skill and from a Tool: Skills add instructions, Tools expose capabilities, and Subagents are concurrent workers with their own Session, Turn, workspace, and lifecycle.
Subagents are spawned only through explicit controlled surfaces such as spawn_agent.
Pixir does not silently auto-fan-out because hidden concurrency makes cost, permissions,
and file ownership difficult to reason about.
Pixir runs Subagents under the Subagents manager, a GenServer in the application
supervision tree. The Manager starts child Sessions through Pixir.SessionSupervisor,
subscribes to their Events, monitors lifecycle, enforces max_threads, max_depth, and
per-worker timeouts, and starts queued workers when capacity frees.
Each child receives an isolated workspace snapshot under the parent workspace's ignored
.pixir/subagents/<id>/workspace directory by default. This keeps file writes from
colliding across Subagents while preserving normal Workspace confinement inside each
child. A shared workspace mode may exist for trusted workflows, but isolation is the
default.
Subagent lifecycle is canonical parent History. The parent Log records
subagent_event entries for queued/started/input/finished/failed/cancelled/timed_out
and closed states. These events carry the parent id, Subagent id, child Session id,
agent role, task, depth, status, workspace, and final summary where available.
If a later Pixir runtime can reconstruct a non-terminal Subagent from the parent Log but
no longer has a live process handle, it reports the Subagent as detached rather than
not_found; detached is an honest query-time projection, not evidence of completion.
Provider replay folds only compact terminal Subagent summaries into parent input. Detailed child logs stay in the child Session Log, so the parent can resume with the outcome without context pollution.
Pixir ships built-in agents analogous to Codex:
default: general-purpose child worker.worker: execution-focused implementation/fix worker.explorer: read-heavy evidence-gathering worker.
Custom agents are loaded from project and user roots with deterministic precedence:
project .pixir/agents, project .codex/agents, user ~/.pixir/agents, user
~/.codex/agents, then built-ins. Duplicate names produce visible warnings; selected
custom agents override lower-precedence entries and built-ins. Agent files use a small
TOML-compatible subset: name, description, developer_instructions, and optional
model, model_reasoning_effort, and sandbox_mode.
Unlike the current tool-backed Codex limitation reported in openai/codex#15250, Pixir's
tool surface resolves named custom agents directly through spawn_agent.
The model-facing v1 surface is ADR 0005-compliant Tools: spawn_agent, wait_agent,
send_input, close_agent, and list_agents. Listing and waiting are read-only.
Spawning, sending input, and closing are lifecycle mutations and therefore go through
the existing permission policy. Child agents inherit the parent's permission posture
unless their agent config narrows it to read-only.
Consequences
- Pixir can run tens or hundreds of lightweight child workers while keeping lifecycle state supervised and observable.
- Parent context remains smaller because child logs are summarized instead of replayed wholesale.
- Resume/fork can reconstruct Subagent relationships and terminal outcomes from the parent Log.
- Parallel write-heavy workflows remain safer by default because isolated child workspaces prevent accidental cross-agent file interference.
References
- OpenAI Codex docs, "Subagents": https://developers.openai.com/codex/subagents
- openai/codex#15250, custom subagents in tool-backed sessions: https://github.com/openai/codex/issues/15250