最终项目是一个简化版 Pi Agent,技术栈是 React + Node.js + TypeScript。
它不是 Pi 的复制品,而是一个适合学习的缩小模型。你可以把它看作“Pi 核心思想的教学沙盘”。
| 功能 | 是否实现 | 说明 |
|---|---|---|
| 聊天输入 | 是 | React 页面输入用户目标 |
| Agent Loop | 是 | 后端循环处理模型输出和工具调用 |
| 工具注册 | 是 | list_files、read_file、write_note |
| 工具结果回写 | 是 | 生成 toolResult 消息再进入下一轮 |
| 事件时间线 | 是 | 前端展示 message/tool/turn 事件 |
| JSONL 会话 | 是 | 后端追加写 .teaching-agent/session.jsonl |
| 会话树 | 最小实现 | 保存 id / parentId / leafId |
| 上下文压缩 | 简化实现 | 超过阈值时插入 summary message |
| 真实模型 API | 可选 Demo | 默认用 MockModel,npm run demo:05 展示 OpenAI-compatible 接入 |
flowchart TB
subgraph Browser["React 前端"]
Chat["ChatView"]
Timeline["EventTimeline"]
Inspector["MessageInspector"]
end
subgraph Server["Node 后端"]
API["Express API"]
Loop["runAgentLoop"]
Model["MockModel"]
Tools["ToolRegistry"]
Store["JsonlSessionStore"]
Events["AgentEvent[]"]
end
subgraph Workspace["教学工作区"]
Files["sample files"]
Notes["notes"]
end
Chat --> API
API --> Store
API --> Loop
Loop --> Model
Loop --> Tools
Tools --> Workspace
Loop --> Events
Events --> API
API --> Timeline
API --> InspectorsequenceDiagram participant UI as React participant API as Express participant Store as JsonlSessionStore participant AgentLoop as Agent Loop participant Model as MockModel participant Tool as ToolRegistry UI->>API: POST /api/runs API-->>UI: runId UI->>API: GET /api/runs/:runId/events API->>Store: append user message API->>Store: buildContext() API->>AgentLoop: runAgentLoop(context) AgentLoop->>Model: complete(messages, tools) Model-->>AgentLoop: toolCall read_file AgentLoop->>Tool: execute read_file Tool-->>AgentLoop: tool result AgentLoop->>Model: complete(messages, tools) Model-->>AgentLoop: final answer AgentLoop-->>API: newMessages + events API->>Store: append newMessages API-->>UI: SSE AgentEvent API-->>UI: run_done + full session
POST /api/prompt 仍然保留,方便 curl 调试;浏览器默认使用 /api/runs + SSE,这样读者能看到消息和工具事件逐步进入 UI。
教学项目不直接接真实模型,是为了让每个读者都能在没有 API Key 的情况下跑通。
MockModel 的另一个好处是可预测:你知道它什么时候会调用工具,什么时候会停止。等你理解 Agent Loop 后,再把它替换成 OpenAI/Anthropic/Vercel AI SDK 都不难。
如果你已经有 OpenAI-compatible 测试接口,可以先看 可选:接入 OpenAI-compatible 模型。这条路径不会改变默认教学项目,只用于验证真实模型如何接入同一套工具协议。
examples/teaching-agent/
├─ src/
│ ├─ client/ # React 前端
│ ├─ server/
│ │ ├─ agent/ # loop、model、tools、session store
│ │ └─ index.ts # Express API
│ └─ shared/ # 前后端共享类型
├─ workspace/ # 工具可访问的示例文件
├─ package.json
├─ tsconfig.json
└─ vite.config.ts
如果你已经跑过四个 Demo,可以把最终项目看成它们的组合版:
| 机制 | Demo | 最终项目 |
|---|---|---|
| 最小 Agent Loop | Demo 1 | src/server/agent/loop.ts |
| 工具调用 | Demo 2 | ToolRegistry + MockModel |
| 会话树 | Demo 3 | JsonlSessionStore |
| 上下文压缩 | Demo 4 | compactIfNeeded() |
更细的文件对照见 Demo 到项目的映射。