novo agents

Subagents

Subagents are how Novo turns one API call into an agent team. The orchestrator owns the user-facing answer, workers execute focused tasks, and advisors pressure-test plans, drafts, and decisions before the orchestrator commits.

Novo routes each delegated task to the model and configuration best suited for that role. The public contract stays simple: enable or disable delegation, set the normal run budget and limits, and render the task cards the stream emits. That routing lets Novo spend stronger routes where they are useful without sending every task through the most expensive model.

New agents have subagents enabled by default. You can also set it explicitly:

const agent = await novo.agents.create({
  context: 'You synthesize source-grounded research and clearly separate facts from assumptions.',
  band: 'core',
  capabilities: {
    web: true,
    subagents: true,
  },
});

With subagents on, Novo may split focused work into internal advisor and worker tasks while the root run remains the only user-facing conversation. You do not configure those routes or address child sessions directly.

When Novo delegates, you see task lifecycle cards on the root run stream. Each card has a human-readable label, a role (worker or advisor), and a workerRef you can use to follow that task's live transcript. The fields are detailed under Watching the subagent tree.

Each subagent receives task-specific instructions and referenced inputs rather than the full parent transcript, keeping specialist work focused and the orchestrator context clean. Files, artifacts, command output paths, preview URLs, and external URLs should be named by reference in the main request when you expect delegated work to inspect them.

Each task is a hidden child run that shares the orchestrator's thread identity and workspace, runs to completion, and hands back a concise result the orchestrator synthesizes. Children still inherit the effective agent/thread context, workspace/tool capability plan, time zone, data-handling posture, approvals, and budget/deadline policy. That plan excludes user interaction and further delegation; files or artifacts should be named by reference in the root request when you expect delegated work to inspect them. Set capabilities: { subagents: false } only when you want to prevent delegation.

Because effective agent and thread context are visible to delegated subagents when subagents are enabled, keep durable context narrow and role-neutral. Put task-specific instructions, one-off task details, and user-message details in the run input instead of broad durable context.

Subagent capabilities

A delegated subagent is always a subset of its parent - never more.

Every subagent starts from a read-only floor: it can read files and documents, view media, update its plan, use skills, and search or fetch the web when those are available to the parent. Advisors stay on that read-only floor. Workers may receive additional authority such as workspace writes, shell, browser, media generation, or selected MCP tool servers only when the delegated task needs it and only if the parent already has that authority.

That means developers get specialist routing and broad tool coverage without designing their own agent scheduler, specialist prompts, model map, or capability fan-out.

Three things are never delegated to a subagent: GitHub workflow authority, user interaction, and further delegation. Subagents cannot spawn their own subagents.

subagents is a simple on/off switch. Set subagents: false only when you want to prevent delegation entirely:

const agent = await novo.agents.update(agentId, {
  capabilities: {
    subagents: false,
  },
});

Task lifecycle

A delegated task runs autonomously and returns a single result to the orchestrator. It cannot ask a clarifying question mid-task, and it does not transfer control of the conversation to the end user. If it lacks essential information, it returns a blocked or partial result with the precise missing input so the orchestrator can follow up. Give the main agent complete instructions up front.

Workers and advisors are depth-1 leaves: a subagent cannot itself delegate.

Novo may keep an internal subagent session available for directly relevant follow-ups. Customers do not address these sessions directly - render task cards from the root stream and open worker streams with workerRef.

Open sessions and concurrency

A thread may have at most 9 open subagent sessions. Idle, running, and closing sessions all count until the orchestrator closes them, because idle sessions remain available for directly relevant follow-ups. If the agent tries to open a 10th session, that task is rejected without failing the root run; the orchestrator can close a no-longer-needed session or reuse a relevant existing one.

Running attempts still have the same shared safety guard: workers and advisors share the active-attempt budget, and the orchestrator should wait for in-flight work unless it intentionally closes a session to cancel it.

Cost and limits

Subagent cost rolls into the orchestrator run's budget. budgetCents and the platform per-run ceiling bound the whole tree, and the run's reported usage includes delegated work: both novo.runs.get(runId).usage and the stream's terminal data-novo-usage receipt are the tree-inclusive total, so stream.usage reconciles to the billed run. There is no separate subagent budget to set. Watch spend accrue mid-flight by polling runs.get: while the run is executing, usage reflects the whole tree's metered cost as of its last completed step.

Engine-fault attempts are not billed. If a delegated task terminates on an internal engine fault (a platform failure on our side, not a fault of your request), that attempt's inference is credited to $0 and never draws down your wallet, even though Novo still incurred the provider cost. The orchestrator re-dispatches the work, so you pay only for attempts that ran cleanly; the credited attempt is still visible as a $0 subagent_run row in usage. This applies to delegated (child) runs; a root run that faults after streaming partial output is billed for what it delivered.

Approvals inside a subagent

If a subagent calls a tool that requires your approval, it pauses and the approval surfaces to you under the orchestrator run. The run's status becomes waiting_for_approval and the request appears in interactions. Resolve the interaction the usual way and the delegated task resumes:

const pending = await novo.interactions.list({ runId: rootRunId, status: 'pending' });
await novo.interactions.resolve(pending.data[0].id, {
  inputResponses: [{ requestId: pending.data[0].id, optionId: 'approve' }],
});

Subagents never reach the end user directly; every approval is routed to you through the orchestrator.

Watching the subagent tree

The orchestrator's stream carries a data-novo-task card per delegated task (started, completed, failed, or cancelled). Render label as the task's primary title. Use workerRef as the address for the live transcript. The sub-stream opens with a data-novo-worker-meta chunk carrying the task's label, role, and the full dispatch prompt (the instructions the subagent ran on):

const worker = await novo.runs.workers.stream(rootRunId, workerRef);
for await (const chunk of worker) {
  // data-novo-worker-meta first (label, role, prompt), then
  // worker text, tool, and lifecycle chunks
}

Worker streams are addressable only under their root run. A delegated task is reached through runs.workers.stream(rootRunId, workerRef), never as a standalone run. Which model and band serve a task is chosen by server-managed routing and is not part of the customer surface.