Skip to content

Agentic Step Patterns

When to use bash, agent, and recipe step types in YAML recipes, and how to write effective agent prompts.

Contents


Decision rule

Default to agent steps. Use bash only for deterministic operations (git commands, file checks, API calls with known output). Use recipe to compose larger workflows from smaller ones.

The reasoning: agent steps handle ambiguity, adapt to unexpected input, and produce richer output. Bash steps are brittle when the output format or error conditions vary.

Step types

Type Executor Output Timeout default
bash Shell subprocess stdout captured to output key 120s
agent Claude/Copilot session Full response captured to output key default_step_timeout (recipe-level)
recipe Nested recipe-runner-rs invocation Final context from sub-recipe Inherits from sub-recipe

When to use each type

bash — Deterministic, verifiable operations

Use when: - Running git commands (branch, commit, push, status) - Checking file existence or reading structured output - Calling APIs with predictable JSON responses (gh issue view) - Setting up environment (mkdir, export, install)

- id: "create-branch"
  type: "bash"
  command: |
    cd "$REPO_PATH"
    git checkout -b "feat/$BRANCH_NAME" 2>/dev/null || git checkout "feat/$BRANCH_NAME"
  output: "branch_result"

agent — Reasoning, analysis, generation

Use when: - Analyzing requirements or code - Generating code, tests, or documentation - Making design decisions - Evaluating quality or correctness - Anything requiring natural language understanding

- id: "design-solution"
  type: "agent"
  prompt: |
    Design an implementation for the following requirement.

    **Task**: {{task_description}}
    **Requirements**: {{final_requirements}}
    **Constraints**: Rust codebase, must maintain backward compatibility.

    Output a concrete file-by-file implementation plan.
  output: "design"

recipe — Workflow composition

Use when: - A step is itself a multi-step workflow (e.g., running default-workflow from within smart-orchestrator) - Reusing an existing recipe as a building block - Isolating a complex sub-task with its own context

- id: "run-default-workflow"
  type: "recipe"
  recipe: "default-workflow"
  context:
    task_description: "{{task_description}}"
    repo_path: "{{repo_path}}"

Prompt writing guide

Agent steps live or die by their prompts. Follow these rules:

1. State the goal, not the process

# Good: what to achieve
prompt: "Identify all public functions in {{file_path}} that lack test coverage."

# Bad: how to do it
prompt: "Read the file, then grep for fn, then check if tests exist..."

2. Provide full context via interpolation

Every {{variable}} referenced must be a context key populated by a prior step. Never assume the agent remembers prior steps — each agent session starts fresh.

3. Specify output format when downstream steps parse it

prompt: |
    Classify this task.
    Respond with EXACTLY one line: `Development` or `Investigation` or `Q&A`.
output: "task_type"

4. Timeout strategy

Agent steps in the default-workflow recipes run without timeout_seconds. Agent reasoning is inherently variable-duration — architecture design may take 30 seconds or 30 minutes depending on complexity. Hard timeouts cause premature kills that waste all prior work.

For CI environments with wall-clock budgets, use --step-timeout <SECONDS> or --no-step-timeouts at invocation time rather than embedding timeouts in YAML. See Control step timeouts.

Anti-patterns

Anti-pattern Problem Fix
Bash step that parses natural language Fragile regex on free-form text Use an agent step
Agent step for git checkout Wastes tokens on deterministic work Use a bash step
Agent prompt without context vars Agent has no information to work with Interpolate {{variables}}
Nested recipe without forwarding context Sub-recipe runs with empty context Pass required context explicitly
Hard timeout_seconds on agent step Premature kill wastes all prior agent work Omit timeout_seconds; use --step-timeout at invocation time if a wall-clock budget is required

Example recipe sequence

From default-workflow.yaml, a typical sequence mixing all three types:

steps:
  # 1. Bash: create GitHub issue (deterministic API call)
  - id: "create-issue"
    type: "bash"
    command: "gh issue create --title '...' --body '...'"
    output: "issue_url"

  # 2. Agent: design the solution (reasoning required)
  - id: "design"
    type: "agent"
    prompt: "Design implementation for: {{task_description}}"
    output: "design_spec"

  # 3. Agent: implement the code (generation required)
  - id: "implement"
    type: "agent"
    prompt: "Implement the design: {{design_spec}}"
    output: "implementation"

  # 4. Bash: run tests (deterministic command)
  - id: "test"
    type: "bash"
    command: "cargo test 2>&1"
    output: "test_results"

  # 5. Agent: evaluate results (judgment required)
  - id: "review"
    type: "agent"
    prompt: "Review test results: {{test_results}}"
    output: "review"