Introduction
Voice is how the agent speaks. Behavior is what the agent does in specific moments. Both belong in SOUL.md, but behavior rules need more care: they are easy to over-specify, and over-specified behavior turns the agent into a rigid script.
Key Concepts
- Behavior rule: A directive about what the agent does in a specific category of situation.
- Trigger pattern: The condition that activates the rule (e.g., "before destructive shell commands").
- Default action: What the agent does when triggered.
- Escape hatch: How the user can override the rule in-session.
Real World Context
A developer wants the agent to confirm before destructive commands. They write into SOUL.md: "Always confirm before destructive commands." The agent does. They also notice the agent confirming before all shell commands, including ls, because the rule is too loose. They tighten it: "Confirm before commands that delete, overwrite, or modify state outside the current directory." Better. The pattern: behavior rules need precise triggers, or they over-fire.
Deep Dive
Behavior rules have three components: the trigger, the action, and (optionally) the escape hatch. All three matter.
The trigger specifies when the rule applies. Be specific. "Before destructive commands" is loose. "Before commands matching rm, rmdir, dd, mkfs, or git push --force" is specific. The looser the trigger, the more often the rule misfires.
The action specifies what the agent does when triggered. "Confirm" is a category, not an action. "Echo the exact command and wait for explicit 'yes' before running" is an action. The cleaner the action, the more predictable the agent.
The escape hatch specifies how the user overrides. "Unless the user has prefixed the command with 'force:'" is an escape hatch. Without one, behavior rules become friction. With one, they become safety nets that get out of the way when you do not need them.
Here is a sample SOUL.md behavior section that uses all three components:
markdown## Behavior - Before commands that delete or overwrite (rm, rmdir, dd, mkfs, git push --force, git reset --hard): echo the exact command and wait for an explicit 'yes' before running. Skip the prompt if the user prefixes the command with 'force:'. - When asked for an opinion on a design choice, give one. Do not hedge with 'it depends' unless you genuinely cannot decide. - When you do not know something, say 'I do not know' and offer to look it up. Do not fabricate.
Notice the structure: each rule has a trigger, an action, and (where useful) an escape hatch. The rules read like operational policies, not like personality descriptions.
A caveat: over-specifying behavior makes the agent rigid. If you write twenty rules, the agent starts to feel like a procedure rather than a collaborator. Three to five sharp rules cover most of what you need. The rest can stay implicit, governed by voice and values.
And remember: rules in SOUL.md apply everywhere. If a rule is project-specific ("in this repo, always run tests after edits"), put it in AGENTS.md instead. Global rules in SOUL.md, project rules in AGENTS.md.
Common Pitfalls
- Loose triggers: "Before destructive commands" misfires on
ls. Be specific about what counts. - No escape hatch: A safety rule with no override becomes friction. The user routes around it instead of trusting it.
Best Practices
- Three to five behavior rules total: Beyond that, the agent feels scripted.
- Test rules by counter-example: For each rule, ask "when would I want the agent to break this?" If the answer is "never," the rule is fine. If there is a reasonable exception, write the escape hatch.
Summary
- Behavior rules have three components: trigger, action, escape hatch.
- Loose triggers cause over-firing. Be specific about what counts.
- Three to five sharp rules suffice; more makes the agent feel scripted.
- Project-specific rules belong in
AGENTS.md, not inSOUL.md.
Code Examples
## Behavior
- Before commands matching `rm`, `rmdir`, `dd`, `mkfs`, `git push --force`,
or `git reset --hard`: echo the exact command and wait for an explicit
'yes' before running. Skip the prompt if the user prefixes with 'force:'.
- When asked for an opinion on a design choice, give one. Do not hedge
with 'it depends' unless you genuinely cannot decide.
- When you do not know something, say 'I do not know' and offer to look it
up. Do not fabricate.
- For tasks under 30 seconds of expected work, skip the plan and just do it.
For tasks over 5 minutes, propose a plan first and wait for confirmation.