Agents
View MarkdownBeta: this feature may change before general availability
An Agent is a definition: a system prompt, the inference source it runs on and a cost cap. An AgentRun is one
conversation with it. Each run works in its own sandbox, where the model runs shell commands to check its work, and
it survives restarts of Nodus by replaying recorded results. An interrupted command or model call using your own
key parks with NeedsResolution when its outcome is uncertain; inspect its effects before starting replacement work.
Agents, shared-sandbox subagents, parallel AgentGroups and Environment evaluation batches are in Beta.
Use the console
Section titled “Use the console”Agents opens directly to Tasks, with a table by default and a grid in the view switcher. Use New task to open the composer. Open Sandboxes → New sandbox to choose an environment and machine size. Sandboxes show status, CPU, memory, disk, idle timeout, usage cost and lifecycle actions. Open one for Environment, Terminal, Files, Commands, Preview and Inference.
Tasks, Sandboxes, Definitions and Batches stay together in the console navigation.
Connect Claude Code, Codex or Cursor through the existing connection setup. Then use the console to follow tasks, manage sandboxes and choose Nodus-served models.
- Choose New task. The Default setup is ready to use. Choose a saved setup for reusable instructions, tools and spending limits, or choose New setup… to create one.
- Open Model and search by model name, ID or alias. Keep the setup’s model, choose a Nodus-served model or ready endpoint, or use Bring your own endpoint… at the bottom of the picker. Nodus models use your existing credits. This choice applies to the new task without editing the saved setup. Describe the result, then choose Review task to see both selections, the spending limit, team size and sandbox lifetime. Choose Start run to launch. Closing the review keeps your draft and both selections.
- Open Activity to see what is happening, which tasks are done, and whether anything needs attention. Search assignments or filter to active tasks. Pause updates freezes the live view without pausing the run.
- Open Task to read your prompt and the answer, send a follow-up, or see why the run stopped. A compact side panel shows the setup, model, duration, cost and workspace status. Open Workspace for full-width Environment, Terminal, Files, Commands, Preview and Inference tools. Activity keeps team results, recorded steps and model usage together. Released workspaces show their status without offering unavailable tools.
Use Active, Needs attention, or Completed on the Agents page to narrow the task list. The default list puts actionable waits and failures first, followed by active and finished runs. Each task explains its known waiting reason and offers a direct link to review the team, continue the conversation, read the answer or view progress. Ordinary waits stay in Active. Mobile summaries keep status, cost and the next action together. Projects with existing tasks open on inventory and activity; New task expands the launcher. Closing it preserves your draft. Search by prompt, run name, agent or group; the URL keeps your filters. Pause live updates freezes the displayed list while the runs continue.
An agent is reusable configuration; a run is one task. Subagent count is optional: the parent chooses how many subagents it needs within your configured ceiling. Each run shares one sandbox among its parent and children. Enable Keep the sandbox for follow-up messages only when you need to continue the conversation; compute can continue accruing charges while it waits. Send the next task from the run’s Task → Send follow-up. Cancel the run when finished.
Sandboxes and development
Section titled “Sandboxes and development”Agents → Sandboxes includes machines created directly and sandboxes belonging to agent runs. Choose New sandbox, an environment image, and a CPU size (Starter, Standard, Performance or Custom). Set when idle compute stops, when the sandbox is deleted, its network access and an optional compute spending limit. Review the configuration before creating it. Advanced contains saved startup profiles (Alpha), organization and project defaults, GPU and runtime settings. Your explicit settings take priority over defaults. The Code menu shows the same configuration as YAML, CLI or Python.
Open a sandbox to use the same Environment, Terminal, Files, Commands, Preview and Inference panel as an agent run. Opening the environment summary does not start a shell or wake stopped compute. Running and Paused filters reflect the reported machine state.
The Inference tool shows token rates, a coding-tool setup prompt and a Python example for a tool-capable model from the live Nodus catalog, and links to create an agent with that model. For your own sandbox code, provide a Nodus API key through a project Secret and allow outbound access to the inference endpoint. Credentials are never copied automatically. Managed agent runs use their existing inference connection; model usage and sandbox compute remain separate charges.
Reuse an environment
Section titled “Reuse an environment”When creating an agent, Environment image lists completed project and catalog images. Choose an image
containing your tools and dependencies; each run uses the selected immutable image version. Custom image
reference accepts an OCI image your project can pull. The default is nodus/agent-tools. New Sandbox creation
uses the same picker. Building or failed images are not offered as ready environments.
On a run’s Workspace, Files opens the Sandbox file browser. Upload inputs, edit text with conflict protection, and download outputs without leaving the run. Opening the panel does not start stopped compute; choose Wake and browse when you want to resume it. Files outside the configured persistent state directory do not survive a stop and restart.
Run commands alongside an agent
Section titled “Run commands alongside an agent”On a run’s Workspace, choose Commands. Enter a shell command, working directory and timeout, then choose Run command. The command runs in that agent’s Sandbox and can continue after you close the panel. Use its output panel to follow stdout and stderr, or cancel it from command history. Cancelling a command does not stop the agent or its Sandbox.
History includes commands from earlier sessions and stays readable while the Sandbox is stopped. New commands and the terminal require a running Sandbox; opening history never starts compute. A stopped Sandbox needs an explicit Start sandbox action. Output retrieval currently requires the original running environment; a new start does not restore past process output. The viewer bounds recent output to 10,000 lines and about two million characters, shortening individual lines over 65,536 characters.
If a launch response is lost, check history and open the matching recorded command. Nodus does not automatically resubmit an uncertain launch. Check the command’s effects before intentionally launching it again.
Choose inference
Section titled “Choose inference”In Agents → Definitions → New agent, choose an inference source. The parent and its parallel subagents share this choice. Changes to an Agent apply to new runs; existing runs keep their admitted settings.
| Source | Select |
|---|---|
| Nodus inference | A tool-capable model from On Demand, or endpoint/name |
| My hosted model | Coming soon; currently unavailable |
| Bring my API key | OpenAI-compatible or Anthropic API, model id and saved Secret |
| Managed Claude | Automatic Claude routing |
Named endpoints retain their access, concurrency and budget policies; an endpoint restricted to named API keys cannot be invoked through the agent’s service identity.
import nodus
agent = nodus.ModelAgent("researcher", model="openai/gpt-oss-20b", max_parallel_agents=8)print(agent.remote("Use two parallel subagents to compare the approaches, then combine the findings."))For a single task, choose Model / inference → Bring your own endpoint…. Select the API format, enter the public HTTPS API base URL and exact model ID, then select a saved key or choose Add API key. Saving a new key returns you to the task; its value is stored in an encrypted project Secret, never in the run configuration. For a Secret with several values, select the field containing the API key.
Choose Use endpoint, then Review task to confirm the model, endpoint and saved key before launching. These steps configure the connection; they do not test it or start paid work. The model must support tool calling. Your inference provider bills model usage and controls its spending limits; Nodus bills sandbox compute separately. Use Edit endpoint to adjust the connection, or select a Nodus model to use your existing Nodus credits instead. The saved setup is unchanged.
For the SDK, save your key as a project Secret, then select it:
agent = nodus.ModelAgent( "researcher", protocol="OpenAI", model="gpt-4.1-mini", api_key_secret="model-key")A single-value Secret can use any field name. With multiple values, use OPENAI_API_KEY, ANTHROPIC_API_KEY,
or specify api_key_field. A compatible provider can set base_url="https://api.example.com/v1"; private
addresses and redirects are refused. Keys are not placed in agent files or prompts.
ChatGPT and Claude chat subscriptions have separate API billing; subscription sign-in is not supported here.
My hosted model is coming soon. The option is reserved; hosted Agent definitions and runs are rejected before any compute starts. Use On Demand or BYOK for now.
For On Demand, parallel calls split the remaining per_run_max_cost allowance before dispatch. BYOK calls
have no Nodus model charge; their token usage is still shown. Set provider-side limits for BYOK. An uncertain
BYOK call parks with NeedsResolution instead of repeating it.
Sign in and create an agent
Section titled “Sign in and create an agent”apiVersion: nodus.dev/v1kind: Agentmetadata: name: hello-agentspec: workingDir: /workspace continuity: {mode: Snapshotted, stateDir: /workspace} setup: printf 'workspace-ready\n' > ready.txt # Optional, after connecting the repository in this project: # source: {git: {repo: your-org/your-repo, ref: main}} system: | You are a careful assistant. Run shell commands in your sandbox to check your work, and answer in one short paragraph. # Nodus's Claude: each prompt is routed to Haiku, Sonnet, Opus or Fable, and billed from your credits. model: access: Nodus perRunMaxCostUSD: "0.50"nodus loginnodus apply -f agent.yamlThe agent uses Nodus’s Claude. Every prompt goes to a small router that picks the right Claude model for it (Haiku
for simple requests up to Fable for demanding ones). That model answers the whole prompt, including its commands,
so the model never changes in the middle of a turn. If the router is unavailable, Sonnet answers. Restrict the
choice with spec.model.families, for example [haiku, sonnet].
Start a run
Section titled “Start a run”apiVersion: nodus.dev/v1kind: AgentRunmetadata: name: hello-agent-runspec: agent: hello-agent # Optional: select inference for this task without editing hello-agent. # Omit model to use the saved setup. model: access: Nodus input: "Use the shell to print the Python version, then tell me which one it is."nodus apply -f run.yamlnodus wait agentrun/hello-agent-run --for=jsonpath='{.status.phase}'=Succeeded --timeout=8mnodus get agentrun/hello-agent-run -o yamlOr without a file: nodus create agentrun triage --agent hello-agent --prompt "Summarize the logs". To start
from Nodus’s ready-made assistant, name the template claude-assistant.
status.turns lists each prompt with the model that served it, how it was chosen (jev or fallback) and its
cost. status.answer.preview holds the first 4 KiB of the final answer; nodus agentrun answer prints all of it.
nodus agentrun answer hello-agent-runnodus agentrun steps hello-agent-runsteps lists what the run did in order: creating its sandbox, each routing and model call, each command. A step
that shows Completed is never repeated, even after a restart.
The console’s Agents page shows the same: each run with the model of its latest turn and its cost, and on a run every turn with the model that served it, how that model was chosen and what the turn cost, then the answer and the recorded steps. Task keeps the original prompt visible as the run updates. Its execution-attempt count includes startup retries; it does not mean the agent recovered completed work.
From Python
Section titled “From Python”import nodus
agent = nodus.ClaudeAgent("helper", system="You are careful.", families=["haiku", "sonnet"])print(agent.remote("Use the shell to print the Python version")) # runs to the end, returns the answer
run = agent.submit("Summarize the logs", keep_alive=True) # a handle: run.answer(), run.steps(), run.cancel()run.send("message", "Now the staging logs")ClaudeAgent creates the agent on first use. Pass api_key_secret="anthropic-key" to use your own Anthropic key,
or ClaudeAgent.from_name("claude-assistant", project="nodus") to run the ready-made template. To run many at once
from Python, see Run agents in parallel.
Prepare a repository and keep its workspace
Section titled “Prepare a repository and keep its workspace”In New agent → Sandbox environment, choose the workspace folder, then open Repository & setup. Enter a GitHub repository and optionally a branch, tag or commit. Connect that repository to the project through Connections → GitHub first. Each task pins one commit and copies its code into the workspace before the model starts. This is a code snapshot: it contains neither Git history nor credentials for pushing changes.
A setup command runs once after the copy. Select Public internet if it downloads dependencies, and install
those dependencies inside the workspace (for example, node_modules or .venv). Use a prepared image for system
packages. Setup output is recorded in Steps. A failed setup stops before inference; an interrupted command
with an unknown outcome requires inspection instead of automatically running again.
spec: image: nodus/agent-tools workingDir: /workspace continuity: {mode: Snapshotted, stateDir: /workspace} source: {git: {repo: your-org/your-repo, ref: main}} setup: npm ci network: {egress: {policy: Open}} model: {access: OnDemand, name: YOUR_TOOL_CAPABLE_MODEL_ID}For the task, choose After the answer → Keep workspace for follow-ups. Send another message from its task page to continue with the same files, setup, pinned model configuration and cumulative model budget. Compute may continue to accrue while the task is open. Finish and release workspace remains the default.
Selected-folder persistence is Beta. A normal stop saves the folder within the funded shutdown window; a restart restores its last useful save. Check the Sandbox’s save status before relying on it. An unexpected node loss can lose changes since the last checkpoint. Files outside the folder and running processes are not preserved. Ending, cancelling or deleting the task removes its Sandbox; this is not an independent workspace that survives the task. A new task starts a new workspace and repeats preparation.
import nodus
agent = nodus.ClaudeAgent( "repo-helper", model="YOUR_TOOL_CAPABLE_MODEL_ID", # served through Nodus inference working_dir="/workspace", state_dir="/workspace", source={"git": {"repo": "your-org/your-repo", "ref": "main"}}, setup="npm ci", network=nodus.Egress.open(),)run = agent.submit("Inspect the project and suggest one improvement", keep_alive=True)# After the answer, continue without repeating preparation:run.send("next-step", "Implement the suggested improvement and check it")# End the task when you are done; this deletes its workspace.run.cancel()Keep a run open for follow-ups
Section titled “Keep a run open for follow-ups”Set spec.keepAlive: true and the run waits for messages after each turn instead of finishing. While it waits it
uses no model and keeps its sandbox, which can still accrue compute charges. Set spec.deadline to bound the run’s
lifetime. The deadline also applies while waiting for a message: the run fails with DeadlineExceeded and its
sandbox is deleted without another model call.
nodus apply -f run.yaml # with keepAlive: truenodus agentrun send hello-agent-run "Now do the same for the staging logs" --key staging-1Sending the same --key again delivers the message once. A run that is still working reads the message after its
current turn; a finished run refuses it with AgentRunFinished. Cancel a run with nodus cancel agentrun/NAME;
its sandbox is deleted.
The same calls are REST: POST …/agentruns/NAME/messages with {"payload": "…", "messageKey": "…"}, and GET
on …/steps and …/answer.
Delegate subtasks in one sandbox
Section titled “Delegate subtasks in one sandbox”The parent agent can call parallel_agents to choose how many subagents a task needs, up to eight at a time by default, gather their results and
finish a larger task. Ask it to split independent work and give each child a clear goal and its own output paths:
apiVersion: nodus.dev/v1kind: AgentRunmetadata: name: shared-subagentsspec: agent: hello-agent # Run at most two ready subtasks together; omit or use zero for Auto. parallelism: 2 input: | Use one parallel_agents batch with these named tasks in our shared sandbox: 1. primes: Compute the sum of the primes below 30 using Python. Write the number to /tmp/primes.txt. 2. squares: Compute the sum of the squares from 1 through 5 using Python. Write the number to /tmp/squares.txt. 3. total: After primes and squares complete, read their files, sum the numbers, and write /tmp/total.txt. Declare each task's own output path in writes. total depends_on primes and squares; the first two run concurrently. After the batch finishes, read all three files yourself, verify them, call verify_team with a Python assertion for both numbers and their total, and reply with exactly: primes=129 squares=55 total=184Use the hello-agent definition above, then apply this run:
nodus apply -f run.yamlnodus agentrun steps shared-subagentsnodus agentrun answer shared-subagentsNew agents default to Unlimited subagents. The parent chooses useful tasks and schedules ready work within the sandbox capacity and shared model budget. There is no fixed 32-subagent ceiling. Use Set a limit in the console to add your own concurrency limit. Existing agents retain saved positive limits; remove one with:
nodus patch agent/hello-agent --patch '{"spec":{"maxParallelAgents":0}}'The change applies to new runs. The API uses zero or an omitted maxParallelAgents for Unlimited; in Python,
use nodus.ClaudeAgent("helper") or max_parallel_agents=0. A positive value sets your own concurrency ceiling.
Larger plans queue tasks rather than rejecting them for exceeding that ceiling. Unlimited does not increase
the run’s budget or tool allowance: choose perRunMaxCostUSD and maxToolCalls to cover the larger task.
New sandboxes reserve one vCPU and 1 GiB per eight explicitly allowed concurrent workers, rounded up.
Unlimited Auto starts with one vCPU and 1 GiB. A smaller run maximum reduces an explicit reservation.
Existing sandboxes keep their original resources. Combined answer text is capped at 128 KiB; put longer results in shared files.
Payload limits, the 10,000-step run journal allowance and cancellation remain enforced. Children cannot delegate recursively.
For each run, Auto chooses how many ready tasks work at once from task dependencies, assigned files,
configured sandbox capacity and the remaining model allowance. The Activity tab explains its selection.
Choose Set a maximum to override the capacity heuristic; the Agent ceiling and spending/tool limits still
apply. Set spec.parallelism: 6, use nodus create agentrun NAME --agent NAME --prompt "TASK" --parallelism 6,
or call agent.submit("TASK", parallelism=6). Omit it or use zero for Auto. This does not resize an existing
sandbox or guarantee a final price. BYOK provider spending is not measured or capped by Nodus.
The Team view and CLI report Peak parallel model calls from recorded invocation timings. This measures
overlap among finished child calls, not the requested team size or queued assignments. Older calls without
timings and unresolved calls are excluded, so the number is a lower bound. For a total cap covering compute
and managed inference together, use a project-scoped Budget with period: Total and action: Block; see
examples/agents/product-showcase/budget.yaml. Keep that budget across rehearsals so spend is cumulative.
Children share the parent’s sandbox and files. Each has its own conversation, so the parent supplies the context it needs in the task description. They use the same model as the parent and can run commands, read files and write files concurrently. The parent waits for the batch, reads the answers and shared files, and can delegate another batch for the next stage. For new runs, the parent gives each task a name, declares its output files or folders, and lists any earlier tasks it depends on. Independent tasks run together. Tasks with overlapping assigned paths wait for the current owner to finish; dependent tasks receive their prerequisites’ saved results.
For example, ask for two research tasks that write separate files, followed by a synthesis task that depends
on both. You describe the outcome; the parent builds the task plan. Developers configuring a parent use this
parallel_agents tool input:
{"tasks":[ {"name":"research","task":"Research the approach; write /tmp/research.md.","writes":["/tmp/research.md"]}, {"name":"summary","task":"Summarize the findings in /tmp/summary.md.","depends_on":["research"],"writes":["/tmp/summary.md"]}]}Task names are unique lowercase letters, digits or hyphens, beginning with a letter (up to 64 characters).
Dependencies must name earlier tasks in the batch. writes is required: use clean absolute file or directory
paths, or [] for a read-only task. Read-only children can read files and report progress; they cannot run shell
commands. Direct file writes outside assigned paths are rejected. Path claims coordinate work; they do not
isolate processes or enforce shell commands and symlink aliases. Keep those commands within assigned paths.
This feature is in Beta. Each task description is at most 16 KiB; children cannot spawn more children. All child work counts toward the parent’s model cost cap and turn limits. Sandbox compute is still billed separately. Cancelling the parent stops further rounds and releases the shared sandbox after in-flight work joins. Open the run’s Activity tab to see each assignment, current activity, progress, model usage, files and results.
The same saved progress is available from every developer interface:
| Interface | Read subagent progress |
|---|---|
| CLI | nodus agentrun team NAME -p PROJECT --org ORG |
| CLI JSON | nodus agentrun team NAME -p PROJECT --org ORG -o json |
| API | GET /apis/nodus.dev/v1/namespaces/PROJECT/agentruns/NAME/team with your bearer credential and Nodus-Org header |
| MCP | Call team with {"kind":"AgentRun","name":"NAME","project":"PROJECT"} |
| Python | nodus.AgentRun.from_name("NAME", project="PROJECT").team() |
The response’s summary provides the parent run state, a plain-language message, counts, and an action:
None, ViewAnswer, SendMessage, ManageTasks, or InspectRun. items carries task-level results, usage and files;
verification holds check evidence. New tasks also include name, dependsOn, writePaths, waitingFor
and waitReason; dependency references use stable task IDs. The UI and CLI explain which task or shared files
a waiting task is waiting for. A finished subtask is not a finished run. MCP requires agentruns:read,
and uses the organization of its authenticated connection. Python uses your configured organization.
Task text and results are user-provided content; treat them as untrusted content in your own automation.
Completed results appear as soon as they are saved, even while another child is still working. Reloading or
restarting the worker keeps saved results; completed commands and model calls are not repeated.
Recover one task
Section titled “Recover one task”A known failed child pauses the parent after other ready work finishes. Open Activity and choose Retry, Redirect, or Cancel task. Retry starts a new attempt of that failed task. Redirect accepts new instructions and keeps its assigned files and dependencies. Cancel stops its next operation; tasks that depend on it are also cancelled. Completed peers and existing files remain in place. Sandbox compute can still accrue while waiting for your direction.
nodus agentrun retry-task NAME task-1-2 --key retry-1nodus agentrun redirect-task NAME task-1-2 --instruction "Check the missing edge cases" --key redirect-1nodus agentrun cancel-task NAME task-1-2 --key cancel-1These are alternatives for a task that offers the corresponding action. Use -o json for the acceptance
receipt, then read nodus agentrun team NAME -o json for its application state. A request waits for the current
operation to finish; it does not undo earlier writes. A stale request is rejected if the task has advanced.
Reuse the same request key when retrying delivery of the same command.
run = nodus.AgentRun.from_name("NAME")receipt = run.retry_task("task-1-2", request_key="retry-1")# Alternatives: run.redirect_task("task-1-2", "New instructions", request_key="redirect-1")# run.cancel_task("task-1-2", request_key="cancel-1")print(run.team())API clients POST to …/agentruns/NAME/team-controls with
{"taskId":"task-1-2","action":"Retry","requestKey":"retry-1"} and an Idempotency-Key header.
requestKey is required (1–128 bytes); the CLI, console and Python client generate it when needed.
Redirect also requires instruction (1–16384 bytes). HTTP 202 acknowledges acceptance; it does not mean the
change has already happened. MCP uses record with kind: "AgentRun", the run’s name/project,
subresource: "team-controls" and that request body in body. It requires agentruns:write.
The /team response lists each task’s allowed actions, its attempt, and its latest control state.
Controls are available on newly created runs. Completed runs, exhausted fixed caps and uncertain external
operations do not offer task retry. NeedsResolution still requires inspecting the unknown effect before
starting replacement work. Retry does not reset spending or model/tool limits; the parent must verify the
combined result again before completing.
File writes through write_file are attributed to the child. Shell changes appear as reported outputs when
an agent calls report_progress; the view reads and fingerprints those files, but does not infer who changed
arbitrary shared files. Assigned paths control which tasks may run together, while shell edits still rely on
the task following its instructions.
The parent reviews the combined result and calls verify_team with relevant test commands before completing.
The Activity tab shows actual exit codes and check output. For non-code work it may record why tests do not apply;
that appears as Reviewed, rather than Checks passed. Later edits invalidate the review. A run that
exhausts its turn without current verification fails with TeamVerificationRequired instead of claiming success.
Children leave a fifth of the model cap for parent review; increase the budget when the whole task needs more.
Read the same saved view with run.team() in Python or GET …/agentruns/NAME/team. Activity also includes recorded steps with
task-BATCH-CHILD.assignment, .model and .tool.TOOL records, plus team.verification. Runs admitted before
subagent tracking keep their original subagent.N history. Uncertain external operations still require inspection;
a completed child is not rerun merely because another child needs resolution.
Run agents in parallel
Section titled “Run agents in parallel”An AgentGroup runs many runs of one agent at once. You choose how many run at the same time and how much the whole group may spend. The other runs wait their turn, and one command cancels or deletes all of them. Create the agent and the group, then one run for each task:
apiVersion: nodus.dev/v1kind: Agentmetadata: name: parallel-agents-workerspec: system: | Follow the task's requested answer format; otherwise answer in one short sentence. # Nodus's Claude, limited to Haiku so each run stays far below its cap. model: access: Nodus families: [haiku] maxTokens: 1024 perRunMaxCostUSD: "0.10"apiVersion: nodus.dev/v1kind: AgentGroupmetadata: name: parallel-agentsspec: agent: parallel-agents-worker limits: maxActive: 2 # at most two runs go at once maxCostUSD: "0.60" # a run starts only while its own cap still fits under what is leftapiVersion: nodus.dev/v1kind: AgentRunmetadata: name: parallel-agents-aspec: agent: parallel-agents-worker group: parallel-agents taskKey: a input: "What is the capital of France?"---apiVersion: nodus.dev/v1kind: AgentRunmetadata: name: parallel-agents-bspec: agent: parallel-agents-worker group: parallel-agents taskKey: b input: "What is the capital of Japan?"---apiVersion: nodus.dev/v1kind: AgentRunmetadata: name: parallel-agents-cspec: agent: parallel-agents-worker group: parallel-agents taskKey: c dependsOn: [a, b] # c waits until a and b have succeeded input: "Say in one sentence that both questions have been answered."nodus apply -f agent.yamlnodus apply -f group.yamlnodus apply -f runs.yamlnodus patch ag/parallel-agents --patch '{"spec":{"sealed":true}}'Or without a file: nodus create agentgroup parallel-agents --agent parallel-agents-worker --max-active 2 --max-cost 0.60.
Each run is a task of the group: spec.group names the group and spec.taskKey names the task (a DNS label that is
unique in the group). The run is named <group>-<taskKey>; leave metadata.name out or set exactly that. The run
uses the group’s agent, so spec.agent must match it. The last command seals the group, which says that no more runs
are coming (see below).
Watch progress and read the answers
Section titled “Watch progress and read the answers”nodus wait ag/parallel-agents --for=jsonpath='{.status.phase}'=Succeeded --timeout=12mnodus get agnodus get ar --field-selector spec.group=parallel-agentsnodus agentrun answer parallel-agents-cnodus get ag lists each group with its phase, RUNS (finished successfully out of all) and ACTIVE runs, and
its cost. status.counts splits the runs into queued, active, waiting (for a message or for funds),
succeeded, failed and cancelled. status.blockedReasons says why queued runs have not started and how many
wait for each reason: DependencyWait, MaxActiveReached or MaxCostReached. A queued run’s own status.reason
is DependencyWait, or GroupWait while it waits for a free slot or for room under the cost cap. The runs you list
are ordinary runs, so status.answer, nodus agentrun answer and nodus agentrun steps work on each of them.
A group is Running until it is sealed and every run has finished. It then becomes Succeeded, or Failed with
reason RunsFailed when a run failed or was cancelled because a dependency failed. A sealed group with no runs
succeeds.
How many run at once
Section titled “How many run at once”spec.limits.maxActive is how many runs the group lets run at the same time (default 10, 1 to 1000). Change it on a
live group:
nodus patch ag/parallel-agents --patch '{"spec":{"limits":{"maxActive":4}}}'spec.limits.maxPending is how many unfinished runs the group takes in (default 10000); a run beyond it is refused.
Dependencies
Section titled “Dependencies”spec.dependsOn lists the task keys a run waits for. It starts only after every one of them has succeeded, and
until then it is queued with reason DependencyWait. A dependency must already be in the group, so create the runs
it depends on first (earlier in the same file works). When a dependency fails, the run is cancelled with reason
DependencyFailed; when a dependency was cancelled, the run is cancelled with reason DependencyCancelled.
The group cost cap
Section titled “The group cost cap”spec.maxCostUSD is one cap for the whole group. A run starts only when its own cap (the agent’s
perRunMaxCostUSD) still fits under what is left: the cap minus what the group has spent and minus the caps of the
runs that have started and not finished. The members together can therefore never spend more than the cap, and runs
that do not fit yet wait with MaxCostReached. In the example, the $0.60 cap has room for the caps of six runs at
$0.10 each before any run has spent anything. Raise the cap on a live group with nodus patch; it cannot be lowered.
If the cap is smaller than one run’s cap, no run starts: raise it or lower the agent’s perRunMaxCostUSD.
status.cost shows totalUSD and limitUSD. The cap covers the runs’ Claude usage (model and routing calls), the
spend each run’s perRunMaxCostUSD limits; the sandbox each run works in is billed on its own and is not counted
against either cap.
Seal, cancel and delete
Section titled “Seal, cancel and delete”A group takes new runs until you seal it with spec.sealed: true. Sealing cannot be undone, and a sealed group
refuses new runs with a conflict. A group finishes only once it is sealed, so seal it after you create the last run.
nodus cancel ag/parallel-agentsnodus delete ag/parallel-agentsnodus cancel cancels every run that has not finished and leaves the finished runs, with their answers, as they are.
status.phase goes through Cancelling to Cancelled. nodus delete removes the group together with all of its
runs.
Evaluate an agent
Section titled “Evaluate an agent”Create an evaluation group with an Environment at an explicit version. Nodus generates the fixed task batch, runs it through ordinary AgentRuns, and grades completed answers using the Environment’s isolated grader. There is no manual submit or seal step. Set a project Budget to limit total spend: the group cap covers model usage, while agent and grading Sandbox compute is billed separately.
After deploying the example’s parallel-agents-worker Agent above, run this Python example. It creates two
held-out tasks, waits for a terminal result, prints per-case outcomes and deletes the evaluation group afterward.
"""Evaluate the deployed example agent on a fixed, versioned task batch."""
import nodus
def main() -> None: # Model caps exclude Sandbox compute; set a project Budget before running this example. evaluation = nodus.AgentGroup.create( "parallel-agents-eval", agent="parallel-agents-worker", max_active=2, max_cost="0.20", evaluation={ "split": "test", "tasks": 2, "repetitions": 1, "seed": 42, "timeout": "10m", }, ) try: status = evaluation.wait(timeout=660) results = evaluation.results() print( f"{status.phase}: cases={len(results)}, pending={status.evaluation.pending}" ) print("pass rate:", status.evaluation.get("passRate")) print("mean reward:", status.evaluation.get("meanReward")) for result in results: print(result.task_id, result.state, result.get("verdict")) finally: evaluation.delete()
if __name__ == "__main__": main()The batch is at most 100 cases including repetitions. Every member pins the same Agent revision; results record the Environment version, resolved image digest, split and seed. Only task prompts reach the agent, never hidden answers. The timeout defaults to 30 minutes, may be 1 minute to 24 hours, and includes manifest preparation, queueing and funding waits from group creation. Each member receives that absolute deadline. Grading also stops at the deadline; completed answers that could not be scored are shown as evaluation timeouts, excluded from pass rate and mean reward.
Open the group in the console to see scored cases, pass rate, mean reward, pending cases and execution/grading failures separately. The Results view links each case to its AgentRun and shows grader evidence. A failed run, missing answer or grader failure is unscored and does not become a zero reward. A wrong or invalid answer is a scored result. Per-case records share the member journal’s 30-day payload retention; deleting the group removes its runs and records. Canceling or finishing the group cleans up its grading pool.
Use your own Anthropic key
Section titled “Use your own Anthropic key”Store the key in a Secret under the key ANTHROPIC_API_KEY and point the agent at it. Nodus then charges nothing for the model, and your Anthropic
account pays for it.
spec: model: access: BYOK name: claude-sonnet-5-5 apiKeySecret: anthropic-keySpending limits
Section titled “Spending limits”spec.perRunMaxCostUSD (default $1.00) caps what an On Demand or managed Claude run spends on the model. Before each call
the run checks that it fits under the cap. When it does not, the run waits (reason: MaxCostReached) and makes no more calls. The cap is
copied from the agent when the run is created, so changing the agent does not change a run that has started: to
continue the work, cancel the run and start a new one. If your credits run out, the run waits instead and
continues when you add credits. BYOK inference uses your provider’s spending limits.
Sandbox compute is billed separately and is outside this model cap. status.cost shows the model spend so far. Runs in a group also
share the group’s cap (see Run agents in parallel).
Limits
Section titled “Limits”- One run works one prompt at a time, with at most
spec.maxToolCallscommands per turn (default 50). - The input and each message are at most 256 KiB. A run’s recorded payloads are kept 30 days after it ends.
- A run created for a stopped agent (
spec.state: Stopped) is refused withAgentStopped. - A group takes at most 10000 unfinished runs. Create runs in batches of up to 100 by posting an
AgentRunListto…/agentrunswith anIdempotency-Keyheader; a batch is all-or-nothing, and its runs are created in list order, so list each run after the runs it depends on.
See Durable execution for what survives a restart.
In the console, Agents includes Tasks, Sandboxes, Definitions, and Batches. Use the page’s ⋯ menu to copy its CLI command.
Connect tool credentials
Section titled “Connect tool credentials”Agents accept the same env, secrets, and network settings as Sandboxes. Use project
Secrets for GitHub deploy keys and other tool credentials. Parent and child tools share these
permissions, so scope credentials to the repositories and services the task needs. Keep secrets
out of prompts and command output. The default outbound policy is Deny; explicitly select
network.egress.policy: AllowList with allow: [github.com, api.github.com] for GitHub HTTPS
access. Add the domains the task needs. Tools must honor the injected HTTPS_PROXY/HTTP_PROXY
settings. Open permits public Internet access; private and metadata addresses stay blocked.
These settings are pinned when a run is admitted, and secret delivery uses the Sandbox path.