Lesson14 min

Steering Agentic Behavior

Tuning action defaults, parallelism, and over-engineering tendencies when Claude acts rather than answers.

Answering vs acting

Everything so far steered what Claude says. Agentic use — Claude Code, tool-using API agents — steers what Claude does: which files it edits, which commands it runs, how much it builds. Acting has defaults just like writing style does, and the defaults may not match your intent. This lesson covers the four dials that matter most.

Dial 1: the action default

Claude infers whether you want action or discussion from your phrasing. "Change this function to use async/await" triggers edits. "Can you suggest some changes?" gets suggestions, no edits. That inference is usually right — but in a long working session you don't want to re-signal it every message. Set the default once, explicitly:

<default_to_action>
By default, implement changes rather than only suggesting them.
If intent is ambiguous, make the change.
</default_to_action>

Or the reverse, for cautious review sessions:

<do_not_act_before_instructions>
Do not edit any file until I explicitly say to implement.
Propose changes and wait for approval.
</do_not_act_before_instructions>

Pick per context: bias to action for solo prototyping, bias to proposals for shared or risky codebases.

Dial 2: parallel tool calls

An agent that reads five files one at a time takes five round trips; one that reads them simultaneously takes one. Claude parallelizes some of the time by default — an explicit instruction pushes it to near 100%:

<use_parallel_tool_calls>
When multiple independent tool calls are needed, make them all
simultaneously in one turn. Never guess a parameter that depends on
another call's result — sequence only genuinely dependent calls.
</use_parallel_tool_calls>

The second sentence is load-bearing. Parallelism is only safe for independent calls; a call whose input comes from another call's output must wait. State both halves, and you get speed without garbage parameters.

Dial 3: over-engineering

Left to its defaults, an agent asked for a 3-line bug fix may deliver the fix wrapped in a new helper module, with docstrings, configuration options, and defensive checks for inputs that can't occur. It reads as thoroughness; it's actually scope creep that you now have to review and maintain.

Counter it with explicit scope rules — this block, dropped into a repo's CLAUDE.md, is what stopped exactly that helper-module incident:

<scope_rules>
- Do not add features that were not requested.
- Do not add defensive code for scenarios that cannot occur.
- Do not create abstractions for one-time operations.
- The right amount of complexity is the minimum needed to solve
  the problem correctly.
</scope_rules>

A related failure is test-gaming: an agent that can't make tests pass legitimately may special-case the test inputs or "fix" the test instead of the code. Close that door explicitly:

Implement a solution that works for all valid inputs, not just the
test cases. Tests verify correctness — they don't define the
solution. If you believe a test is incorrect, tell me instead of
working around it.

Dial 4: investigate before answering

Agents hallucinate most when asked about code they haven't opened — answering from what similar codebases usually look like rather than what yours actually says. The fix is a hard rule:

<investigate_before_answering>
Never speculate about code you have not opened. If the question
references specific files, read them before answering. Investigate
first; answer only from what you observed.
</investigate_before_answering>

This trades a little latency for grounded answers — almost always the right trade when the answer will drive an edit.

Calibrate to the model generation

One meta-rule ties this together: newer models are more responsive to prompts, so steering written for older models can overshoot. Prompts of the "CRITICAL: YOU MUST ALWAYS..." variety were written to punch through older models' inattention. On current models that language causes overtriggering — tools invoked when they shouldn't be, rules applied where they don't belong, verification loops that never end.

When you upgrade models:

  • Dial emphasis down; state rules once, plainly.
  • Delete workarounds for weaknesses the model no longer has (the self-verification caveat from the thinking lesson is one example).
  • Re-run your eval set — steering, like any dependency, needs re-testing on upgrade.

The one-page summary

BehaviorSteering blockFailure it prevents
When to act<default_to_action> / <do_not_act_before_instructions>Suggestions when you wanted edits, or vice versa
Parallelism<use_parallel_tool_calls>Slow sequential tool calls
Scope<scope_rules>Unrequested features, defensive bloat
Test integritytests-verify-not-define ruleSpecial-cased "solutions"
Grounding<investigate_before_answering>Confident answers about unread code

Set these once — in a system prompt or CLAUDE.md — and every session inherits them. That's the difference between steering an agent and re-arguing with it.