Skip to content

Agent Step

Run the Tsumugi AI agent as a workflow step. The agent executes a multi-turn tool-calling loop — it reads files, runs commands, edits code, and searches the web to accomplish the task described in messages.

Basic Usage

yaml
steps:
  - name: analyze-logs
    type: agent
    messages:
      - role: user
        content: |
          Analyze the error logs at /var/log/app/errors.log from the last hour.
          Summarize the root causes and suggest fixes.
    output: ANALYSIS_RESULT

The agent uses the default model configured in Agent Settings (/settings/agent). No per-step model configuration is needed.

Configuration

The agent block is optional. When omitted, the step uses defaults from the global Agent Settings.

yaml
steps:
  - name: fix-config
    type: agent
    agent:
      model: claude-sonnet
      tools:
        enabled:
          - bash
          - read
          - patch
      prompt: |
        Focus only on files in /etc/app/.
      max_iterations: 30
      safe_mode: true
    messages:
      - role: user
        content: "Fix the invalid database_url in /etc/app/config.yaml"
    output: RESULT

agent Fields

FieldTypeDefaultDescription
modelstringglobal defaultModel ID from Agent Settings. Overrides the default model for this step.
toolsobjectTool selection and bash policy. See Tools.
memoryobject{ enabled: false }When enabled: true, loads global and per-DAG memory into the agent context.
promptstringAdditional instructions appended to the built-in system prompt.
max_iterationsint50Maximum tool-call rounds before the agent stops.
safe_modebooltrueWhen true, bash commands matching dangerous patterns require HITL approval.

Model Resolution

The agent step resolves its model from the global Agent Settings (configured at /settings/agent):

  1. If agent.model is set in the step, look up that model ID in the global ModelStore
  2. If agent.model is omitted, use the global default model (DefaultModelID from Agent Settings)
  3. If no default model is configured, the step fails with: "no model configured; set a default model in Agent Settings or specify agent.model in the step"

Model configuration (provider, API key, base URL) is managed entirely through Agent Settings. This avoids duplicating credentials in DAG files.

Tools

Available Tools

The agent step has access to these tools:

ToolDescription
bashExecute shell commands (timeout: 120s default, max 600s)
readRead file contents with line numbers (max 1MB, 2000 lines default)
patchCreate, edit, or delete files
thinkRecord reasoning without executing actions
read_schemaLook up DAG YAML schema documentation
web_searchSearch the internet via DuckDuckGo
outputWrite the final result to stdout (step-only, see Output Capture)

The navigate and ask_user tools are not available in agent steps because they require the Web UI.

See Tools Reference for full parameter documentation.

output Tool

The output tool is unique to agent steps. When the agent calls it, the content parameter is written directly to the step's stdout. This is how the step produces its output variable.

ParameterTypeRequiredDescription
contentstringYesThe final result to output. Cannot be empty.

The output tool is always included even if not listed in tools.enabled.

Tool Selection

Tools are filtered in two layers:

  1. Global policy (from Agent Settings): Tools disabled in the global ToolPolicy.Tools are removed. You cannot re-enable a globally-disabled tool at the step level.
  2. Step-level tools.enabled: If specified, only the listed tools are available (intersected with what's globally allowed).

When tools.enabled is omitted, all globally-enabled tools are available.

yaml
agent:
  tools:
    enabled:
      - bash
      - read
      - think

If read is disabled in global Agent Settings and the step specifies enabled: [bash, read], only bash and output will be available. The step does not produce a warning for this.

Bash Policy

Bash command policy rules are loaded from the global Agent Settings and enforced via a BeforeToolExecHook on every bash tool call. Rules are evaluated in order; the first matching rule determines the action.

Step-Level Bash Policy

The step can define its own bash policy rules via tools.bash_policy:

yaml
agent:
  tools:
    bash_policy:
      default_behavior: deny
      deny_behavior: block
      rules:
        - name: allow-read-commands
          pattern: "^(cat|head|tail|grep|find|ls)\\b"
          action: allow
        - name: deny-destructive
          pattern: "^(rm|chmod|chown|mkfs)\\b"
          action: deny
FieldTypeValuesDescription
default_behaviorstringallow, denyAction when no rule matches. Global default: allow.
deny_behaviorstringblock, hitlWhat happens when denied. hitl degrades to block in agent steps (no UI). Global default: ask_user (treated as block).
rules[].namestringHuman-readable rule name.
rules[].patternstringRegex pattern matched against each command segment. Required.
rules[].actionstringallow, denyAction when pattern matches. Required.

When a bash command is denied, the agent receives: "Blocked by policy: bash command denied by policy: {reason}".

Messages

At least one message is required. Validation fails with "agent step requires at least one message" if messages is empty.

Message content supports variable substitution with ${VAR} syntax. Variables are evaluated at runtime via runtime.EvalString:

yaml
params:
  - INPUT_FILE
  - OUTPUT_DIR

steps:
  - name: process
    type: agent
    messages:
      - role: user
        content: "Analyze ${INPUT_FILE} and write results to ${OUTPUT_DIR}"
    output: RESULT

Execution

The agent runs as a single-shot loop. It processes the user messages, calls tools as needed, and stops when either:

  • The agent finishes processing with no more tool calls (normal completion)
  • max_iterations is reached (the loop is cancelled)

Stderr Logging

All agent activity is logged to stderr with [agent] prefix. This keeps stdout clean for output capture.

[agent] Starting (model: Claude Sonnet, tools: 7, safe_mode: true, max_iterations: 50)
[agent] Tool call: bash {"command":"ls -la /var/log/app/"}
[agent] Tool result: [success, 1234 chars]
[agent] Assistant: I found the following log files...
[agent] Tool call: read {"path":"/var/log/app/errors.log","limit":100}
[agent] Tool result: [success, 5678 chars]
[agent] Completed (2 iterations)

Tool call arguments are truncated at 200 characters. Assistant content is truncated at 500 characters with newlines replaced by spaces.

Output Capture

The step's output field captures whatever the agent writes to stdout via the output tool:

yaml
steps:
  - name: analyze
    type: agent
    messages:
      - role: user
        content: "Count the number of .go files in this directory"
    output: FILE_COUNT

  - name: report
    command: echo "Found ${FILE_COUNT} Go files"
    depends: [analyze]

The agent is instructed (via system prompt) to call the output tool with its final result. The content is written directly to stdout and captured by the output field.

If the agent never calls the output tool, the output variable will be empty.

Examples

Minimal

yaml
steps:
  - name: summarize
    type: agent
    messages:
      - role: user
        content: "Summarize the README.md in this repository"
    output: SUMMARY

With Model Override

yaml
steps:
  - name: review
    type: agent
    agent:
      model: claude-opus
    messages:
      - role: user
        content: "Review the code in src/main.go for bugs and security issues"
    output: REVIEW

Restricted Tools

yaml
steps:
  - name: read-only-analysis
    type: agent
    agent:
      tools:
        enabled:
          - read
          - think
      safe_mode: false
    messages:
      - role: user
        content: "Analyze the architecture of this codebase without modifying anything"
    output: ANALYSIS

With Bash Policy

yaml
steps:
  - name: deploy-check
    type: agent
    agent:
      tools:
        bash_policy:
          default_behavior: deny
          deny_behavior: block
          rules:
            - name: allow-status-commands
              pattern: "^(kubectl get|kubectl describe|helm status)\\b"
              action: allow
      prompt: |
        Check the deployment status of the staging environment.
        Only use read-only kubectl and helm commands.
      max_iterations: 20
    messages:
      - role: user
        content: "Report the health of all pods in the staging namespace"
    output: HEALTH_REPORT

Pipeline with Multiple Agent Steps

yaml
params:
  - REPO_PATH

steps:
  - name: analyze
    type: agent
    messages:
      - role: user
        content: "Analyze the test coverage of ${REPO_PATH} and identify untested code paths"
    output: COVERAGE_ANALYSIS

  - name: write-tests
    type: agent
    agent:
      model: claude-opus
      max_iterations: 100
    messages:
      - role: user
        content: |
          Based on this analysis:
          ${COVERAGE_ANALYSIS}

          Write unit tests for the untested code paths in ${REPO_PATH}.
    depends: [analyze]
    output: TEST_RESULT

Graph DAG with Agent and HITL

yaml
type: graph

steps:
  - name: draft
    type: agent
    messages:
      - role: user
        content: "Draft a migration plan for upgrading the database from v3 to v4"
    output: MIGRATION_PLAN

  - name: approve
    type: hitl
    config:
      prompt: "Review the migration plan and approve if acceptable"
    depends: [draft]

  - name: execute
    type: agent
    agent:
      safe_mode: true
    messages:
      - role: user
        content: "Execute the approved migration plan: ${MIGRATION_PLAN}"
    depends: [approve]

See Also

  • Agent Overview — Web UI agent with sessions and interactive tools
  • Tools Reference — Full parameter documentation for each tool
  • Chat & AI Agentstype: chat for simple LLM calls with DAG-based tools
  • HITL — Human-in-the-loop approval steps
  • Data Flow — Passing data between steps with output

Released under the MIT License.