Chapter 1 —- The Loop
- Figure 1.1 —- Where This Chapter Lives
- Figure 1.2 —- A Concrete Trace
- What the Loop Is Not
- The Entry Points
- Figure 1.3 —- The Two Loops
- Figure 1.4 —- The Turn, Step by Step
AgentContext: The Loop’s View of the WorldAgentLoopConfig: The Loop’s Extension Points- Events: The Only Observable Output
- Design Note: Why a Pure Function?
- Summary: What the Loop Actually Does
Chapter 2 —- The Stateful Agent
- Figure 2.1 —- Who Owns What
- Figure 2.2 —- Two Messages, Two Queues
- Before the Code: The Problem with a Pure Function
- What
AgentOwns subscribeandprocessEventsprompt()vscontinue()- The Dual-Queue Model
abort()and What Happens to In-Flight Tool CallsrunWithLifecycle: The Run Boundary- Failure Handling:
handleRunFailure createContextSnapshotandcreateLoopConfig- Figure 2.3 —- One Run, Start to Finish
- Design Note: Why Not Subclass
Agent? - Summary
Chapter 2.5 —- The Session Layer (AgentSession)
- Figure 2.5.1 —- The Full Stack, Top to Bottom
- The Gap Between the Kernel and a Real Application
- The Package Boundary
- What
AgentSessionOwns - Constructor: Wiring the Kernel
_installAgentToolHooks_handleAgentEvent: The Session’s View of Every Eventprompt()at the Session Layer_rebuildSystemPrompt: What Goes Into Every PromptAgentSessionEvent: A Richer Event UnioncreateAgentSessionandcreateAgentSessionServices- Design Note: Why Composition, Not Subclassing
- Summary: The Layer Stack
Chapter 3 —- The Tool Call Cycle
- Figure 3.1 —- One Tool Call, Start to Finish
- Figure 3.2 —- A Batch of Tool Calls
- Before the Code: A Concrete
bashTrace - Phase 1: Argument Arrival (Streaming Deltas)
- Phase 2: Routing — Sequential or Parallel?
- Phase 3:
prepareToolCall— Validation and thebeforeToolCallHook - Phase 4:
executePreparedToolCall— Execution and Streaming Updates - Phase 5:
finalizeExecutedToolCall— TheafterToolCallHook - Phase 6: Emitting the Result
- Phase 7: Truncated-Message Safety
- The
terminatePattern - Parallel Execution: How Events Interleave
- Design Note: Tool Errors as First-Class Results
- Summary: The Seven Phases
Chapter 3.5 —- The Streaming Pipeline
- Figure 3.5.1 —- Where the Pipeline Sits
- Figure 3.5.2 —- One Tool Call, Every Event
- Why the LLM Produces Tool Call Blocks At All
- The
StreamFnContract AssistantMessageEventStreamInternals- The Event Protocol
- How
streamAssistantResponseConsumes the Stream convertToLlm: Projecting the TranscripttransformContext: Pre-Projection RewritingstopReasonand Loop Branching- A Concrete Trace: Single Tool Call
- What Happens If the Stream Is Cut Mid-Token
- Design Note: Why “Never Throw” Is a Hard Contract
- Summary
Chapter 4 —- Defining Tools
- A Tool Call Arrives: What the Loop Needs
- Figure 4.1 —- Two Levels of Tool Abstraction
- Two Levels:
AgentToolvsToolDefinition AgentToolResult: WhatexecuteReturns- The Seven Built-In Tools: Design Case Studies
executionMode: When Sequential Ordering MatterspromptSnippetandpromptGuidelines: Tools Advertising Themselves- Design Principle:
executeIs Arbitrary Code - Closing Pattern: Sub-Agents as a Tool
- Summary
Chapter 5 —- The System Prompt as a Living Document
- Figure 5.1 —- Where Each Section Comes From
- The Problem with a Fixed System Prompt
- What
buildSystemPromptAssembles - The Guidelines Deduplication Rule
- Context Files:
AGENTS.mdas Project-Scoped Instructions - Skills: Progressive Disclosure via the System Prompt
_rebuildSystemPrompt: Assembling from Live State- The Three Prompt Sources: Base, Append, Override
- A Concrete Walk-Through: What the Model Sees
- Design Note: Why Rebuild Rather Than Patch
- Summary
Chapter 6 —- Provider Abstraction
- A Concrete Failure to Open With
- Figure 6.1 —- The Three Layers
Provider: The Unit of Stream BehaviourModels: Auth Resolution and DispatchModelRuntime: The Coding-Agent Layer- Auto-Retry and Backoff
- Design Note: Two Layers, Not One
- Summary
Chapter 7 —- Authentication
- A Concrete Failure: OAuth Token Expired Mid-Session
- The Credential Resolution Chain
- OAuth: Double-Checked Locking for Token Refresh
- API Keys: Stored, Ambient, and Interpolated
RuntimeCredentials: Session-Scoped Key OverlayAuthStorage: Theauth.jsonFile Store- The Two
ModelsErrorCodes - Design Note: Why Auth Lives in
packages/ai, Not the Agent - Summary
Chapter 8 —- Session Persistence
- A Concrete Failure: Losing the Conversation
- Figure 8.1 —- Who Owns the Session
- The File Format: A Minimal Two-Turn Session
- Entry Types
- The DAG: Why a Tree, Not a List
- The Lazy-Write Contract
buildSessionContext(): Reconstructing the Conversation- Compaction Entries and the
firstKeptEntryIdPointer - Session Discovery and the Directory Convention
- Session Forking and Cross-Project History
- Version Migrations
- Design Note: Append-Only vs. Mutable State
- Summary
Chapter 9 —- Compaction: Managing the Context Window
- A Concrete Overflow: The Session That Stops Itself
- The Three Triggers
prepareCompaction: Choosing What to Summarisecompact(): Generating the Summary- Applying the Compaction:
appendCompactionand State Rebuild - The
session_before_compactExtension Hook - Token Estimation: When the Provider Doesn’t Report Usage
- Design Note: Incremental Summaries vs Full Regeneration
- Summary
Chapter 10 —- The Extension System
- A Concrete Extension: Auto-commit After Every Turn
- What an Extension Is
- The Hook Phase Table
ExtensionRunner: Routing Events to Multiple Extensionsinvalidate(): Stale Context Detection- Registered Tools: The Same Hook Chain
- Provider Registration
- Design Note: Why One
ExtensionContextPer Call - Summary
Chapter 11 —- The Skill System
- The Problem: Context Is Finite
- Figure 11.1 —- The Layers
- A Concrete Trace
- Skill File Format
- Discovery: Where Pi Looks
- Injecting Skills into the System Prompt
- Explicit Invocation:
/skill:name - Name Collision Resolution
- Skills vs Extensions
- Design Note: Why Descriptions, Not Keywords
- Summary
Chapter 11.5 —- Building a Real Skill: Auto-Downloading Udemy Courses
- The Problem: Automation Meets External Tooling
- A Concrete Trace
- Anatomy of the Udemy Skill
- What Makes This a Good Skill
- The Token Budget Trade-off
- disableModelInvocation: Opt-In Only Skills
- Extending the Skill: Listing and Searching
- Skill Placement: Project vs Global
- Pattern: The Skill as a Thin Orchestration Layer
- Summary
Chapter 12 —- Three Run Modes
- The Same Session, Three Surfaces
- Figure 12.1 —- One Session, Three Dispatchers
- Mode Resolution
- Print Mode (
runPrintMode) - RPC Mode (
runRpcMode) - Interactive Mode
- The Shared Contract
- Design Note: Why One
AgentSession, Not Three - Summary
Chapter 13 —- Sandboxing and Safety
- What an Unsandboxed Agent Can Do
- The
BashOperationsAbstraction - Three Containment Patterns
- Threat/Mitigation Matrix
- The
tool_callHook as a Policy Layer - Why No Built-in Sandbox
- Summary
Chapter 14 —- Supply Chain and Release Hardening
- The Threat Model
- Figure 14.1 —- The Defence Layers
- Exact-Version Pinning
- The Age Gate
npm-shrinkwrap.jsonand the Lifecycle-Script Allowlist- The Release Script
- CI: OIDC Trusted Publishing
- The R2 Version Marker
- Lockfile Commit Policy
- Why All of This Together
- Summary
Chapter 15 —- Use Case 1: Context Engineering
- The Model Has No Memory
- A Concrete Trace: What the Model Sees
- The Six Levers
- How the Levers Compose
- The !-Prefix Escape Hatch
- Practical Patterns
- Summary
Chapter 16 —- How Pi’s AgentHarness Actually Works
- 1. The Five Problems a Harness Solves
- 2.
AgentHarness— The Entry Point - 3.
ExecutionEnv— The Capability Boundary - 4.
Session,SessionStorage,SessionTree— The Storage Abstraction - 5. Records and
reduceLaneState—- Crash Recovery - 6. The Agent Loop vs. The Harness Executor
- 7. Hooks and Events — Observability Without Coupling
- 8.
Result,TaggedError, and the Two Error Layers - 9. Synthesis: A Dependency Inversion Checklist
- 10. Summary
Chapter 17 —- Integrating Pi into Organizational Workflows
- The Integration Problem
- What Pi Provides
- Three Levels of Pi Integration
- Where Intelligence Belongs
- Workflow Patterns
- Workflow 1: Automated PR Review
- Workflow 2: Spec -> Code -> Test
- Workflow 3: Planner + Editors
- Workflow 4: SonicWall Engineering Agent
- Declarative Workflow vs Programmatic Orchestration
- Human Approval as a First-Class Workflow Stage
- Cross-Cutting Patterns for Programmatic Integrations
- Observability
- What Pi Does Not Provide
- Designing an Agentic Workflow
- Automation and Intelligence
- SonicWall Target Architecture
- Summary
Chapter 18 —- Turning Domain Knowledge into Agent Capabilities
- The Generic/Correct Gap
- Gap-First Diagnosis
- When Not to Write a Skill
- What a Skill Actually Encodes
- Use Cases
- Skill Granularity
- Measuring Whether a Skill Works
- Skill Maintenance
- Connecting Skills, Tools, Policies, and Workflows
- Designing a Skill Portfolio
- Summary
Chapter 19 —- MCP and External Tools: A Case Study
- Why Pi Has No Built-In MCP
- The Tool Integration Decision
- Case Study: Jira Search
- Get one issue
- Use JQL directly
jira-search.py
Usage: ./jira-search.py “”
Requires: JIRA_URL, JIRA_USER, JIRA_API_TOKEN env vars
- name: jira-search description: Search Jira issues using JQL. Use when the user asks about open issues, bug assignments, sprint status, or anything in Jira. Requires JIRA_URL, JIRA_USER, and JIRA_API_TOKEN environment variables.
Jira Search
- Search for issues
- Typical queries