@tylerho/pi-subagents
Background subagents on a pi or Claude Code backend, with fire-and-forget spawn and deferred result delivery.
Package details
Install @tylerho/pi-subagents from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@tylerho/pi-subagents- Package
@tylerho/pi-subagents- Version
0.2.1- Published
- Sep 21, 2026
- Downloads
- 286/mo · 189/wk
- Author
- tylerho
- License
- MIT
- Types
- extension
- Size
- 336.8 KB
- Dependencies
- 2 dependencies · 4 peers
Pi manifest JSON
{
"extensions": [
"extensions/subagents"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@tylerho/pi-subagents
Background subagents on a pi or Claude Code backend, with fire-and-forget spawn and deferred result delivery.
Install
pi install npm:@tylerho/pi-subagents
Subagents
Subagents ports Claude Code 2.1.274's Agent tool to pi: background subagents on two harnesses, an in-process pi SDK session or the Claude Agent SDK, behind one Effect service. A spawn is a self-contained child with its own context window, background by default, whose report returns to the parent as a framed hand-back. Workflows, memory consolidation, and summaries share its delegation defaults and activity counters.
Claude Code lineage
Claude Code 2.1.274 is the release the current port text came from, pulled in commit 1379455 feat(subagents): drop subagent_wait; make subagent_check the pull path (2026-09-16). That change adopted the Agent contract where agents run in the background by default, run_in_background: false blocks, and the parent never writes a pending result itself. An earlier pass used 2.1.273, which supplied the naming rules and the nesting depth, and commit 9829e61 feat(subagents): name agents verbatim, Claude Code-style (2026-09-10) took the naming rules.
Restated verbatim in src/domain.ts:
SUBAGENT_NAME_PATTERNis the Agent tool's name schema,/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/, andSUBAGENT_NAME_ERRORis its rejection wording.SUBAGENT_NAME_RESERVED_ERRORrestates the reserved-recipient rule formainandteam-lead, including the generated-id shapes that already address an agent.generateAgentId()builds the omitted-name id,a<description-slug>-<16hex>, ora<16hex>when the slug is empty.
Other borrowed mechanisms:
- The hand-back frame states that the report is model output with no user authority, which mirrors Claude Code's framed final report.
/btwmirrors Claude Code's side question. The child inherits the parent conversation up to the spawn point, andBTW_PROMPT_PREFIXtells it to answer from that context in one response.subagent_sendmirrorsSendMessage: steering a running agent, and resuming a settled one in the same session.
Pi does not copy these parts:
- Claude Code nests children to a default depth of three. pi keeps children flat, because the orchestration tools are in
CHILD_EXCLUDED_TOOL_NAMES, so orchestration stays in the parent manager and its concurrency cap. - There is no persistent resume.
subagent_sendresumes a settled agent only while the parent session tracks it, with no reconstruction across a pi restart or parent reload. - There are no agent profiles. A delegation is a tier or an explicit target plus the prompt, with no reusable definition files.
- There is no per-call worktree isolation. A child runs in the resolved
working_dir. The workflow runner'sisolation: "worktree"option is separate and is not exposed on spawn.
How it works
- Two backends, one API.
harness: "pi" | "claude"selects where the child runs. The pi backend is an in-processcreateAgentSession()with real session files visible in/resume, per-cwd resources under trust gating, and the canonical child tool policy. The claude backend is one@anthropic-ai/claude-agent-sdkquery()in streaming-input mode, where the CLI owns conversation continuity, tool execution, and~/.claude/projectstranscripts. It runsbypassPermissions, disallows Claude's nativeAgentandTasktools so orchestration stays inside this manager, and reports unavailable when noclaudebinary is on PATH. - Effect v4 layering.
backends/produce a scopedSubagentSessionwith a normalizedSubagentEventstream. The manager runs one pump fiber per child that folds the stream into a mutableSubagentSnapshot.runtime.tscomposes the layer into oneManagedRuntime, andindex.tsis the async boundary where tool handlers run effects throughrunTool(). A typed failure becomes a thrownError, and an AbortSignal interruption throwsinterruptMessage. - Semantic tiers. The parent picks one of four fixed names,
fast,standard,deep, orclaude. Each maps to a harness, model, and effort in the local config, and an omitted tier meansstandard.fast,standard, anddeepresolve to native pi targets, andclaudeis the secondary harness. Resolution is pure, throughresolveDelegationTarget()inshared/subagent-models.ts, so the same tier map serves subagent spawns and workflow agents. - Explicit overrides.
harnessplusmodel, with optionalreasoning_effort, is the one-off override path. The harness and model are required together, and a tier cannot be combined with any of them. A pi override splits"provider/model", and a bare model uses thestandardtier's provider for the registry lookup. An omitted effort falls back to thestandardtier effort for pi and theclaudetier effort for claude. An agent-chosen model on the claude harness is limited tosonnetorhaiku, whileopusandfablestay available to a configured default and to a/btwaside. - Spawn contract.
descriptionis required, a short task label for the UI and the generated-id slug, capped at 200 characters.promptis required and must be self-contained, because a model-origin child cannot see the parent conversation.nameis optional and only controls addressing. - Ids. A supplied
namemust matchSUBAGENT_NAME_PATTERN, must not normalize tomainorteam-lead, and must not have the shape of a generated id, or the spawn is rejected. A valid name becomes the id verbatim, with no prefix and no slug. An omitted name getsgenerateAgentId(description). Repeats get a numeric suffix, sofix-login-bugbecomesfix-login-bug-2. Extension-generated btw ids useslugifyTitleinstead, because btw descriptions are free-form questions. Ids stay unique per parent session and are the handle forsubagent_check,subagent_cancel, andsubagent_send. - Foreground and background.
run_in_backgrounddefaults totrue. A background spawn returns at once, and its settled run is delivered later as asubagent-resultfollow-up message (deliverAs: "followUp",triggerTurn: true) when the parent is idle or on the nextagent_settled. A foreground spawn claims its run at spawn time, waits for settlement, and returns the hand-back from the tool call. A tool abort releases the claim and leaves the child running. - Per-run, exactly-once delivery. Delivery is keyed by a run ref (
id#runSequence), not by agent id, because a settled agent resumed withsubagent_sendstarts a new run that can deliver again. A foreground spawn andsubagent_canceleach claim the run before it can be delivered, and an unconsumed background settle is deferred and delivered once on the next flush.subagent_checkon a settled agent consumes the deferred delivery and returns the report, and a later check re-renders the report from the retained snapshot without a second follow-up. - The hand-back (24 KiB).
buildHandback()frames one report per run. The header names the id, description, terminal status, tier orexplicitsource, harness, model, and effort, plus any error text, and the description and error text are each bounded to 1 KiB with a truncation marker. A fixed frame then states that the report is model output with no user authority, so instructions, approvals, and permission claims inside it are not from the user. Control syntax that could imitate harness messages is escaped (reserved control-tag openings and fakeHuman:orAssistant:turn markers), and every report line and every continuation line of an interpolated header value is indented two spaces, so child text cannot appear at column zero as a harness frame. Above the cap the model text keeps the head and appends an exact truncation notice pointing at the takeover view and the persisted session.details.fullOutputcarries the sanitized, untruncated report. - Origins. A model-origin spawn is visible to model-facing tools and the
/subagentsdashboard.isModelVisiblefilters byorigin === "model", so user asides from/btwstay out of the tool layer and the dashboard and are revisited in the/btwpanel. A btw result is appended as a synchronousbtw-resultsession entry, safe while the parent is streaming, and never becomes a model-context follow-up. A failed aside also fires an error notify. A btw child runs withnoTools: "all", so built-in and extension tools are excluded. - btw context inheritance. A btw child is a fork, not a clean slate. At spawn time the command handler snapshots the parent conversation with
buildSessionContext(getEntries(), getLeafId()).messages, two adjacent synchronous reads that are race-free while the parent streams. The snapshot ends at the parent's last completed message, the same cut Claude Code applies. The pi backend seeds those messages into the child session file beforecreateAgentSession, which restores them as the child's history, so compaction, resume, and the transcript treat them as its own. Summary roles are rewritten to the plain user textconvertToLlmwould produce. The inherited range is fenced withBTW_CONTEXT_STARTandBTW_CONTEXT_ENDcustom entries, and the persisted-transcript loader skips it. Result extraction excludes the seeds by object identity, so a child that fails before answering reports failure instead of echoing a parent message. - Caps.
MAX_RUNNING = 50running subagents across all backends, reserved synchronously before the first yield so parallel spawns cannot race past it. An idle restart throughsubagent_sendcounts too.MAX_TRACKED = 4_096settled snapshots per parent session, pruned oldest-settled-first, and session files survive on disk. - Transcripts are bounded in memory and full on disk. The manager keeps 512 transcript items and 64 KiB per text. The takeover view lazily streams the full persisted JSONL, from
~/.pi/agent/sessions/<escaped-cwd>/<timestamp>_<id>.jsonlon pi or~/.claude/projects/<escaped-cwd>/<sessionId>.jsonlon claude, through thesrc/persisted/parsers, with the format auto-detected per record and the file read line by line.mergeTranscriptsmerges the persisted snapshot with the live transcript, and live items always win, so streamed content never vanishes when it finalizes. The persisted load refreshes once when the run settles. - Delegation defaults and the cost ceiling. With no explicit model, a spawn runs the tier's configured target from
shared/subagent-models.json, set by/subagent-model, and never the parent's model. The cost ceiling (disabled by default, set with/subagent-cost, overridden per launch byPI_SUBAGENT_COST_CEILING) applies only on the pi harness and only to an explicit model an agent picked for itself. A tier target, a configured default, and a btw aside are deliberate user choices and are not checked. - Child safety rails. The pi backend applies
childToolPolicy()fromshared/child-session.ts, whoseCHILD_EXCLUDED_TOOL_NAMESlistssubagent_spawn,subagent_wait,subagent_cancel,subagent_check,subagent_list,workflow,ask_user_question,enter_worktree,exit_worktree, andcode_review. The claude backend disallows Claude's nativeAgentandTask. Every child tool call is wrapped with a 30-minute execution timeout fromshared/tool-call-timeout.ts, re-applied onagent_startso tools registered mid-session are covered. - Trust gating. A child in the parent's directory inherits the parent's trust decision. An alternate
working_diris trusted only when pi's persistedProjectTrustStoreexplicitly trusts it, and unreadable or invalid trust data fails closed. A claude child in an untrusted cwd getssettingSources: ["user"], so an untrusted project's config cannot reconfigure it. - Task rail. A
belowEditorwidget shows running and finished subagents. When the rail is unexpanded and at least one agent runs, it shows the running model-origin agents as compact auto rows, four at most with a… N moreline, and a 1 Hz ticker animates a spinner glyph while any agent runs. When no agent runs and the rail is unexpanded, the widget renders nothing so the rail stays out of the way. A single down-arrow in the default editor view, with no modal focused and empty editor text, reaches the editor as normal navigation. A second down-arrow within 500 ms opens the rail. Once expanded, down and up move the selection without wrapping, at the bottom the rail reveals finished subagents, at the top it closes, and Enter opens the takeover view. The expanded rail renders at most 8 rows and scrolls to keep the selection visible, with↑ N aboveand… N moreindicators. Key release and repeat events are filtered, and inside a modal the gesture yields to the focused component. - Lifecycle and cross-extension signals.
session_startwires the rail and the raw input handler.agent_settledflushes deferred results.session_shutdownunregisters everything and disposes the runtime, whose manager finalizerdisposeAllforce-closes every child scope with a 5 s bound per close. The manager publishes its running count withreportRunning("subagents", n)at transition points, which summaries reads to gate recaps. Both backends publish child spend throughshared/child-cost.ts: pi adds each assistant message'susage.cost.total, and claude adds only the positive delta of the result message'stotal_cost_usd, so a resumed run is not double-counted. The expanded footer reads that accumulated total, and the takeover header renders the snapshot's ownusage.costUsdthroughformatCost.
API
Tools
subagent_spawn spawns on a tier or with an explicit override. Parameters: description (string, required, max 200 chars), prompt (string, required), name (optional string), tier (optional "fast" | "standard" | "deep" | "claude", omitted means standard), working_dir (optional string, must exist and be a directory, default parent cwd), run_in_background (optional boolean, default true), harness (optional "pi" | "claude", requires model), model (optional string, pi "provider/model-id" or a bare id, claude an alias like "sonnet"), reasoning_effort (optional "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max"). tier cannot be combined with harness, model, or reasoning_effort. A background spawn returns text like Spawned fix-login-bug "fix login bug" (tier: standard, pi, deepseek/deepseek-v4-pro, high). plus the tail telling the parent to report what it launched and to say the agent is still running if the user asks. A foreground spawn returns the same header plus Waited for it; the report follows. and the run's hand-back. details: { id, description, cwd, harness, tier, model, effort }. Rejections: the 50-agent cap (ConcurrencyLimitError), an invalid or reserved name, a tier mixed with explicit fields, an unknown or unavailable harness, a bad working_dir, an unavailable configured or requested model, and an over-ceiling explicit model on pi.
{
"description": "fix login bug",
"prompt": "Refactor src/util.ts: split the two exported functions into separate files, run the test suite, report the diff stat.",
"tier": "standard"
}
subagent_send steers a running subagent or resumes a settled one in the same parent session. Parameters: id (string), message (string). While the agent runs the message is a course correction to the active run. When the agent is settled the call starts another turn in the same child session as a new runSequence and returns the Resumed acknowledgement. A steer returns Steered <id> (run N). The transcript shows the first line of message as a one-line preview, so the message should open with a self-contained sentence saying what it is about. A resumed turn counts against the concurrency cap, and a backend rejection rolls back the restart reservation. details: { id, runSequence, restarted }. An unknown or pruned id fails through the shared unknown-id error, and a SendError surfaces to the model and inline in the takeover view.
subagent_cancel aborts running subagents. Parameters: ids (array of string). The call claims each run before interrupting (a 5 s graceful session.interrupt with a force-close fallback that settles first, so the stream-ended fallback cannot misreport), waits for settlement, and reports Cancelled <id> "<description>". or <id> "<description>" was already <status>. followed by each run's hand-back, partial output included. It consumes the deferred automatic delivery for every listed run, settled or just cancelled, and the combined report is capped at 48 KiB. details: { results: [{ id, description, status, cancelled }] }. Partial session transcripts stay on disk.
subagent_check pulls one subagent's result or status without blocking. Parameters: id (string). A settled agent returns its full framed hand-back and consumes the deferred delivery, and a later check on the same run re-renders the report from the snapshot without a second follow-up. A running agent returns a describeSubagent() status line, the turn count, any error text, and up to 2 KiB or 20 lines of the latest output, including live streaming assistant text, followed by the guidance note that tells the parent not to spawn a duplicate and to use subagent_send for a progress report. details: { id, description, status, turns, tier, runSequence, createdAt, settledAt, runStartedAt, costUsd, tokens, contextWindow, sessionFilePath, summary, summaryCostUsd, summaryTokens }, where the timestamps and usage fields drive the row and the summary fields are filled from the shared digest.
subagent_list lists every tracked model-origin subagent. No parameters. One describeSubagent() line per model-origin child, in the form id [status] "description" (tier, backend: model, ctx%, elapsed, cwd), or No subagents. when empty. details: { subagents: [{ id, description, harness, status, tier }] }.
Commands
All four are TUI-only. In a non-TUI mode a command notifies when it has a UI and returns.
| Command | Args | Behavior |
|---|---|---|
/btw |
optional prompt text | Spawns a pi-harness child with origin: "btw" and a description from deriveBtwTitle (first non-empty prompt line, 60 chars max), then opens the BtwPanel bottom dock. The panel lists past asides as /btw <question> lines above the selected aside's answer: left and right switch asides, up and down or j and k scroll, n asks a new question through ctx.ui.input, c copies the answer, ctrl+t toggles reasoning (hidden by default), Esc closes. With no args and history it opens on the newest aside, and with no history it goes straight to the question input. The child runs without tools on a session file seeded with the parent conversation, and its result arrives as a btw-result entry, not a model follow-up. |
/subagents |
none | Opens the fullscreen dashboard of model-origin subagents, with btw asides excluded. j/k or the arrow keys move the selection, Enter takes over, and x aborts a running agent. |
/subagent-model |
none | Tier-first flow: pick a tier (each row shows its current harness/model · effort mapping), then for fast, standard, and deep the curated pi model list with cost and over ceiling markers followed by the thinking levels the model supports, or for claude the alias list (sonnet, haiku, opus, fable) followed by every effort. Saves the complete version 2 config atomically through saveDelegationConfig() and notifies tier → harness/model · effort. |
/subagent-cost |
none | Text input for the agent-model cost ceiling in USD/Mtok output. The placeholder shows the current value, empty input cancels, off disables, and a positive number sets it. Persists costCeiling in the version 2 config through saveDelegationConfig() and notifies the value. |
Events
session_startcaptures theExtensionContext. In TUI mode it registers the task-rail widget throughsetWidget("subagent-task-rail", …, { placement: "belowEditor" })and the rawonTerminalInputhandler for the down double-tap gesture.agent_settledrunsflushResults(), which drains the deferred-result queue and delivers each entry as asubagent-resultfollow-up message.session_shutdownclearssessionContext, removes the task-rail widget, unsubscribes the raw-input handler, resets the rail and the result queue, and awaitsruntime.dispose(). Childsession_shutdownhooks are emitted with a 5 s bound.
Renderers
registerMessageRenderer("subagent-result")renders the follow-up for a settled subagent: a status glyph,subagent id · description · finished/failed/cancelled, then elapsed and cost when known. Collapsed it adds the one-line digest and a dimsummary $x · N toknote for the digest call, so no raw report floods the transcript. Expanded it showsdetails.fullOutputhead-capped atrawCharCapwith a notice naming the takeover view and the persisted session file. The framed report lives indetails, and the message content stays the model-facing hand-back.registerEntryRenderer("btw-result")renders/btwanswers as session entries. Collapsed it shows theby the way · description · answered/failedheader and a/btw to reopenhint, and expanded it shows the full markdown body.subagent_sendrenders a call row (subagent_send, the id, then the message's first line) and a result row (⏵ id · steered/resumed (run N) · first line). Expanded, a resumed row addsThe result arrives the same way as a spawn.and the full message.subagent_checkrenders■ id · description · status · elapsed · $cost · ctx%with the digest line when settled. Expanded it shows the report, or while running the latest-output preview.subagent_cancelrenders one line per result (Cancelled id "description"orid "description" was already status) and puts the per-run hand-backs behind expansion, capped atrawCharCap.
Config
extensions/shared/subagent-models.jsonholds the persisted version 2 config,{ version: 2, costCeiling, tiers: { fast: { harness: "pi", provider, model, effort }, standard, deep, claude: { harness: "claude", model, effort } } }. The file is local-only (gitignored and excluded from published packages), so a fresh checkout runs onDEFAULT_DELEGATION_CONFIGwith every pi tier ondeepseek/deepseek-v4-proathigh, the claude tier onsonnetathigh, and no ceiling. A legacy version 1{ costCeiling, pi, claude }file still loads:piseedsfast,standard, anddeep,claudeseeds the claude tier, and the ceiling carries over. Migration happens in memory, and the file is rewritten as version 2 only after a save. Read throughloadDelegationConfig(), written atomically (temp file plus rename) by/subagent-modeland/subagent-costthroughsaveDelegationConfig().- The env var
PI_SUBAGENT_COST_CEILINGis a per-launch override of the file value, in USD/Mtok output, with"off"disabling the ceiling. <agentDir>/subagent-summary.jsonis the optional local config for the settle-time digest:{ enabled, inputCharCap, rawCharCap, skipUnderChars, timeoutMs }. Every field falls back on its own, so a missing or corrupt file means the defaults.enableddefaults to true,inputCharCapto 8000,rawCharCapto 4000,skipUnderCharsto 300, andtimeoutMsto 15000. The file is local only and gitignored, so no command writes it and a fresh checkout runs on the defaults.
Exports
index.ts: default(pi: ExtensionAPI) => void, andconsumeReturnedRuns().domain.ts:BACKEND_NAMES,SUBAGENT_NAME_PATTERN,SUBAGENT_NAME_ERROR,SUBAGENT_NAME_RESERVED_ERROR,validateSubagentName,generateAgentId,REASONING_EFFORTS,runRefOf,latestText,formatElapsed, typesBackendName,SubagentOrigin,ReasoningEffort,SubagentStatus,ParentContext,SpawnTask,SubagentMeta,SubagentSnapshot,TranscriptPart,TranscriptItem,LiveToolState,QueuedMessage,RunOutcome,SubagentEvent,SubagentRunRef,SubagentUsage, and tagged errorsSpawnError,BackendUnavailableError,ConcurrencyLimitError,SendError.backend.ts:SubagentBackend,SubagentSession,BackendCapabilities,BackendRegistry.backends/pi.ts:piBackend,piChildToolOptions,toSeedMessage,seedInheritedBtwContext,SeedableMessage.backends/claude.ts:claudeBackend,contextOccupancyTokens,costDelta.backends/stub.ts:makeStubBackend,StubProfile. IncontextOccupancyTokens, the per-request assistant-messageusageis the occupancy, and the result message's whole-runusageaggregate must never be used as one.manager.ts:SubagentManager,SubagentManagerLive,MAX_RUNNING,MAX_TRACKED,slugifyTitle,SubagentManagerShape,SubagentReadModel,CancelResult,SendResult,SpawnOptions.runtime.ts:createSubagentRuntime(),SubagentRuntime,runTool().handback.ts:HAND_BACK_MAX_BYTES(24 KiB),buildHandback({ snapshot, output })returning{ modelText, fullOutput, truncated }.prompt.ts: theSUBAGENT_*_TOOL_DESCRIPTIONconstants, the*_PARAMETER_DESCRIPTIONSmaps,SUBAGENT_SPAWN_PROMPT_SNIPPET,SUBAGENT_SPAWN_PROMPT_GUIDELINES,buildSubagentSpawnResult,buildSubagentCheckRunningNote,describeSubagent,delegationLabel. This is the single source of model-facing strings.by-the-way.ts:deriveBtwTitle,isModelVisible,BTW_TITLE_MAX_LENGTH,BTW_PROMPT_PREFIX,BTW_CONTEXT_START,BTW_CONTEXT_END,isBtwContextStart,isBtwContextEnd.result-delivery.ts:runRefKey,createDeferredResultDelivery.format.ts:formatContextUtilization,contextPercent,formatCompactTokens,formatCost,capChars,truncationNotice,ContextUtilization.summarize.ts:summarizeReport,shouldSummarize,makeSummarizeDeps,fastSummaryTarget,buildSummarizeRequest,SUMMARY_TIMEOUT_MS,SUMMARY_MAX_TOKENS,SUMMARY_PROMPT,SummarizeResult,SummarizeDeps,SummarizeTarget.summary-config.ts:loadSummaryConfig,parseSummaryConfig,summaryConfigPath,DEFAULT_SUMMARY_CONFIG,SummaryConfig.ui/:openSubagentPicker,openSubagentTakeover,reconcileDashboardSelection,configuredKeys,statusGlyph,statusWord,takeoverHeader,DashboardSelection(takeover.ts).openBtwPanel,BtwPanelResult(btw-panel.ts).TaskRailController,visibleRailSubagents,createTaskRail,DOUBLE_TAP_MS(task-rail.ts).firstLine,sendRowText,sendCallRowText,rowComponent(send-row.ts).findFocusedComponent,isDefaultEditorFocused(focus.ts).buildTranscriptLines,buildBtwAnswerLines,sanitizeText,mergeTranscripts(transcript.ts).pickTierConfig,pickEffort,applyTierSelection,tierTargetLabel,TierPickerUi,TierPickerDeps,TierPickerResult(model-picker.ts).persisted/:readPersistedTranscript(lazy async generator),loadPersistedTranscript,detectSessionFormat,SessionFormat(transcript.ts).parsePiEntry(pi.ts).ClaudeParserandcreateClaudeParser(claude.ts), plus the sharedparseJsonLine,safeJsonPreview,previewOf,textOf,isRecord.
Examples
- Delegate on a tier and keep working.
subagent_spawn { description: "errors survey", prompt: "Read docs/errors.md and list the three most common failure modes with their codes, as a bullet list.", name: "errors-survey", tier: "fast" }returns a background receipt, and the report arrives later as asubagent-resultfollow-up. The parent usessubagent_check { id: "errors-survey" }to pull the report on demand, or for a running agent to get status and guidance. There is no blocking wait: when the parent has nothing else to do it ends its turn, and the result wakes it as a follow-up. - User-requested override. A user-named Claude Code task,
subagent_spawn { description: "todo sweep", prompt: "In this repo, find every TODO and categorize by owner file; write the result to TODOS.md.", name: "todo-sweep", harness: "claude", model: "sonnet", reasoning_effort: "medium" }. Omitmodelandreasoning_effortunless the user named them, because a tier already carries the configured model and effort. - Steer or resume.
subagent_send { id: "errors-survey", message: "Also note which codes are retryable." }steers the run while it works. If the agent has settled, the same call starts a new run in that child session, and the next report is delivered like a spawn. - User aside. The user types
/btw what changed in the subagent API in this update?. A child inherits the conversation up to that point and answers while the main agent keeps working. The answer appears as a one lineby the way · …session entry, reopened in the/btwpanel or expanded inline. - Manage.
/subagentsopens the dashboard of model-origin subagents (j/k or the arrow keys select,xaborts a running agent, Enter takes over, where up and down or pgup and pgdn scroll, ctrl+t toggles thinking, ctrl+o toggles tool calls, ctrl+c aborts the run, the interrupt binding closes the view, and typing at the input line steers or continues)./btwwith no args opens the aside panel (left and right switch questions,nasks a new one,ccopies the answer)./subagent-modelchanges a tier's model and effort.