The nodetool agent command runs one CodeAct turn from the terminal. It takes
an objective, hands it to the model as the user message, and prints the final
answer. The model acts by writing sandboxed JavaScript over the toolbelt — the
same loop the chat runs — so what it does is up to it: call a tool, decompose
the objective with create_plan and run the DAG with execute_plan, or answer
straight away. Every run streams a live trace of tool calls, plan events, and
task events to stderr.
There is no configuration file. Everything the command needs is an argument.
Subcommands
nodetool agent run --objective "..." # run the agent loop
nodetool agent diagnose <job_id> # aggregate a failed run into one report
nodetool agent run
The objective comes from -o, --objective or, when that is absent, from piped
stdin.
nodetool agent run -p anthropic -m claude-sonnet-5 \
--objective "Research the latest AI trends"
echo "Research the latest AI trends" | \
nodetool agent run -p anthropic -m claude-sonnet-5
Options:
-o, --objective <text>— Objective for the agent (else read from stdin)-p, --provider <id>— Provider id (required)-m, --model <id>— Model id (required)-w, --workspace <path>— Workspace dir for file tools (default: cwd)--max-iterations <n>— Tool-calling rounds in the turn (default 25)--cost-cap <usd>— Ceiling on provider spend for the whole run;0lifts it--timeout <s>— Wall-clock bound on the run in seconds;0leaves it none--json— Emit each agent event as a JSON line on stderr-v, --verbose— Include low-level chunk and other events in the trace
Run budget
--cost-cap and --timeout override two of the five NODETOOL_AGENT_*
settings a chat turn reads (NODETOOL_AGENT_TURN_COST_CAP_USD,
NODETOOL_AGENT_TURN_DEADLINE_MS); concurrency, total turns, and the
unpriced-token ceiling come from the settings alone.
The run holds one budget and shares it downward — a sub-agent, an
execute_plan DAG, an AgentNode reached through run_node — so the ceiling
bounds the run, not each loop. A cap is admission: a turn whose worst case
would cross it is refused before the call, not noticed after the money is
spent. A model with no catalog price has no worst case and is admitted against
a prompt-token ceiling instead, never as free.
A ceiling that stops the run prints its reason and exits non-zero
(agent stopped: turn budget of $0.01 reached); with --json the same reason
arrives as an error event. Every run ends with what it committed —
spent $0.0123.
nodetool agent run -p openai -m gpt-5.4-mini -o "Research AI trends" \
--cost-cap 0.50 --timeout 120
The final result goes to stdout and the trace goes to stderr, so you can capture the result on its own:
nodetool agent run -p openai -m gpt-5.4-mini \
-o "Summarize NodeTool" > result.txt
Tools
The agent gets the default toolbelt: files, search, browser, PDF, vision,
critique, memory, assets, todo, plus the platform tools — workflows,
nodes, jobs, apps, models, and media generation. This is the same belt the chat
agent and the MCP bridge assemble, so the surfaces cannot drift. The belt is not
narrowable from the command line — nodetool agent run has no --tools flag.
The belt is assembled by buildCliAgentBelt, shared with the CLI’s own chat,
and carries the capabilities that spawn loops of their own: run_subtask,
start_subtask, wait_subtasks, run_search, and — here, unlike chat — both
create_plan and execute_plan. The provider itself is offered execute_code
plus the direct tools; the rest of the belt lives in the sandbox.
What the planner used to do
agent run used to plan a task DAG up front, execute it, and have a compiler
model write the final answer. The model now decides: it calls create_plan when
the objective wants decomposing, and execute_plan runs that DAG on the same
executor. Four things went with the old pipeline and have no replacement flag:
the plan approval prompt (the permission gate on execute_plan is the
approval), checkpoints and the plan cache, the separate planning and reasoning
models, and skill auto-selection by word overlap (the model loads a skill
itself). --max-steps is gone with them; --max-iterations now bounds
tool-calling rounds in the turn rather than action rounds per step.
nodetool agent diagnose
Aggregates a failed run — the failing node or step, its error, the last LLM call, and the agent’s memory — into one report.
nodetool agent diagnose <job_id>
nodetool agent diagnose <job_id> --json
nodetool agent diagnose <job_id> --trace-file trace.jsonl
Messages and spans come from a debug bundle in nodetool-debug/<job_id>-*/
when one exists. --trace-file wins over NODETOOL_TRACE_FILE, which wins over
the bundle’s own trace.jsonl. --api-url points the job lookup at a remote
server.
Output
# Capture the result, discard the trace
nodetool agent run -p openai -m gpt-5.4-mini -o "Task" 2>/dev/null > result.txt
# Machine-readable event stream on stderr
nodetool agent run -p openai -m gpt-5.4-mini -o "Task" --json 2>events.jsonl
API keys
Keys come from the secret store (nodetool secrets store OPENAI_API_KEY) or the
environment:
export OPENAI_API_KEY=sk-...
export ANTHROPIC_API_KEY=sk-ant-...
Chaining runs
nodetool agent run -p anthropic -m claude-sonnet-5 \
-o "Research topic X" > research.md
nodetool agent run -p anthropic -m claude-sonnet-5 \
-o "Write an article based on: $(cat research.md)"
Related Documentation
- Chat & Agents — Agent system overview
- Chat CLI — Interactive chat interface
- NodeTool CLI — Complete CLI reference