You are reading Nightly documentation for 0.12.6.dev0+g563af09.

This documentation may describe behavior that differs from Stable.

Open Stable documentation

Subagents and coding jobs

Subagents and coding jobs

The agent can delegate work: spawn child agent runs it supervises, and hand coding tasks to headless Claude Code or Codex CLIs — either attended (streaming into your chat) or as fire-and-forget background jobs. You watch and control all of it from the Agents tab of the web interface.

The Agents tab

Open Agents (Ctrl+5 by default) to see every delegated child run under the persistent host. For each run you can:

  • Approve or deny its parked actions — a child hitting the approval gate waits for you, exactly like an unattended run (see Autonomy and approvals).
  • Answer questions — when a child calls ask_operator, only that run pauses; siblings and the lead keep going. Runs waiting for text show the question and an answer box.
  • Steer — queue a directive for an active run. It is appended to the run's transcript as an operator directive at the next turn boundary; it never interrupts a tool call already executing.
  • Cancel the run.
  • Inspect events — drill into each run's recorded event stream.

The same controls exist from the terminal:

holaryn status                     # host + task overview
holaryn question list              # pending questions
holaryn question answer <id> "Use README.md"
holaryn steer <session-id> "Focus on the approval failure"

Child agent runs

When the lead agent runs inside holaryn serve, its delegate tool can spawn child runs (one
task or a tasks array). Each child has a session id like {parent}/sub:{n}. Default limits are
one delegation level and four concurrent children. Child approvals use the host's parked-approval
store and are labelled by child session id.

Children retain independent parent autonomy restrictions, an exact executable-tool name ceiling,
and intersected file-tool workspace limits. Choosing a different child posture cannot discard a
parent restriction. A read-only child cannot regain excluded write tools through discovery.
Plugin, MCP, extension, connector/account, command and workflow permission lists apply before child
construction. Disabled memory stays unopened. A different memory destination or loader configuration
does not silently replace the parent's selection; a fresh child instead receives no memory.
Supported process backends retain a parent's Docker requirement, bounded mount, disabled network
and output-capture limit even if the host default is local. The child receives a new backend
instance. Unknown custom backends deny child process execution instead of granting local execution.

A child keeps its parent's selected chat model instead of switching to the registry default.
Approved adaptive/fallback alternatives remain available, but new models, rebound endpoints or
credential selectors, and newly added pool members cannot silently enter its scope. Custom provider
factories need an explicit host binding and independent clients. Child clients are released on
completion, cancellation or failure.
If a nested client's shutdown fails, other owned resources are still attempted and the failure is
reported. Retrying shutdown resumes unfinished cleanup without closing successful clients again.

Canonical chat providers also preserve the parent's pool execution identity and reservation policy,
with separate attempt keys for each child. A changed file-secret destination, pool ledger, broker
binding or required authorization identity is rejected before constructing credentials. Custom
secret stores and in-memory pool ledgers need an explicit reconstruction contract before delegation.

Native providers also retain the approved API key or OAuth credential lineage. Replacing a sign-in,
changing its effective account/endpoint, or changing a key requires a fresh run. Normal native OAuth
refresh preserves that lineage, including across provider reconstruction; a late refresh cannot
overwrite a concurrent sign-in or sign-out. Private lineage records share the secret store's existing
encryption and filesystem protections. They do not attest remote account ownership or protect a
plaintext store from someone who can rewrite it.

Prompt-cache planning retains the parent's privacy boundary with a separate child cache key. A
child can use the authorized metadata store or narrow to private memory; it cannot select a foreign
store or borrow a parent/peer key. Missing or changed cache evidence requires a fresh child, as do
changes to its authorization privacy scope or session epoch. These local checks do not attest a
remote provider's caching or retention behavior.

After a restart, reopen the owning parent before resuming a scoped child. Recovery intersects the
saved restrictions with that current parent; it does not restore an approval grant. A changed
profile, owning workspace, or unavailable exact skill source can require a fresh run. Missing
construction-permission evidence or a revoked integration/memory permission requires a new child,
because an old transcript can already contain data disclosed under those permissions.
Missing or revoked backend evidence also requires a fresh child; relaxing a parent does not remove
a saved child's container restriction.
Missing or revoked chat-provider evidence also requires a fresh child; saved transcripts are not
silently replayed under a changed model/connection definition.
Missing or changed provider execution snapshots likewise require a fresh child; recovery does not
infer credential sources from new host defaults.

Skills 2.0 inheritance remains in progress: exact integration identity, hook safety floors, complete
connector resource and memory namespace isolation, broker credential-version/revocation enforcement,
custom secret-store contracts, auxiliary model-call paths and aggregate-budget inheritance,
complete backend adapter coverage, and live revocation during a running child are not yet implemented.
The file-tool sandbox is not OS
isolation for arbitrary shell code. See the
current policy boundaries before relying on delegation for isolation.

Coding delegation: delegate_coding_task

The agent can conduct Claude Code and OpenAI Codex as subordinate coding agents. Tell it something like "write this code in D:\projects\photo-tools — use Claude Code" and it hands the task to the headless CLI, streams the coder's progress live into your chat, and reports back with the result and a session id for follow-up rounds. The agent's own model is the dispatcher; the coding CLI burns its own subscription or API usage.

Setup

Install and sign in to each CLI separately, on the machine running Holaryn:

Backend Install Sign in
claude-code npm install -g @anthropic-ai/claude-code claude login (or ANTHROPIC_API_KEY)
codex npm install -g @openai/codex codex login

In Settings → Configuration, pick the default Coding agent (HOLARYN_CODING_AGENT) and, if the CLIs are not on PATH, set the Claude Code CLI path / Codex CLI path (HOLARYN_CLAUDE_BIN / HOLARYN_CODEX_BIN). The tool is always registered; if the CLI is missing you get an error with install instructions, not a silent failure.

Using it

  • "Delegate to Claude Code: add input validation to the signup form. Work in D:\apps\web."
  • "Use codex for this: profile the slow test and fix it."
  • Every result includes session: <id> — say "tell it to also add tests" and the same coding session continues with full context.

Permissions

Two gates stack. First, delegate_coding_task is irreversible (category coding.delegate), so it is ask-first at the default posture. Second, the permission_level argument maps onto the child CLI's own permission system:

permission_level Claude Code Codex
safe default (a needed permission aborts) read-only
edits (default) acceptEdits workspace-write
full bypassPermissions danger-full-access

full disables the child's own gate, so it is only allowed under the unrestricted posture in an attended session. Delegations default to 900 seconds (max 3600); on timeout the whole child process tree is killed.

Background coding jobs

Under holaryn serve, extra tools turn delegation into fire-and-forget:

  • start_coding_task — same arguments as delegate_coding_task, but returns a job id (cj_...) immediately. When the job finishes, a notice is posted back to the chat that started it (web chats get a live bubble or a stored notice; Telegram-origin jobs get a bot message). permission_level: full is never allowed here — background jobs are unattended by definition.
  • check_coding_job — status, progress tail, and result for one job or a list of recent jobs. Always the source of truth for a job's outcome.
  • steer_coding_job — redirect a running claude-code job mid-run (see Steering a running job).

Steering a running job

A running claude-code job can be redirected without cancelling it: the steering message is delivered to the coder as its next instruction, with the session's full context. The coder's current step may finish first; each delivered steer shows up as a steer: … line in the job's progress.

Three ways to steer:

  • The steer_coding_job tool (ask-first at the default posture, same as starting a job).
  • The web Agents page → Coding jobs card's Steer… action (shown only on steerable jobs).
  • The CLI: holaryn coding-jobs steer <cj_id> "skip the refactor, just fix the test".

Codex jobs cannot be steered — the Codex CLI accepts no mid-run input. Use the cancel-and-resume recipe instead: cancel_coding_job, then start a new job with session_id set to the cancelled job's child session and the corrected instructions.

Cancelling jobs

Three ways to cancel a running job:

  • The cancel_coding_job tool (ask-first at the default posture — uncommitted work may be lost). The child session id survives, so a follow-up job can resume where the coder left off.
  • The web Agents page → Coding jobs section — one card per job with status and progress, and a confirm-gated Cancel on running jobs.
  • The CLI:
holaryn coding-jobs list             # recent jobs, straight from the state dir
holaryn coding-jobs steer <cj_id> "<message>"   # redirect a running claude-code job
holaryn coding-jobs cancel <cj_id>   # cancels through the running host

The JSON API mirrors these: GET /api/operator/coding-jobs, POST /api/operator/coding-jobs/steer, and POST /api/operator/coding-jobs/cancel.

Concurrency

At most Max concurrent coding jobs run at a time (HOLARYN_CODING_MAX_CONCURRENT, default 2, applied on host restart); further jobs queue.

Mutating background jobs default to a unique, durable isolated Git worktree; safe jobs default
to read_only. The start result and completion notice include the retained worktree_id. Review
and integrate it with the Code Workspace panel or holaryn worktree; a successful coding job
does not silently merge or delete its checkout. Advanced callers can select current, existing,
or read_only, resume a retained worktree_id, set a target branch, or provide explicit named
repository-root mappings. See Isolated coding worktrees.

Restarts

The host cannot reattach a headless CLI that was running when it stopped — such jobs are marked orphaned, but the record keeps the child session id so you can continue with session_id=... in a new job.

Recurring coding jobs can be scheduled — see Scheduler and automation.

  • Agent Teams — named agents collaborating over a durable bus, including coding-CLI team members.
  • Autonomy and approvals — how the approval gate applies to delegated work.