Skip to content

agent steps

kadyapam edited this page Oct 17, 2026 · 4 revisions

kind: agent in the local runtime

noetl run --runtime local executes kind: agent steps since 5.1.0 (#95). Cost controls arrived in 5.3.0 (#97). The agent loop itself lives in noetl-tools (AgentTool); this page covers what the CLI adds around it.

Where the code is

Piece Source
YAML shape: Tool::Agent executor/src/playbook.rs
Config mapping + session start: to_tools_config agent arm, start_agent_session executor/src/tools_bridge.rs
Turn loop + tool calls: Tool::Agent arm, run_agent_tool_call, defang_template_markers src/playbook_runner.rs
Local capability: "agent" in RuntimeCapabilities::local() executor/src/playbook.rs

Execution

  1. Render. String fields (framework, model, prompt, system, endpoint, claude_bin, workdir, thinking, effort, mcp_config entries) and the YAML tools / auth blocks are rendered against the step context.
  2. Start. start_agent_session maps auth: to the noetl-tools AuthConfig. A credential: alias resolves through the local credential store. AgentSession::start enforces auth: per framework: required for claude, refused for claude-code.
  3. Loop. Each next_turn is one block_in_place + block_on. Tool calls run between turns, outside any block_on, which is why the session is turn-by-turn.
  4. Tools. run_agent_tool_call looks up the tool by name, resolves its playbook: binding relative to the agent playbook, and runs it with a fresh PlaybookRunner (quiet/verbose inherited). Its final_result (or its step results, or its error) becomes the tool result. A failing tool returns is_error: true to the model; it doesn't fail the step.
  5. Result. The session's final JSON is stored as the step result.

dispatch_via_registry refuses Tool::Agent ("agent steps are driven by the runner via start_agent_session"). Routing an agent step through the registry would answer its tool calls with nothing.

Model output is data

Values the model passes to a tool become the sub-playbook's workload.<key> verbatim, never rendered. They also go through defang_template_markers ({{ → { {). That was needed because template::render_template re-expanded substituted values up to 5.3.0, so {{ workload.secret }} inside an email quoted by the model would have been expanded by the tool playbook's own templates. 5.3.1 makes render_template single-pass (#98). 5.3.2 (#100, noetl/ai-meta#477) stops noetl-tools from rendering the CLI-rendered shell / http config a second time: the bridge escapes it before dispatch. Data containing {{ … }} now reaches the tool unchanged. The defang stays as defence in depth.

Fields added in 5.3.0

thinking (disabled | adaptive), effort (low | medium | high) and prompt_cache (bool) pass through to the tool only when set. See AgentTool for their effect.

Versions

CLI noetl-executor noetl-tools Agent change
5.1.0 0.11.0 4.1 Tool::Agent, local capability, runner loop
5.2.0 0.12.0 4.1 credentials via the store (env or 600 file)
5.3.0 0.13.0 4.2 thinking / effort / prompt_cache
5.3.1 0.13.1 4.2 single-pass render_template (#98)
5.3.2 0.13.2 4.2 bridged shell / http config rendered once, not again by noetl-tools (#100)

Tests

tests/agent_local.rs (wiremock Messages API + a fake claude binary) covers:

  • a tool call answered by a sub-playbook;
  • the defang;
  • a claude-code step without auth:.

Bridge unit tests in tools_bridge.rs cover the config mapping, refused registry dispatch, and missing or blank credentials.

Related

Credentials · Executor crate · showcase: noetl/agent-playbooks · tracking: noetl/ai-meta#474

Clone this wiki locally