How AI Agents WorkCourse map

Chapter 17b · Real systems

Comparison table

Pi, Deep Agents, and Hermes side by side, concept by concept, with the mechanism and the source behind every cell.

How to read the table

Take the Memory row. Hermes is marked Built in, because two small memory files are always in its prompt. Deep Agents is marked Optional, because memory works once you pass memory files and give them durable storage. Pi is marked Not built in, because it has no memory system, and saved sessions and plain files do that job instead. So the badge says whether a feature ships, and the short text says what it is. Open "How it works" under a cell for the mechanism and the source.

The cells describe Pi 1.3.0, the Deep Agents Python SDK 0.7.28, and Hermes Agent v0.22.2, from research notes checked on 2026-10-19. The three are different kinds of product. Pi is a CLI plus packages you can import. Deep Agents is a library you call from your code, and the table describes the library unless a cell names its separate CLI, dcode. Hermes is an application you configure. Chapter 17 profiles each one in full.

The Philosophy row shows the kind of product instead of a support level, and the last row has no badge.

Pi, Deep Agents, and Hermes side by side

Column switches need JavaScript. Without it, the table below shows every system. Scroll it sideways if it is wider than your screen.

Three systems compared (2026-10-19)
Concept Pi 1.3.0 Deep Agents 0.7.28 Hermes v0.22.2
Philosophy CLI and packages

A small core on purpose. It ships a loop, four tools, sessions, and skills, and you, or Pi itself, add more as extensions.

How it works

Subagents, plan mode, permission popups, and to-do lists stay out of the core. Earendil: "We wait until something has proven itself, and only then do we consider adopting it."

Sources: pi.dev; "Pi 1.0" (2026-10-01).

Python library

A ready-made harness on LangChain and LangGraph. Every part can be replaced, and defaults are dropped when tests show no gain.

How it works

create_deep_agent() assembles middleware and calls LangChain's create_agent(), so there is no new runtime. The empty default prompt and the opt-in todo tool both followed experiments.

Sources: Deep Agents overview; PR #4929.

Application

A personal assistant that improves itself. One agent core serves every app, and new abilities come as skills, plugins, or MCP servers.

How it works

The repo guide makes the prompt cache a priority: nothing in the cached prompt changes mid-session except at compaction. It also keeps the core small, so new abilities arrive as skills, plugins, or MCP servers rather than new core tools.

Sources: AGENTS.md (v0.22.2); architecture doc.

Agent loop Built in

Runs tool calls in parallel, and repeats while tool calls or queued messages remain. No step limit found.

How it works

Two nested loops: the inner one handles tool calls and steering messages, and the outer one handles messages queued for after the task. If a reply hits the output limit, its tool calls fail instead of running, because their arguments may be cut off.

Source: agent-loop.ts (1.3.0).

Built in

LangChain's loop, run as a LangGraph graph. It ends when a reply has no tool calls; the recursion limit is 9,999 steps.

How it works

Each tool call from one reply runs as its own task in the same step. Middleware runs before and after each model call and around each tool call.

Sources: factory.py (langchain 1.4.6); graph.py.

Built in

One loop per user message. It ends on a reply with no tool calls, with no step limit within a turn by default.

How it works

Other limits remain: a watchdog stops a turn after 600 seconds without progress, guards warn about a call that keeps failing, and per-turn caps limit web searches and subagent spawns. If the model says it will act but calls no tool, Hermes nudges it, at most twice per turn.

Sources: agent loop doc; config_defaults.py.

State Built in

One append-only JSONL file per session, shaped as a tree. The current branch is rebuilt into context for each request.

How it works

Each entry has an id and a parentId. Prompt and tool changes are entries too, so a branch replays exactly what the model saw.

Source: session-format.md.

Built in

A typed dictionary kept per conversation thread: messages, files, and fields that middleware adds.

How it works

Messages are saved as changes, with a full snapshot every 50 steps, so saved state grows linearly on long threads. Private fields are removed before state goes to a subagent.

Sources: graph.py; backends doc.

Built in

A message list during the turn. One SQLite database per profile stores every session, and memory and skills are text files.

How it works

The database keeps each session's exact system prompt and its hash. A resumed session reuses that prompt, so its start stays eligible for the provider's cache, subject to the provider's retention time, routing, and rules.

Source: session storage doc.

Context Built in

A short prompt, AGENTS.md files, and a skills list. Near the window limit, older entries are summarized.

How it works

Compaction starts at the window size minus 16,384 tokens and keeps about 20,000 recent tokens word for word. It never separates a tool call from its result, and the original entries stay in the file.

Source: compaction.md.

Built in

Your prompt, plus skills and memory files if you configure them. Big tool results go to files, and long histories become a summary.

How it works

Tool results above about 80,000 characters (20,000 tokens at 4 characters each) are saved under /large_tool_results/, with a preview of the first and last 5 lines. The built-in file tools are exempt. Summarization starts at 85% of the input limit in the model's profile, or at 170,000 tokens with no profile. The summary replaces old messages only in what the model sees, and the state keeps every original.

Sources, at commit 12f70f2: _message_eviction.py; filesystem.py; summarization.py.

Built in

A system prompt frozen per session, with changing parts in the user message. A second model summarizes the middle of long chats.

How it works

Compaction starts at 50% of the window, or at least 75% for windows under 512K tokens. The old rows stay in the database, marked compacted and still searchable.

Source: compression and caching doc.

Tools Built in

read, bash, edit, and write by default. Extensions add or replace tools, and MCP tools are reached through scripts or search.

How it works

read and bash output stops at 2,000 lines or 50 KB. read can page through a long file, and bash saves its full output to a temp file. A result has a part for the model and a part for the screen that the model never sees.

Sources: cli.md; tool code; mcp.md.

Built in

File tools, a shell tool that needs a command-capable backend, and task for subagents. Your own functions and MCP tools join them.

How it works

grep matches literal text and stops at 1,000 matches. A second write to the same path in one reply is refused.

Source: tools doc.

Built in

Tools register themselves and hide when a key is missing. Rare tools load on demand, and the shell runs on 7 backends.

How it works

Read-only calls in one reply run in parallel, and writes join only if their paths do not overlap. execute_code runs a Python script that calls tools, and only its printed output comes back.

Sources: tools runtime doc; tool search doc.

Planning Extension or custom

No plan mode and no to-do tool. Plans go in files, or in an optional extension.

How it works

Pi's creator: "to-do lists generally confuse models more than they help." An example plan-mode extension makes the tools read-only and tracks numbered steps.

Sources: design post (2025-11-30); plan-mode example.

Optional

write_todos left the standard defaults in 0.7.0, though the built-in Codex profiles still add it. It replaces a list in state, and nothing enforces the list.

How it works

The only rule checked is one write_todos call per reply. A test on three models found no statistically significant accuracy gain from the tool.

Sources: todo.py (langchain 1.4.6); PR #4929; Codex profile.

Built in

A todo_list tool (found through tool search), a /plan mode enforced only by the prompt, and a /goal loop with a judge.

How it works

With /goal, another model answers done, continue, or blocked after each turn, for up to 20 turns by default. If the judge fails, the loop continues, and the turn limit stops it.

Source: goals doc.

Memory Not built in

No memory system. Saved sessions, AGENTS.md files, files the agent writes, and skills do the job.

How it works

Pi's creator gathers context in one session, writes it to a file, and starts a fresh session from it. An example handoff extension automates this.

Sources: design post; handoff example.

Optional

Short-term: the thread's saved state. Long-term: files routed to a LangGraph store, with AGENTS.md put into the prompt.

How it works

The store can be scoped per user or per assistant. The docs warn that shared memory the agent can write is a prompt-injection path.

Sources: memory doc; going to production doc.

Built in

Two small files the agent writes (2,200 and 1,375 characters), always in the prompt. Keyword search over past sessions.

How it works

New entries reach the prompt only in the next session, to protect the cache. A review step fires after 10 user turns without a memory write.

Source: memory doc.

Skills Built in

Agent Skills folders. The prompt lists each name, description, and path, and the model reads the file when needed.

How it works

/skill:name loads a skill by hand. Skills in the project's .pi/skills/ folder load only after you trust the project.

Source: skills.md.

Optional

Agent Skills folders you pass in. The prompt lists each name, description, and path, and the model reads the file when needed.

How it works

Skills are scanned once per thread. A skill can list tools that appear only after the skill is read.

Source: skills doc.

Built in

SKILL.md folders, listed by name in the prompt and loaded on demand. The agent writes and edits its own skills.

How it works

A review step fires after 10 or more tool-using steps without a skill write. A curator archives unused agent-written skills after 30 days and never deletes them.

Sources: skills doc; curator doc.

Subagents Extension or custom

Not built in. Run pi again through bash, or use the example extension that starts separate pi processes.

How it works

The example runs one task, several in parallel (up to 8, 4 at a time), or a chain, and caps each result at 50 KB. Pi's creator argues that built-in subagents hide their work from the user.

Sources: subagent example; design post.

Built in

The task tool runs a child that starts fresh and returns only its final message. Children share the parent's files.

How it works

The parent waits for each child, and runs several in parallel by calling task more than once in one reply. Children cannot start their own subagents by default.

Source: subagents doc.

Built in

delegate_task starts children with a fresh context, no memory, and fewer tools. They run in the background by default.

How it works

By default up to 10 run at once, one level deep, and both limits are settings. A summary of at most 24,000 characters comes back later as a new message. A child that was running during a crash is marked unknown.

Source: delegation doc.

Sandbox Not built in

None. Pi runs with your permissions, and the docs recommend a container or VM.

How it works

The docs name Docker, Docker Sandboxes, OpenShell, and the Gondolin micro-VM. An example extension wraps bash in an OS sandbox with a list of allowed domains.

Sources: security.md; containerization.md.

Optional

No shell by default. A command-capable backend can be an isolated sandbox, or a local shell with no isolation.

How it works

Sandbox providers include LangSmith, Daytona, Modal, and Runloop. The local shell backend runs commands on your machine with no isolation. The docs say: "Never put secrets inside a sandbox."

Sources: sandboxes doc; backends doc; local_shell.py.

Built in

The shell runs locally or in Docker and other sandboxes. Inside a container, the container replaces command approval.

How it works

Docker runs with all Linux capabilities dropped and a limit of 256 processes. Deny rules still apply inside containers. The docs call the file write guards "defense-in-depth, not a hard boundary".

Source: security doc.

Persistence Built in

Every session is saved as JSONL. You can resume, branch, fork, export, or share it.

How it works

Branching rewinds the conversation, not the files on disk. Resuming a turn that crashed is the goal of Pi Durable, an experimental separate package.

Sources: sessions.md; Pi Durable README.

Optional

LangGraph saves every step of a thread if you pass a checkpointer. A store keeps files across threads.

How it works

A saved run resumes after a crash without redoing finished steps, and it can wait for approval as long as needed. dcode keeps its sessions in SQLite.

Sources: going to production doc; LangGraph persistence doc.

Built in

Sessions in SQLite survive restarts. Optional file snapshots in a hidden git store, cron jobs, and a Kanban board.

How it works

Hermes writes each message during the turn. /rollback restores files and undoes the last chat turn.

Sources: session storage doc; checkpoints doc.

Human approval Extension or custom

No approval prompts, only a project-trust question. Extensions can block or confirm calls.

How it works

If a gating extension crashes, Pi blocks the call. Example extensions confirm rm -rf and sudo, and protect .env and .git.

Sources: extensions.md; security.md.

Optional

interrupt_on pauses before the tools you name: approve, edit, reject, or respond. File path rules can allow, deny, or ask.

How it works

All gated calls in one reply become one pause, which needs a checkpointer. Path rules do not cover the shell, your own tools, or MCP tools.

Sources: human-in-the-loop doc; permissions doc.

Built in

Risky shell commands go to a second model (the default) or to a person. Some floors apply even when approvals are off.

How it works

110 patterns flag commands. A prompt waits 300 seconds and then denies. Writes to instruction files such as AGENTS.md always ask a person.

Source: security doc.

Best mental model

A tiny agent core (one loop, four tools, a tree-shaped log) with a plugin system. Plan mode, subagents, and approval gates are extensions, often written by Pi itself.

Why

See the Pi profile.

An ordinary tool loop wrapped in ordered middleware, with a virtual file system as working memory and subagents as throwaway context windows.

Why

See the Deep Agents profile.

An assistant that lives on a server: one cache-friendly tool loop, many chat apps, and a notebook of memory, skills, and transcripts it rewrites between conversations.

Why

See the Hermes profile.

Patterns across the systems

Suppose you move Patch from Deep Agents to Pi. Its skill folders and its AGENTS.md file still load, because all three systems read the Agent Skills format and AGENTS.md. Its approval rules do not carry over: on Deep Agents you listed tools in interrupt_on, and on Pi you would write an extension.

What carries over

What changes your design