Skip to content
AGH RuntimeAgents

Spawning

How AGH resolves an agent definition into an ACP subprocess, negotiates a session, injects environment, and stops the process.

Audience
Operators running durable agent work
Focus
Agents guidance shaped for scanability, day-two clarity, and operator context.

Spawning is the handoff from an AGH agent definition to a live ACP subprocess. It starts when a session is created or resumed, and it ends when the subprocess has completed ACP initialization and the AGH session becomes active.

Rendering diagram...

AGH resolves workspace and provider configuration before launching an ACP-compatible process over stdio.

Spawn inputs

The session manager builds acp.StartOpts from the resolved workspace and agent:

Start optionSource
AgentNameresolved AGENT.md name
Commandagent.command or provider command
Cwdprimary workspace root
AdditionalDirsregistered workspace additional roots
Envdaemon environment plus AGH session variables and bound provider secrets
MCPServersresolved config/provider/agent/skill MCP server list
Permissionsresolved agent or global permission mode
SystemPromptassembled startup prompt built from AGENT.md body plus runtime context
ResumeSessionIDstored ACP session ID when resuming

The ACP driver validates these before launch:

  • AgentName, Command, and Cwd are required.
  • Cwd must resolve to an existing directory.
  • Each non-empty additional dir must be absolute and resolve to an existing directory.
  • Duplicate additional dirs are removed after symlink resolution.
  • An additional dir equal to the primary workspace root is skipped.
  • Permissions must be deny-all, approve-reads, or approve-all.

Launch

AGH parses the provider command with shell-style quoting:

npx -y @agentclientprotocol/claude-agent-acp@latest

The parsed executable and arguments are launched directly, not through a shell. The subprocess runs with cwd set to the workspace root, and AGH connects JSON-RPC to the subprocess over stdio.

On Unix systems, managed ACP subprocesses start in their own process group. Stop can therefore terminate wrapper processes and their children, which matters for commands such as npx ... that start a Node wrapper before the actual ACP runtime.

Environment

The subprocess inherits the daemon environment with these AGH additions:

VariableWhen setValue
AGH_SESSION_IDevery spawned sessionAGH session ID
AGH_AGENTevery spawned sessionresolved agent name
AGH_AGENT_NAMEevery spawned sessionresolved agent name
AGH_PROVIDERevery spawned sessionresolved provider id
AGH_PROVIDER_HARNESSevery spawned sessionresolved provider harness, such as acp or pi_acp
AGH_MODELevery spawned session with a resolved modelresolved model string
PI_CODING_AGENT_DIRsessions launched through the pi_acp harnesssession-local Pi runtime directory
AGH_SESSION_CHANNELsessions created with a channelchannel name
AGH_PEER_IDsessions created with a channel<agentName>.<sessionID>
AGH_BINevery spawned session when the daemon executable can be resolvedabsolute path to the AGH binary

AGH also prepends the AGH binary directory to PATH, removing a duplicate entry if it already exists. Before setting channel values, stale AGH_SESSION_CHANNEL and AGH_PEER_ID values are cleared from the inherited environment.

Provider API keys are injected only through bound provider credential_slots. A slot maps a secret_ref into a target environment variable such as OPENROUTER_API_KEY. env:NAME refs read from the daemon environment at launch, while vault:providers/<provider>/<slot> refs read encrypted AGH-managed provider credentials written through settings. Required slots fail startup when the bound secret is missing.

For pi_acp providers, AGH also materializes a session-local Pi runtime directory containing the resolved settings.json and models.json. That directory is passed through PI_CODING_AGENT_DIR so OpenRouter, z.ai, Moonshot/Kimi, Vercel AI Gateway, and custom Pi-compatible providers can run through the same ACP adapter while still appearing as distinct AGH providers.

ACP negotiation

After the process starts, AGH sends initialize.

AGH advertises:

  • filesystem read text support
  • filesystem write text support
  • terminal support
  • client name agh
  • client version dev

The initialize response tells AGH whether the agent supports session/load.

New session

For a new session, AGH sends session/new:

{
  "cwd": "/workspace/root",
  "mcpServers": [],
  "additional_dirs": ["/workspace/other-root"]
}

additional_dirs is an AGH extension field. It is top-level snake_case because the upstream ACP SDK does not model it yet.

The response provides the ACP sessionId, supported modes, and supported models. AGH stores the ACP session ID separately from the durable AGH session ID.

Resume

For resume, AGH sends session/load:

{
  "cwd": "/workspace/root",
  "mcpServers": [],
  "additional_dirs": ["/workspace/other-root"],
  "sessionId": "provider-session-id"
}

Resume requires the agent to advertise loadSession during initialize. If it does not, startup fails with an unsupported load-session error. If the upstream runtime says the stored session no longer exists, AGH can recognize the ACP resource-not-found shape and repair resume behavior at the session layer.

Permission mode mapping

AGH applies its static permission mode to ACP session modes when the provider reports a compatible mode.

AGH permissionACP mode names AGH tries
approve-allfull-access, full_access, bypassPermissions, bypass_permissions, auto, acceptEdits
approve-readsread-only, read_only, readOnly, plan, ask
deny-allread-only, read_only, readOnly, plan, ask

If no reported mode matches, AGH skips session/set_mode and still keeps its own inbound permission policy. Filesystem permission checks use the primary workspace root as the sandbox.

Prompt startup behavior

The AGENT.md body becomes part of the startup system prompt. The current prompt path sends that startup prompt together with the first user prompt, then sends only user prompt text on later turns.

That means:

  • the body should contain durable role and operating instructions
  • per-turn details belong in the user prompt
  • changing AGENT.md affects new processes, not a process that is already running

Stop behavior

Stopping is cooperative first:

  1. Mark the process as stop-requested.
  2. Send ACP session/cancel when an ACP session ID exists.
  3. Ask the managed subprocess to shut down.
  4. Wait for process exit.
  5. Escalate through the process-tree shutdown path when needed.
  6. Close managed terminals and suppress expected wait errors for requested stops.

Failed startup uses the same cleanup path. If initialize, session/new, or session/load fails after the process was launched, AGH stops the process before returning the startup error.

Agent-Initiated Safe Spawn

An active agent can request a child session through agh spawn. This is separate from normal session creation: AGH validates the caller identity, requires a positive TTL, keeps the child inside the parent's workspace and coordination channel, denies coordinator-role children, and only permits permission subsets of the parent session.

Safe-spawn children are recorded as spawned sessions with parent/root lineage, depth, role, TTL, and permission metadata. In the MVP, max depth is 1 and the default max children per parent is 5. Parent-stop and TTL expiry cleanup release active task-run leases through the task service before stopping the child session.

Use Safe Spawn for command flags, constraints, and lifecycle hooks.

Edge cases

CaseBehavior
Command cannot be parsedStartup fails before launch.
Executable is missing from PATHStartup fails from subprocess launch.
Workspace root is missingStartup fails during Cwd normalization.
Additional dir is relativeStartup validation fails.
Additional dir is missingStartup normalization fails.
Provider omits supported modesAGH skips session/set_mode.
Provider omits default modelResolved model may be empty.
Provider lacks session/loadResume fails.
Stored ACP session is missing upstreamAGH clears the stale ACP session ID and starts a fresh ACP session for the same AGH session.
Agent requests a filesystem or terminal actionAGH evaluates the inbound permission policy before serving the request.

On this page