Pi Architecture:拆解 Coding Agent 的内部架构

这个视频比上一条“Pi 是什么”的视频更深入,重点不是教你怎么用 Pi,而是直接拆 Pi 的内部架构。Alejandro AO 本人还有一篇与视频对应的文章,可以较完整地还原视频结构。

这期到底在讲什么?

整期可以压缩成一句话:

一个 Coding Agent 本质上并没有那么神秘:LLM + Agent Loop + Context + Tools + Session,再在外面套一层 TUI 和 Skills/Extensions,就已经构成 Pi。

视频最重要的价值,是把“Coding Agent”从一个黑盒拆开。

你可以先记住这张结构:

                 Pi
│
┌────────────┴────────────┐
│ │
Agent Core Pi Interactive
│ │
Agent Loop TUI
Context Session 管理
LLM Commands
Tools Skills
Events Compaction
│ │
└────────────┬────────────┘
│
User

Alejandro 把 Pi 理解为两个主要层次:底层负责真正 Agent 执行循环的 Core,上层是用户实际使用的 Interactive/TUI。更重要的是,Core 并不依赖 TUI,因此同一套 Agent 能通过 CLI、RPC 或 SDK 等不同入口使用。


1. 最核心的东西:Agent Loop

这是整期最值得理解的部分。

很多人第一次接触 Agent Framework,会觉得里面一定有什么非常复杂的算法。

实际上最核心的循环就是:

User
│
▼
构造 Context
│
▼
LLM
│
▼
有没有 Tool Call?
│
├──── No ────→ 返回结果
│
Yes
│
▼
执行 Tool
│
▼
Tool Result
│
▼
加入 Context
│
└────────────→ 再调用 LLM

也就是:

while True:

response = llm(context)

if response.has_tool_calls:
results = execute_tools(response.tool_calls)
context += results
else:
return response

当然真实 Pi 实现比这复杂,但Agent 最本质的东西就是这个循环。Alejandro 特别强调 Pi 的核心 Agent Loop 是自己实现的,而不是依赖 OpenAI Agents SDK、Vercel AI SDK 一类框架。


2. 一次 Pi 请求到底发生什么?

例如你输入:

帮我看看这个项目为什么启动失败。

第一步,Pi 不会只把这句话发给模型。

它会构造 Context,大致包含:

System Prompt
+
AGENTS.md / 项目指令
+
Skill descriptions
+
Tool definitions
+
之前的 Session Messages
+
当前 User Message

变成:

┌─────────────────────────┐
│ System Prompt │
├─────────────────────────┤
│ AGENTS.md │
├─────────────────────────┤
│ Skills │
├─────────────────────────┤
│ Tool Definitions │
├─────────────────────────┤
│ Conversation History │
├─────────────────────────┤
│ User Message │
└─────────────────────────┘
│
▼
LLM

所以这里有个非常重要的 Agent 概念:

Agent 的能力不只是由 Model 决定,还高度取决于每次 LLM Call 之前,你到底组装了什么 Context。

Alejandro 把它总结成一种 layered prompt:基础行为、用户/环境指令、项目指令、Skill/工作流指令,再到当前请求。


3. Pi 的 System Prompt 为什么值得研究?

这和你上一个视频正好连起来。

Pi 的基础 System Prompt 非常短,视频资料将其描述为大约 20 行左右。

也就是说 Pi 不想:

System Prompt

你是 coding agent...
你应该...
如果发生 A...
如果发生 B...
搜索的时候...
修改代码的时候...
Git 的时候...
测试的时候...
Planning 的时候...
...
几千行

而是:

Minimal System Prompt
+
AGENTS.md
+
Skills
+
Extensions
+
Current Context

核心原则仍然是:

Core 尽可能小,具体能力按需组合。

所以你上一期看到“Pi 极简”只是结果,这一期是在解释这个极简到底在代码架构上怎么实现。


4. Tool Call 实际怎么进入 Agent Loop?

假设模型收到 Context 后返回:

我应该先看看 package.json。

同时生成:

tool_call:
read("package.json")

Pi 执行:

read
↓
package.json 内容

然后并不是直接返回给用户。

而是:

LLM response
+
Tool Call
+
Tool Result

加入消息历史:

User
↓
Assistant
↓
Tool Call
↓
Tool Result
↓
Assistant

然后:

重新调用 LLM

模型可能接着说:

看起来是依赖问题,我运行 npm install 看一下。

于是:

bash("npm install")

结果回来:

Tool Result

再进入 Context。

于是形成:

LLM
↓
Tool
↓
LLM
↓
Tool
↓
LLM
↓
Tool
↓
...
↓
Final Answer

这就是 Agent Loop。


5. 所以 Agent 和普通 Chatbot 的关键区别是什么?

普通 Chat:

User
↓
LLM
↓
Answer

Agent:

User
↓
LLM
↓
Action
↓
Environment
↓
Observation
↓
LLM
↓
Action
↓
Environment
↓
Observation
↓
...
↓
Answer

换句话说:

Chatbot = 推理

Agent = 推理 + 行动 + 观察 + 再推理

Tools 就是模型与现实环境之间的桥梁。

Pi 默认的 read/write/edit/bash,就是让模型拥有:

LLM
│
├── 看文件
├── 创建文件
├── 修改文件
└── 操作 Shell

的能力。Alejandro 的文章也把 Tool 描述为模型与环境之间的 bridge。


6. 但是 Agent Loop 自己其实不应该知道太多

这是 Pi 架构里一个特别漂亮的地方。

很多人自己写 Agent 会这样:

agent_loop():

管 Session

管 Context

管 Compaction

管 Tool

管 UI

管 Retry

管 Storage

管 Permissions

管 Everything

最后得到一个巨大的:

God Class / God Function

Pi 的思路恰恰相反:

Loop 就负责 Loop。

源码分析对它的总结很准确:Loop 主要负责把消息送进模型、获取响应、执行 Tool,然后决定是否继续;至于消息从哪来、保存在哪里、UI 怎么显示、哪些 Tool 应该开放等,尽可能交给其他层。

所以:

Agent Loop
│
├── Call LLM
├── Handle response
├── Execute tools
├── Add results
└── Continue / Stop

而不是:

Agent Loop
├── UI
├── DB
├── Session persistence
├── Project config
├── Slash commands
├── ...

这叫关注点分离。


7. Event-Driven 是这里非常重要的设计

那问题来了。

如果 Agent Loop 不负责 UI:

TUI 怎么知道 Agent 正在输出什么?

答案是:

Events

Agent Loop 不需要知道谁在监听。

它只需要不断发:

agent_start

turn_start

message_start

message_update

message_update

message_end

tool_execution_start

tool_execution_update

tool_execution_end

turn_end

agent_end

Pi 的设计资料中记录了一套细粒度的 AgentEvent 生命周期。

于是:

             Agent Loop
│
│ events
▼
┌──────────────────┐
│ │
TUI RPC Client
│ │
显示 Streaming 发给远程程序

Agent Loop 根本不在乎:

谁在消费 Events

这就是为什么同一个 Core 可以被:

Terminal
Web UI
RPC
SDK
Tests

重复使用。


8. TUI 其实只是 Agent 外面的一层“壳”

这也是这期视频标题为什么专门提到 TUI。

很多人会把:

Pi terminal interface

误认为:

Pi Agent

实际上不是。

结构更像:

┌────────────────────────────┐
│ TUI │
│ │
│ 输入框 │
│ Streaming │
│ Tool 展示 │
│ Session Selector │
│ Commands │
│ 状态 │
└─────────────┬──────────────┘
│
│ Events / API
▼
┌────────────────────────────┐
│ Agent Core │
│ │
│ Agent Loop │
│ LLM │
│ Tools │
│ Messages │
└────────────────────────────┘

因此完全可以:

把 TUI 拿掉

Agent 仍然工作。

这就是好的架构分层。


9. Session 的设计也非常有意思

Coding Agent 不可能每条消息都:

从零开始

比如:

User:
修这个 bug

Agent:
读取 10 个文件
修改 3 个文件
运行测试

User:
刚才那个地方再改一下

第二句话必须知道第一轮发生了什么。

所以需要:

Session

Pi 会持久化:

Messages
Tool calls
Tool results
Conversation state

之后恢复 Session 时:

load session
↓
rebuild context
↓
继续 Agent Loop

Alejandro 的讲解特别强调,Session 是 Pi 能持续完成多步骤 coding task 的关键组成部分。


10. 更特别的是:Pi 的 Session 是树,而不仅仅是一条线

这一点上一期的视频没有讲得这么深入。

一般聊天:

A → B → C → D → E

Pi 使用 JSONL 持久化,并支持树状会话结构。

概念上:

  A
│
B
│
C
/ \
D D2
│ │
E E2

也就是说历史不一定只是:

append append append

而可以形成分支。

这对 Coding Agent 特别有价值。

例如:

尝试方案 A
↓
发现不行

回到之前节点
↓
尝试方案 B

不用彻底丢掉历史。


11. Context 太长怎么办?—— Compaction

这是这期非常重要的一块。

Coding Agent 很容易产生大量 Context:

User messages
+
Assistant reasoning/output
+
读取文件
+
bash output
+
error logs
+
test results
+
tool calls

跑几十轮以后:

Context
████████████████████████████████

最终超过:

Context Window

Pi 因此需要:

Compaction

大概是:

完整历史

A
B
C
D
E
F
G
H
I
J
↓
Summary
↓

“目标:
修复 xxx

已完成:
- 找到问题
- 修改 A
- 修改 B

当前状态:
测试还有一个失败

关键决定:
使用 xxx 方案

下一步:
修复 test_xxx”

然后继续:

Summary
+
Recent Messages
+
New User Message

而不是永远带着全部原始历史。


12. Pi 怎么判断什么时候 Compact?

这个细节挺有意思。

视频资料特别提到:

Pi 不只是简单粗暴地:

characters / 4

估算 Token。

它会利用模型 API 返回的 usage 数据,例如:

input
output
cache read
cache write

去判断 Context 使用情况,并在适当节点检查是否需要 Compaction。

因此整个过程是:

Agent Loop
│
▼
LLM usage
│
▼
Context 是否接近限制?
│
┌───┴────┐
No Yes
│ │
继续 Compact
│
▼
Summary
│
▼
继续 Loop

这跟你前几天问我的 cache hit / cached token 其实也直接相关:现代 Agent 的 Context 管理不能只盯着“消息字数”,provider 返回的 token usage、cache read/write 等指标也会参与实际成本与上下文管理。


13. Skills 和 Tools 完全不是一个东西

这个视频另一个很值得搞清楚的点:

Tool ≠ Skill

Tool 是:

Agent 能做什么。

比如:

read
write
edit
bash

Skill 是:

Agent 应该怎么完成某类任务。

例如:

Tool:
bash

Skill:
“如何发布一个 npm package”

1. 检查 git status
2. 运行测试
3. 更新 version
4. 生成 changelog
5. npm publish
6. 创建 tag

因此:

Tools
=
Capabilities

Skills
=
Procedures / Knowledge / Workflows

这一区分非常重要。


14. Skills 为什么不能全部塞 Context?

假设你安装:

100 Skills

每个 Skill:

2000 tokens

如果全部放进去:

200,000 tokens

Agent 还没干活,Context 就快没了。

所以 Pi 使用一种类似 Progressive Disclosure(渐进式披露) 的思想。相关视频资料也把 Skills 的 progressive disclosure 列为 Pi 架构的重要机制。

概念上:

System Prompt
+
Skill 目录/描述

先告诉模型:

你拥有这些 Skill:

deployment
testing
release
video-editing
...

真正需要某个 Skill:

release

再加载:

release 的完整 instructions

所以:

所有 Skill
│
▼
只暴露 Metadata
│
▼
LLM 判断需要哪个
│
▼
按需加载完整内容

这又回到了 Pi 一直强调的:

Context Engineering


15. Extensions 和 Skills 也不是一回事

可以这么区分:

Tool Skill Extension
是什么 能力 工作流程/知识 改造 Agent
例子 read() release workflow 新增 hook/tool/UI
是否执行代码 是 通常主要是 instructions 是
主要目的 Action Procedure Customization

所以:

Tool
→ 给 Agent 手

Skill
→ 教 Agent 怎么做

Extension
→ 改造 Agent 本身

这三个概念分开以后,整个 Pi 架构一下就清楚很多。


16. 把整个视频画成完整架构

这应该是你看完这期最值得记住的一张图:

                       USER
│
▼
┌────────────────────────────────────────┐
│ Pi Interactive │
│ │
│ TUI │
│ Commands │
│ Session Management │
│ Skills │
│ Compaction │
│ Extensions │
└──────────────────┬─────────────────────┘
│
▼
┌────────────────────────────────────────┐
│ Agent Core │
│ │
│ Agent Loop │
│ │ │
│ ┌────────▼────────┐ │
│ │ Build Context │ │
│ └────────┬────────┘ │
│ ▼ │
│ LLM │
│ │ │
│ Tool Call? │
│ / \ │
│ YES NO │
│ │ │ │
│ ▼ └────→ Finish │
│ Tools │
│ │ │
│ Tool Result │
│ │ │
│ └──────────→ LLM │
│ │
│ ↓ Events ↓ │
└────────────────────────────────────────┘
│
┌────────┼─────────┐
▼ ▼ ▼
TUI RPC SDK

17. 把你最近看的三个视频串起来,就更有意思了

你前面连续看了三个:

① Deep Agents PTC

解决:

LLM 不应该机械地
一次 → Tool
一次 → Tool
一次 → Tool

复杂工具编排
↓
交给 Program

② 技术爬爬虾 Pi

解决:

Agent 不应该默认
塞几十个 Tools

↓
Minimal Core
+
Extensions

③ Alejandro 这期 Pi Architecture

进一步告诉你:

那这个 Minimal Agent
内部到底怎么实现?

答案就是:

             Coding Agent
│
┌───────────────┼───────────────┐
│ │ │
Brain Actions State
│ │ │
LLM Tools Session
│ │ │
└────────── Agent Loop ─────────┘
│
Events
│
▼
TUI

+ Skills
+ Extensions
+ Compaction

这三个视频合起来,其实已经开始从“会用 Agent”进入“理解 Agent Harness 怎么设计”了。

其中 Alejandro 这期最值得你真正吃透的,不是 Pi 的某个 API,而是这四个架构原则:

Agent Loop 要小;Core 和 UI 要解耦;所有东西通过 Events 连接;Context、Session、Skills、Compaction 应该由独立层负责。

一旦这四点理解了,再去看 Claude Code、Codex、OpenCode、Deep Agents,很多以前看起来很神秘的东西,其实都是在这个基础 Agent Loop 外面增加不同的 Harness 能力。

Alejandro AO 对应的 Pi Architecture 原文