Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Setting Rules for AI

You’ve Probably Seen This Before

You ask the AI to “fix the login page styles.” 30 seconds later you check the code —

The AI didn’t just fix the styles. It also:

  • “Conveniently” refactored the entire login component directory structure
  • Switched CSS modules to Tailwind (your project doesn’t use Tailwind)
  • Deleted 3 test files it deemed “unnecessary”
  • Upgraded all dependencies in package.json to the latest versions

By the time you notice, the code has already been committed.

💡 The more capable the AI, the more it needs rules. Without boundaries, greater capability only causes greater damage.

Two Lines of Defense: Shepherd and Context

pi-atelier provides two layers of protection:

First Line: pi-shepherd — The Behavior Guard

Shepherd is a rule-driven event hook engine that checks AI actions before and after key moments — think of it as a security guard.

AI about to execute an action (tool call)
     │
     ▼
┌──────────────────────────────────┐
│     Shepherd tool_call hook      │
│   Check: Should it be done?      │
│          How should it be done?  │
└──────┬───────────────────────────┘
       │
   ┌───┴────┐
   │        │
  Allow   Rewrite/Block + Show Reason

... tool executes ...

┌──────────────────────────────────┐
│    Shepherd tool_result hook     │
│    Check: Any follow-up needed?  │
└──────┬───────────────────────────┘
       │
   Inject reminder / Append action

Supported hook timings:

HookWhen It TriggersTypical Use Case
tool_callBefore AI calls a toolRewrite commands, block dangerous operations
tool_resultAfter tool executionAuto-remind to run tests, lint checks
message_endAfter AI finishes replyingMatch AI response text, intercept wrong guesses
agent_endWhen AI finishes a conversationRemind to commit code, update memory
session_shutdownWhen a session closesClean up temporary data

Shepherd’s four actions:

ActionEffectTypical Use Case
blockPrevents tool executionBlock dangerous operations
notifyInjects a reminder into AI context“You edited a TS file, remember to run tests”
steerSilently injects guidance (not visible to user)Guide the AI to consult documentation
rewriteModifies tool call parametersAuto-prepend prefix to commands

Second Line: pi-context-manager — Information Quality & Diagnostics

Context Manager controls what information the AI sees, and also helps you diagnose token consumption issues.

Core capabilities:

  • Distill: Automatically compresses large tool outputs, preserving key information
  • Tool Result Processor: Formats and simplifies output from specific tools
  • Aging: Automatically evicts old tool outputs that haven’t been referenced in a while
  • Payload Analysis: Diagnoses where tokens are being spent with data
Tool returns large output (potentially 50KB)
     │
     ▼
┌────────────────────────┐
│   Context Manager       │
│   Distill + Processor   │
│   Compress to ~5KB      │
│   key information       │
└────────────────────────┘
     │
     ▼
AI sees refined information and makes better decisions

For detailed principles, see 3.3 Context Manager Deep Dive.

Real-World Examples: Preventing AI Mistakes

Scenario 1: Auto-Remind to Run Tests After Edit

{
	"comment": "[TypeScript] Must run tests after editing",
	"hook": "tool_result",
	"tool": "edit",
	"action": "notify",
	"conditions": [
		{ "field": "path", "pattern": "\\.ts$", "flags": "" }
	],
	"reason": "Edited a TypeScript file. You must run unit tests covering this code (add tests if none exist) and fix all test issues to ensure they pass.",
	"enabled": true
}

When the AI edits a .ts file, Shepherd automatically reminds the AI to run tests.

Scenario 2: Session-End Reminder to Commit Code

{
	"comment": "[Wrap-up] Remind to commit + update memory + summary after edits",
	"hook": "agent_end",
	"action": "notify",
	"conditions": [{ "builtin": "has_edits" }],
	"reason": "Detected file edits. Perform wrap-up:\n1️⃣ Git commit...\n2️⃣ Update memory...\n3️⃣ Session summary",
	"stopReason": ["stop"],
	"enabled": true
}

conditions: [{ builtin: "has_edits" }] means it only triggers when the session actually edited files. stopReason: ["stop"] means it only triggers when the AI ends normally (not when interrupted).

Scenario 3: Auto-Rewrite Commands

{
	"comment": "[rtk] Auto-proxy frequent bash commands",
	"tool": "bash",
	"action": "rewrite",
	"pattern": "^(git\\s+(status|log|diff)|cargo\\s+(test|build|clippy)|pytest)\\b",
	"flags": "",
	"reason": "rtk command rewrite: auto prepend rtk prefix to compress output",
	"enabled": true
}

When the AI tries to run commands like git status, Shepherd automatically rewrites it as rtk git status (rtk is an output compression tool).

Scenario 4: Code Style Check

{
	"comment": "[TS] No space indentation - TS files must use Tab",
	"hook": "tool_call",
	"tool": "edit",
	"action": "notify",
	"conditions": [
		{ "field": "path", "pattern": "\\.ts$", "flags": "" },
		{ "field": "text", "pattern": "\\n  [\\S ]", "flags": "" }
	],
	"reason": "❌ TS files require Tab indentation, not spaces. Please rewrite the code using Tab indentation.",
	"enabled": true
}

Both conditions must be met to trigger: the file is .ts and the code contains space indentation.

Scenario 5: Remind to Check Memory After Repeated Errors

{
	"comment": "[debug] Remind to check memory when tools repeatedly fail",
	"hook": "tool_result",
	"action": "steer",
	"state": { "countKind": "errors", "gte": 5 },
	"reason": "🔍 **Tools repeatedly failing**: Multiple consecutive failures. Check memory files under .pi/memory/ to see if there are existing records of this pitfall.",
	"enabled": true,
	"subagent": false
}

state implements state tracking — Shepherd remembers the error count and only triggers when it reaches the threshold. subagent: false means this rule does not trigger in sub-agents.

Shepherd Rule Configuration Reference

Rule File Locations

LevelPathDescription
Global defaultrules.json inside the extension packageBuilt-in rule set for Shepherd
Global custom~/.pi/agent/extensions/shepherd/rules.jsonGlobal custom rules (managed via the shepherd_rules tool)
Project-level.pi/shepherd-rules-*.json (project root)Custom project rules, can create multiple files

Rule file changes take effect immediately — no action needed.

Shepherd Rule Management

Rules can be managed in two ways:

  • shepherd_rules tool: Have AI safely add, update, or delete rules — includes write validation and rollback
  • Direct JSON editing: Global rules at ~/.pi/agent/extensions/shepherd/rules.json, project rules at .pi/extensions/shepherd-rules.json

Rule files take effect immediately after modification, no restart needed.

📖 For complete field reference and parameter docs, see pi-shepherd README.

Typical usage:

# Ask AI to add a rule for you
You: Add a rule to run cargo clippy after editing .rs files

AI calls shepherd_rules(action="add", rule={...})

# View project-level rules
AI calls shepherd_rules(action="list", scope="project")

Configuring Context

pi-context-manager provides the following commands:

CommandPurpose
/record [on|off]Toggle payload recording
/contextTUI panel: visualize context usage
/distill-config [N]View/set distill token threshold
/distill-config --cap [N]View/set first-seen full text cap (firstSeenCap, 0 = no cap)
/processor-config [N|off]View/set tool-result-processor threshold
/aging-config [N|off]View/set aging eviction rounds
/context-clean [sessionId]Clean up persistent data

💡 All commands show current config and usage when called without arguments. For example, entering /distill-config directly displays the current threshold and usage instructions.

For detailed principles, see 3.3 Context Manager Deep Dive.

Best Practices

✅ Good Rule Design

  • Precise conditions: Use conditions to narrow the trigger scope — don’t use a sledgehammer
  • Clear messaging: Tell the AI “why it’s not allowed” and “what to do instead”
  • Layered protection: Use block (enforced) for important matters, notify (advisory) for minor ones, steer (silent) for internal guidance
  • Make use of state tracking: Reminding after 3 consecutive errors is more effective than reminding every single time

❌ Bad Rule Design

  • Too frequent: notify on every tool call — the AI would be flooded with reminders
  • Too draconian: deny all bash commands — the AI can’t even run ls
  • Vague messaging: "reason": "Caution" — caution about what?
  • Ignoring sub-agents: Some rules should use "subagent": false to exclude sub-agent scenarios and avoid interfering with independent tasks

Rule Priority

When multiple rules match simultaneously:

  1. block > notify > steer (block > remind > silent guidance)
  2. At the same priority, rules execute in definition order within the rule file
  3. In the agent_end hook, rules whose check condition is not met are skipped

Next Up

With memory, planning, and rules in place, the AI is already a reliable assistant. But after a session accomplishes many things — how do you know exactly what it did? Which files were changed? What decisions were made?

In the next chapter, we’ll look at how to teach the AI to review its own work.

中文