PI Agent 极简教程:OpenClaw 背后的嵌入式 Agent 引擎全解
前言
本教程面向开发者与技术爱好者,以「极简、深入、可落地」为核心原则,系统讲解 PI Agent(Pi Agent)的设计哲学、架构原理、开发方法与实战技巧。PI Agent 是 OpenClaw 智能体系统的核心运行时引擎,以极简的代码实现、完全可控的上下文、透明的调试体验与优秀的自托管兼容性,成为新一代 Coding Agent 的代表性框架。
全文约 2 万字,从入门认知到源码级原理,从环境搭建到自定义开发,从基础使用到生产级优化,覆盖 PI Agent 全生命周期的核心知识。你无需复杂的前置知识,只需具备基础的 TypeScript/JavaScript 开发能力与 LLM 应用基础概念,即可跟随教程逐步掌握 PI Agent 的完整使用与二次开发能力。
第一部分 入门认知篇:认识 PI Agent
1.1 PI Agent 是什么:定位与核心身份
PI Agent(常写作 Pi Agent)是一个极简主义的嵌入式 Agent 运行时引擎,由 Mario Zechner 主导开发,是 OpenClaw 多渠道智能体平台的核心推理与执行引擎。
它并非 OpenClaw 的内置插件,而是一个独立、可复用的 Agent Harness(智能体框架),OpenClaw 通过嵌入式集成的方式,直接导入并实例化 PI Agent 的会话对象,为自身提供 AI 推理、工具调用、会话管理等核心能力。
从产品定位上看,PI Agent 是为硬核开发者打造的「可控型 Agent 框架」,它的核心目标不是做功能大而全的通用 Agent 平台,而是解决现有 Agent 框架的三大痛点:
PI Agent 以「Opinionated and Minimal(固执且极简)」为设计哲学,用最少的代码实现最核心的 Agent 能力,把上下文控制权完全交还给开发者,同时保持极高的扩展性与可调试性。
1.2 PI Agent 与 OpenClaw 的关系
要理解 PI Agent,首先需要理清它与 OpenClaw 的架构关系。OpenClaw 是一个多渠道消息网关式的 AI 助手平台,支持接入 Telegram、Discord、WhatsApp、Slack 等数十种消息渠道,提供统一的会话管理与智能体能力。
OpenClaw 的整体架构采用经典的 Hub-and-Spoke(轮毂-辐条)模式,分为三层:
Channel Adapters(渠道适配层) → Gateway(控制平面) → Agent Runtime(智能体运行时,即 PI Agent)
- Channel Adapters:负责对接不同的消息平台,将异构的消息格式标准化为统一的输入结构;
- Gateway:整个系统的中枢,负责会话路由、消息队列管理、权限控制与对外接口;
- Agent Runtime:核心的 AI 推理与工具执行层,完全由 PI Agent 提供支撑。
二者的集成方式不是子进程调用,也不是 RPC 远程调用,而是嵌入式集成:OpenClaw 直接通过 createAgentSession() 方法导入 PI Agent 的 AgentSession 类,在自身进程内实例化智能体会话。这种设计带来了四个核心优势:
简单来说:OpenClaw 是「外壳与渠道生态」,PI Agent 是「心脏与大脑」;OpenClaw 负责连接用户与世界,PI Agent 负责思考与执行。
1.3 PI Agent 的核心技术包
PI Agent 不是一个单一的包,而是由四个核心 npm 包组成的技术栈,各司其职,可按需组合使用:
| @mariozechner/pi-ai | 统一的大语言模型 API 抽象层 | 模型接入层 |
| @mariozechner/pi-agent-core | Agent 核心循环、事件系统、队列管理、状态管理 | 核心运行时 |
| @mariozechner/pi-coding-agent | 编码场景的工具集与预设配置,封装文件操作、命令执行等能力 | 编码智能体封装 |
| @mariozechner/pi-tui | 终端交互界面(Terminal UI),提供命令行下的 Agent 交互能力 | 终端交互层 |
其中 pi-agent-core 是整个体系的灵魂,全部源码仅 5 个核心文件、约 1500 行代码,却实现了完整的 Agent 运行时能力,是「极简主义」设计的集中体现。
1.4 PI Agent 的核心优势
1.4.1 完全透明的上下文控制
PI Agent 拒绝隐式 Prompt 注入,所有输入模型的内容都可以被开发者精确查看与修改。系统提示词保持极简,不堆砌大量规则来「教导」LLM 如何做 Agent,而是通过简洁的职责定义,充分发挥前沿大模型的原生能力,既节省上下文 Token,又提升了 Agent 行为的灵活性。
1.4.2 极致的可调试性
PI Agent 的每一次执行都有完整的事件流与 Transcript 记录:从用户输入、上下文组装、模型流式输出,到工具调用的入参与返回值,每一个环节都有明确的事件回调。你可以通过订阅事件实时监控执行状态,也可以通过持久化的 JSONL 会话记录完整回放任意一次执行过程,精准定位问题根源。
1.4.3 原生自托管友好
pi-ai 层对大模型提供商做了完全抽象,不绑定任何云端厂商。无论是 OpenAI、Anthropic 等商业 API,还是 Ollama、vLLM、LM Studio 等本地部署模型,都可以无缝接入,工具调用能力保持一致,解决了本地模型 Agent 化的兼容性难题。
1.4.4 轻量与高扩展性并存
核心运行时代码量极小,运行开销极低,甚至可以在树莓派等低功耗设备上稳定运行。同时它的工具系统、钩子系统、会话系统都具备完整的扩展能力,你可以从零打造专属的智能体,也可以基于编码智能体快速扩展业务场景。
第二部分 核心原理篇:深入 PI Agent 架构内核
2.1 整体运行架构
2.1.1 三层执行管道
PI Agent 的核心执行逻辑是一条清晰的七层工具管道 + 五阶段 Agent 循环。从工具调用的视角看,PI Agent 的能力栈分为四层,从底层到上层依次叠加:
每一层工具都遵循统一的注册与调用规范,上层工具可以复用下层能力,同时通过策略过滤机制,按配置文件、模型提供商、智能体角色、群组、沙箱等级别控制工具的可用范围。
2.1.2 Hub-and-Spoke 协作模式
在 OpenClaw 的整体架构中,PI Agent 作为执行端,与 Gateway 控制平面形成轮毂-辐条式协作:
- Gateway 是中心轮毂,负责接收所有渠道的用户消息,按会话进行路由,维护消息队列;
- PI Agent 是核心执行辐条,接收 Gateway 转发的任务,完成推理与工具执行,将结果返回 Gateway 分发给用户;
- 各类工具、渠道适配器也是辐条,由 Gateway 统一调度,供 PI Agent 调用。
这种架构的优势是解耦:消息接入、控制逻辑、AI 执行完全分离,各自可以独立扩展与迭代。新增一个消息渠道不需要修改 Agent 逻辑,新增 Agent 能力也不会影响消息网关的稳定性。
2.2 Agent Loop:智能体的核心循环
Agent Loop(智能体循环)是 PI Agent 的心脏,定义了智能体从接收输入到输出结果的完整生命周期。整个循环分为五个核心阶段,依次执行,形成闭环:
Intake(输入接收) → Context Assembly(上下文组装) → Model Inference(模型推理) → Tool Execution(工具执行) → Response(结果输出)
如果模型返回工具调用,则执行完工具后,会将工具结果回填到上下文中,再次进入模型推理阶段,直到模型输出最终回答,循环结束。
2.2.1 阶段一:Intake(输入接收)
输入接收阶段是循环的入口,负责处理用户的输入内容,解析输入类型,初始化会话上下文。 PI Agent 支持三种输入类型:
- chat:普通对话输入,用户的自然语言提问或指令;
- edit:编辑类输入,针对文件或代码的修改指令;
- command:系统命令输入,比如 /new 新建会话、 /clear 清空上下文等。
该阶段的核心工作是:
2.2.2 阶段二:Context Assembly(上下文组装)
上下文组装是整个循环中最关键的环节之一,直接决定了模型的输出质量与稳定性。该阶段负责构建发送给大模型的完整上下文,包括:
PI Agent 在该阶段会严格控制上下文的 Token 数量,当接近模型上下文窗口上限时,会触发自动压缩机制,这部分会在后续章节详细讲解。
2.2.3 阶段三:Model Inference(模型推理)
模型推理阶段负责调用大语言模型,基于组装好的上下文生成回复。PI Agent 原生支持流式输出(Streaming),可以逐 Token 返回模型生成的内容,提升交互体验。
该阶段的核心逻辑:
如果模型输出的是普通文本,循环会进入最终的结果输出阶段;如果模型输出了工具调用(Tool Call),则进入工具执行阶段。
2.2.4 阶段四:Tool Execution(工具执行)
工具执行阶段负责解析模型的工具调用请求,校验工具权限,执行对应的工具函数,并获取执行结果。 执行流程包括:
工具执行完成后,循环会回到「模型推理」阶段,将工具结果交给模型,让模型基于执行结果继续思考,生成下一步操作或最终回答。
2.2.5 阶段五:Response(结果输出)
当模型生成最终的自然语言回答、不再调用工具时,循环进入收尾阶段。该阶段负责:
2.3 核心组件源码级拆解
pi-agent-core 是 PI Agent 的核心,仅 5 个文件就实现了完整的 Agent 运行时,理解这 5 个文件的功能,就掌握了 PI Agent 的内核。
2.3.1 types.ts:类型定义层
这是整个项目的基础,定义了所有核心数据结构的 TypeScript 类型,包括:
- 消息类型:用户消息、助手消息、工具消息、内容块;
- 事件类型:agent_start、turn_start、message_start、message_update、message_end、tool_execution_start、tool_execution_end、turn_end、agent_end;
- 工具类型:工具定义、工具调用、工具执行结果;
- 配置类型:Agent 配置、模型配置、会话配置;
- 状态类型:会话状态、循环状态、队列状态。
所有模块都基于这套统一的类型系统开发,保证了数据结构的一致性,这也是极简架构的基础。
2.3.2 agent-loop.ts:核心循环实现
这个文件是 Agent Loop 的具体实现,包含两个核心异步生成器函数:agent_loop() 与 agent_loop_continue()。
- agent_loop():启动一个全新的 Agent 循环,处理初始用户输入;
- agent_loop_continue():在已有会话的基础上继续循环,处理后续输入。
核心循环的伪代码逻辑如下:
async function* agentLoop(context, options) {
yield { type: 'agent_start' };
while (true) {
yield { type: 'turn_start' };
// 1. 调用模型,获取流式回复
const assistantMessage = yield* streamModelResponse(context);
yield { type: 'message_end', message: assistantMessage };
// 2. 如果没有工具调用,结束本轮
if (!assistantMessage.toolCalls?.length) {
yield { type: 'turn_end' };
break;
}
// 3. 执行所有工具调用
const toolResults = [];
for (const toolCall of assistantMessage.toolCalls) {
yield { type: 'tool_execution_start', toolCall };
const result = await executeTool(toolCall);
yield { type: 'tool_execution_end', result };
toolResults.push(result);
}
// 4. 工具结果加入上下文,进入下一轮
context.messages.push(…toolResults.map(toToolMessage));
yield { type: 'turn_end', toolResults };
// 5. 检查是否有实时干预消息
const steeringMsgs = getSteeringMessages();
if (steeringMsgs.length) {
context.messages.push(…steeringMsgs);
continue;
}
if (shouldStop()) break;
}
// 6. 检查后置任务队列
const followUpMsgs = getFollowUpMessages();
if (followUpMsgs.length) {
context.messages.push(…followUpMsgs);
yield* agentLoopContinue(context, options);
}
yield { type: 'agent_end' };
}
从这段逻辑可以看出,PI Agent 的循环分为两层:
- 内层循环(Turn Loop):处理单轮模型推理 + 工具执行,只要有工具调用就持续迭代;
- 外层循环(Agent Loop):处理完整的用户任务,直到所有工具执行完毕且无后续任务。
2.3.3 agent.ts:Agent 类封装
这个文件定义了 Agent 类,对底层的 agent-loop 进行了面向对象的封装,提供了更易用的 API,包括:
- 状态管理:维护会话的当前状态、消息列表、配置信息;
- 事件订阅:支持通过 subscribe() 方法订阅执行过程中的所有事件;
- 控制方法:prompt() 发起任务、abort() 中止执行、reset() 重置会话;
- 队列管理:维护 Steering 队列与 Follow-up 队列,支持实时干预。
Agent 类是对外暴露的核心接口,上层应用通常通过这个类来使用 Agent 能力,而不是直接调用底层的循环函数。
2.3.4 proxy.ts:流式代理层
这个文件提供了 stream_proxy() 函数,用于处理服务端推送(SSE)的流式响应。当 Agent 运行在服务端、前端通过 SSE 接收流式结果时,proxy 层负责将离散的 delta 片段拼接还原为完整的消息结构,保证前后端流式交互的一致性。
2.3.5 index.ts:入口导出层
统一导出所有核心类型与 API,是包的对外入口。
2.4 会话管理机制
2.4.1 JSONL Transcript 存储格式
PI Agent 的会话持久化采用 JSONL(JSON Lines)格式,每一行对应一条消息或事件,是一种轻量且易于解析的存储方式。 JSONL 格式的优势:
每条记录都包含完整的消息元数据:消息 ID、角色、创建时间、内容、工具调用信息等,是调试与回溯的核心依据。
2.4.2 Bootstrap 上下文注入
每个会话启动时,PI Agent 会自动注入 Bootstrap(启动引导)上下文,这部分内容是会话的基础信息,包括:
- 工作目录路径与权限范围;
- 当前可用的工具列表与使用说明;
- 环境信息(操作系统、Node.js 版本、可用命令等);
- 会话规则与行为准则。
Bootstrap 内容会在会话初始化时写入 Transcript,作为模型的基础认知,确保 Agent 了解自身的能力边界与运行环境。
2.4.3 会话分支与回溯
PI Agent 的会话天然支持分支能力,本质上是基于 JSONL 文件的复制与截断。
- 创建分支:复制当前会话的 JSONL 文件,得到一个完全相同的新会话,后续操作互不影响;
- 回溯重置:截断 JSONL 文件到指定的消息位置,丢弃之后的所有内容,会话回退到该时间点的状态。
这种设计让开发者可以轻松进行多方案对比,或者在 Agent 执行出错时回退到正确的节点重新执行。
2.5 上下文管理:压缩与溢出恢复
上下文窗口是大模型的核心资源,PI Agent 设计了完整的机制来管理上下文长度,确保在长会话中依然稳定运行。
2.5.1 Context Compaction(自动上下文压缩)
当上下文的 Token 数量达到设定的阈值(通常是模型上下文窗口的 70%-80%)时,PI Agent 会自动触发上下文压缩。 压缩的核心逻辑:
压缩过程是自动且透明的,开发者不需要手动干预,也可以通过配置调整压缩阈值与摘要策略。
2.5.2 Overflow Recovery(溢出恢复)
如果自动压缩后上下文依然超出模型窗口(比如单次工具返回结果特别长),PI Agent 会触发溢出恢复机制:
对应的核心函数是 handleOverflowOrRetry,它负责判断错误类型、执行压缩、发起重试,是 PI Agent 长会话稳定性的关键保障。
2.6 并发模型:Command Lanes 队列系统
PI Agent 的并发设计遵循一个核心原则:同一个会话的多次调用必须串行执行,不同会话之间可以并行执行。为了实现这一点,PI Agent 设计了 Command Lanes(命令通道)队列系统。
2.6.1 核心原理
每个会话对应一个唯一的 Lane(通道),每个 Lane 内部维护一个任务队列,任务按先进先出的顺序串行执行。当向同一个会话发起多个请求时,请求会依次进入队列排队,前一个任务执行完成后才会执行下一个。
不同的会话对应不同的 Lane,互相之间完全隔离,可以并行执行,充分利用系统资源。
2.6.2 会话 Lane 解析
Lane 的标识由会话 Key 经过清洗后生成,核心逻辑:
export function resolveSessionLane(key: string) {
const cleaned = key.trim().toLowerCase();
return cleaned || 'default';
}
相同的 Key 会解析到同一个 Lane,保证会话内串行;不同的 Key 分配到不同 Lane,实现并发执行。
这种设计既保证了单个会话的状态一致性(避免并行修改导致的状态冲突),又保证了多会话场景下的执行效率,是兼顾正确性与性能的优雅方案。
2.7 队列机制:Steering 与 Follow-up
PI Agent 设计了两个特殊的消息队列,解决「Agent 执行过程中用户干预」的问题,分别是 Steering 队列与 Follow-up 队列。
2.7.1 Steering 队列:实时干预
Steering(转向)队列用于处理用户的实时干预指令。当 Agent 正在执行任务时,用户如果输入新的指令(比如「等一下,先看一下这个文件」),这条消息会进入 Steering 队列。
执行时机:当前工具执行完成、进入下一轮模型推理之前,Steering 队列中的消息会被注入到上下文中,模型会优先处理用户的新指令,调整执行方向。
简单来说:Steering 是「我现在就要说,你马上处理」。
2.7.2 Follow-up 队列:后置任务
Follow-up(跟进)队列用于处理用户的后置任务指令。当 Agent 正在执行任务时,用户如果输入补充指令(比如「做完之后提交一个 Git commit」),这条消息会进入 Follow-up 队列。
执行时机:当前整个 Agent 循环执行完毕、即将结束之前,系统会检查 Follow-up 队列,如果有未处理的消息,就将其加入上下文,重新启动 Agent 循环处理这些任务,全部处理完成后才真正结束。
简单来说:Follow-up 是「你先忙完手里的,再处理这个」。
两个队列各司其职,既保证了用户可以随时与 Agent 交互,又不会打乱当前的执行流程,交互体验非常流畅。
第三部分 环境搭建与快速上手
3.1 环境准备
3.1.1 系统与软件要求
PI Agent 基于 Node.js 开发,运行环境要求如下:
- Node.js 版本:22.x 及以上,推荐 24.x LTS 版本;
- 包管理器:推荐 pnpm,也支持 npm、yarn、bun;
- 操作系统:Windows 10+/macOS 12+/Linux(Ubuntu 20.04+/Debian 11+),支持 ARM 架构(树莓派、Apple Silicon);
- 硬件要求:最低 2GB 内存,推荐 4GB 以上;如果运行本地大模型,需根据模型要求提升配置。
3.1.2 Node.js 环境安装
Windows/macOS 用户:推荐使用 nvm(Node Version Manager)管理 Node.js 版本,安装命令:
# macOS/Linux
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash
# 安装 Node.js 24
nvm install 24
nvm use 24
node –version # 验证版本,应输出 v24.x.x
Windows 用户:可以使用 nvm-windows,从官网下载安装包安装,之后执行相同的版本安装命令。
3.1.3 树莓派环境特殊配置
在树莓派等低功耗 ARM 设备上运行时,需要额外配置交换分区,避免内存不足:
# 创建 2GB 交换分区
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 开机自动挂载
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# 降低交换优先级,提升性能
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
同时建议使用 Raspberry Pi OS Lite 64 位版本,无桌面环境可节省大量内存资源。
3.2 OpenClaw 完整安装与初始化
对于大多数用户,通过 OpenClaw 使用 PI Agent 是最便捷的方式,内置了完整的 TUI 界面、工具生态与渠道支持。
3.2.1 安装 OpenClaw
官方提供一键安装脚本,执行以下命令即可:
curl -fsSL https://install.openclaw.ai | bash
脚本会自动下载最新版本的 OpenClaw,配置环境变量,安装完成后执行 openclaw –version 验证是否安装成功。
3.2.2 初始化配置向导
执行 openclaw init 启动初始化向导,按提示完成基础配置:
完成向导后,OpenClaw 会自动生成配置文件,存储在 ~/.openclaw/ 目录下。
3.2.3 核心配置文件说明
OpenClaw 的核心配置文件是 ~/.openclaw/openclaw.json,包含全局配置与 Agent 定义,核心字段说明:
{
"defaultAgent": "default",
"agents": [
{
"id": "default",
"name": "Default Coding Agent",
"workspace": "~/.openclaw/workspace/default",
"agentDir": "~/.openclaw/agents/default",
"model": "deepseek/deepseek-reasoner",
"identity": {
"name": "AI 编程助手",
"description": "擅长代码编写与文件操作的智能助手"
},
"tools": {
"allow": ["read", "write", "edit", "exec", "browser"],
"deny": []
},
"sandbox": {
"enabled": true,
"rootDir": "~/.openclaw/workspace/default"
}
}
]
}
- id:Agent 的唯一标识;
- workspace:Agent 的工作目录,文件操作默认限制在此目录下;
- model:使用的模型,格式为 提供商/模型名;
- tools.allow:允许使用的工具列表;
- sandbox:沙箱配置,启用后 Agent 无法访问工作目录外的文件。
3.3 创建你的第一个 Agent
我们通过创建一个「文档整理 Agent」来熟悉 Agent 的配置与使用流程。
3.3.1 步骤一:创建工作目录
# 创建工作目录
mkdir -p ~/.openclaw/workspace/doc-sorter
# 创建 Agent 配置目录
mkdir -p ~/.openclaw/agents/doc-sorter
3.3.2 步骤二:编写 Agent 配置文件
在 ~/.openclaw/agents/doc-sorter/ 下创建 agent.json:
{
"id": "doc-sorter",
"name": "文档整理助手",
"workspace": "~/.openclaw/workspace/doc-sorter",
"model": "anthropic/claude-3.5-sonnet",
"identity": {
"name": "文档整理专家",
"description": "擅长分类、总结、整理各类文档资料"
},
"tools": {
"allow": ["read", "write", "edit", "mkdir", "ls"]
},
"systemPrompt": "你是专业的文档整理助手,擅长对文档进行分类、摘要和结构化整理。请严格在工作目录内操作,不要访问外部文件。"
}
3.3.3 步骤三:注册到全局配置
编辑 ~/.openclaw/openclaw.json,在 agents 数组中添加新的 Agent:
"agents": [
// … 原有其他 Agent
{
"id": "doc-sorter",
"configPath": "~/.openclaw/agents/doc-sorter/agent.json"
}
]
3.3.4 步骤四:启动并测试
执行命令切换到该 Agent 并启动 TUI:
openclaw use doc-sorter
openclaw tui
进入 TUI 界面后,输入指令:
请在当前目录创建一个 notes 文件夹,然后创建一个 README.md 文件,写入欢迎语。
观察 Agent 的执行过程:它会先调用 mkdir 创建文件夹,再调用 write 写入文件,最后返回执行结果。你可以在工作目录中验证文件是否成功创建。
3.4 PI Agent SDK 快速入门
如果你希望在自己的项目中嵌入 PI Agent,而不是使用 OpenClaw,可以直接使用官方 SDK。我们以 TypeScript 项目为例,演示最小化集成。
3.4.1 初始化项目与安装依赖
mkdir pi-agent-demo
cd pi-agent-demo
pnpm init -y
pnpm add @mariozechner/pi-coding-agent @mariozechner/pi-ai dotenv
pnpm add -D typescript @types/node
3.4.2 配置环境变量
创建 .env 文件,填入你的大模型 API 密钥:
ANTHROPIC_API_KEY=你的Anthropic API密钥
3.4.3 编写最小化示例代码
创建 src/index.ts:
import 'dotenv/config';
import {
AuthStorage,
createAgentSession,
ModelRegistry,
SessionManager
} from '@mariozechner/pi-coding-agent';
async function main() {
// 1. 初始化认证存储与模型注册表
const authStorage = AuthStorage.create();
const modelRegistry = ModelRegistry.create(authStorage);
// 2. 创建内存会话管理器(生产环境可使用文件持久化)
const sessionManager = SessionManager.inMemory();
// 3. 创建 Agent 会话
const { session } = await createAgentSession({
sessionManager,
authStorage,
modelRegistry,
defaultModel: 'anthropic/claude-3.5-sonnet',
workspace: './workspace'
});
// 4. 订阅事件,实时输出流式内容
session.subscribe((event) => {
if (
event.type === 'message_update' &&
event.assistantMessageEvent?.type === 'text_delta'
) {
process.stdout.write(event.assistantMessageEvent.delta);
}
if (event.type === 'tool_execution_start') {
console.log(`\\n[工具调用] ${event.toolCall.name}`);
}
});
// 5. 发起任务
console.log('=== 任务开始 ===');
await session.prompt('查看当前目录下的文件,然后创建一个 hello.txt 文件,写入 Hello Pi Agent');
console.log('\\n=== 任务结束 ===');
}
main().catch(console.error);
3.4.4 运行示例
npx tsx src/index.ts
运行后你会看到模型的流式回复,以及工具调用的日志,工作目录下会生成 hello.txt 文件。短短几十行代码,就实现了一个具备文件操作能力的智能体,这就是 PI Agent 极简设计的魅力。
3.5 TUI 界面常用操作
PI Agent 配套的 pi-tui 提供了功能丰富的终端交互界面,常用快捷键如下:
- Ctrl + N:新建会话
- Ctrl + O:打开历史会话
- Ctrl + S:保存当前会话
- Ctrl + C:中止当前执行
- Ctrl + L:清屏
- Tab:切换焦点区域
- / + 命令:执行系统命令,比如 /model 切换模型, /tools 查看可用工具
第四部分 核心功能进阶开发
4.1 自定义工具开发
工具是 Agent 能力的延伸,PI Agent 的工具系统具备完整的扩展能力,你可以轻松开发自定义工具,赋予 Agent 专属的业务能力。
4.1.1 工具定义规范
一个标准的 PI Agent 工具由三部分组成:
工具定义的 TypeScript 类型如下:
interface ToolDefinition {
name: string; // 工具名称,英文,驼峰命名
description: string; // 工具功能描述,清晰说明用途
parameters: {
type: 'object';
properties: Record<string, any>; // 参数属性
required: string[]; // 必填参数列表
};
execute: (args: any, context: ToolContext) => Promise<any>;
}
4.1.2 开发一个自定义工具
我们开发一个「天气查询工具」作为示例,让 Agent 可以查询指定城市的天气。
第一步,创建 tools/weather.ts:
import axios from 'axios';
export const weatherTool = {
name: 'queryWeather',
description: '查询指定城市的实时天气信息,支持国内主要城市',
parameters: {
type: 'object',
properties: {
city: {
type: 'string',
description: '城市名称,例如:杭州、北京、上海'
}
},
required: ['city']
},
async execute(args) {
const { city } = args;
try {
// 调用天气 API(示例使用开源接口,实际可替换为商用接口)
const response = await axios.get(
`https://api.openweathermap.org/data/2.5/weather`,
{
params: {
q: city,
appid: process.env.WEATHER_API_KEY,
lang: 'zh_cn',
units: 'metric'
}
}
);
const data = response.data;
return {
success: true,
city: data.name,
temperature: `${data.main.temp}°C`,
weather: data.weather[0].description,
humidity: `${data.main.humidity}%`,
windSpeed: `${data.wind.speed} m/s`
};
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : '查询失败'
};
}
}
};
第二步,注册工具到 Agent 会话:
import { weatherTool } from './tools/weather';
const { session } = await createAgentSession({
// … 其他配置
customTools: [weatherTool]
});
注册完成后,Agent 就可以自动识别并调用这个工具。你可以测试输入「杭州今天天气怎么样」,Agent 会自动调用天气工具并返回结果。
4.1.3 工具沙箱与权限控制
在生产环境中,工具的权限管控至关重要。PI Agent 支持从三个维度控制工具权限:
对于高危工具(如命令执行、系统操作),建议开启执行确认机制,在工具执行前向用户确认,避免误操作。
4.1.4 工具开发最佳实践
4.2 会话与记忆管理
4.2.1 持久化会话管理
默认的内存会话管理器在程序退出后数据就会丢失,生产环境建议使用文件持久化。PI Agent 提供了 FileSessionManager,将会话存储为 JSONL 文件。
使用示例:
import { FileSessionManager } from '@mariozechner/pi-coding-agent';
const sessionManager = new FileSessionManager({
storageDir: './sessions' // 会话存储目录
});
// 创建会话时指定 ID,也可以自动生成
const { session } = await createAgentSession({
sessionManager,
sessionId: 'session-001',
// … 其他配置
});
所有会话会以 .jsonl 格式保存在 ./sessions 目录下,程序重启后可以通过 sessionId 恢复历史会话。
4.2.2 记忆系统三层架构
PI Agent 的记忆系统分为三层,各司其职,共同支撑 Agent 的长期记忆能力:
工作记忆(Working Memory) 即当前会话的上下文消息,保存在内存中,是模型直接可见的内容。特点是读写速度快,但容量有限,只保留当前任务相关的信息。
情景记忆(Episode Memory) 即完整的会话历史,以 JSONL 格式持久化存储。记录了会话的所有细节,可回溯、可回放,是 Agent 的「历史档案」。
长期记忆(Long-term Memory) 从多个会话中提取的结构化知识,比如用户偏好、业务规则、常用指令等。通过向量检索的方式,在新会话启动时召回相关信息,注入到上下文中。
长期记忆需要配合向量数据库使用,PI Agent 提供了记忆钩子接口,可以接入 Chroma、Pinecone 等向量存储,实现自动记忆提取与召回。
4.2.3 上下文压缩进阶配置
上下文压缩是长会话稳定性的关键,你可以通过配置调整压缩策略,核心配置项:
const { session } = await createAgentSession({
// … 其他配置
context: {
compaction: {
enabled: true, // 启用自动压缩
thresholdRatio: 0.75, // 触发阈值,占上下文窗口的比例
summaryModel: 'anthropic/claude-3-haiku', // 用于摘要的模型
preserveRecentTurns: 5, // 保留最近的 N 轮对话不压缩
preserveSystemPrompt: true // 保留系统提示词不压缩
}
}
});
压缩策略调优建议:
- 对于编码场景,建议保留更多的最近轮次(8-10 轮),因为代码上下文关联性强,压缩后容易丢失细节;
- 对于普通对话场景,可以降低保留轮次,提升压缩比例,节省 Token;
- 摘要模型建议使用速度快、成本低的小模型,压缩任务不需要强推理能力。
4.3 并发与队列控制
4.3.1 多会话并发配置
在服务端场景,通常需要同时处理多个用户的会话,PI Agent 的 Command Lanes 机制天然支持多会话并发。你只需要为每个用户会话分配唯一的 sessionId,系统会自动为每个会话创建独立的 Lane,实现并行处理。
示例:
// 不同用户的会话,自动并行执行
const sessionA = await createAgentSession({ sessionId: 'user-123' });
const sessionB = await createAgentSession({ sessionId: 'user-456' });
// 同时发起任务,互不阻塞
Promise.all([
sessionA.prompt('任务A'),
sessionB.prompt('任务B')
]);
默认情况下,并发数没有限制,你可以根据服务器资源手动限制最大并发数,避免资源耗尽。
4.3.2 Steering 与 Follow-up 编程接口
在自定义 UI 中,你可以通过 API 主动向队列中插入消息,实现实时干预与后置任务。
// 插入实时干预消息,当前工具执行完后立即处理
session.steer('等一下,先不要修改这个文件,先看一下配置');
// 插入后置任务消息,当前任务完成后再处理
session.followUp('做完之后把修改的内容整理成一份变更报告');
这两个方法都是非阻塞的,调用后立即返回,消息会在合适的时机自动注入执行流程。
4.4 Hooks 扩展机制
Hooks(钩子)是 PI Agent 的扩展点,允许你在 Agent 执行的不同阶段注入自定义逻辑,无需修改核心代码即可扩展能力。
4.4.1 钩子类型与触发时机
| preRun | Agent 任务开始执行前 | 参数校验、限流、日志记录、内容审核 |
| preToolCall | 工具执行前 | 权限校验、参数审计、操作确认 |
| postToolCall | 工具执行后 | 结果格式化、异常上报、指标统计 |
| postRun | Agent 任务结束后 | 结果回调、记忆存储、通知推送 |
| onError | 执行出错时 | 错误告警、故障恢复、日志记录 |
4.4.2 开发一个日志钩子
我们开发一个简单的命令日志钩子,记录所有工具调用的耗时与结果。
创建 hooks/command-logger.ts:
export const commandLoggerHook = {
name: 'command-logger',
preToolCall({ toolCall, context }) {
context.startTime = Date.now();
console.log(`[工具开始] ${toolCall.name},参数:`, JSON.stringify(toolCall.arguments));
},
postToolCall({ toolCall, result, context }) {
const duration = Date.now() – context.startTime;
console.log(`[工具结束] ${toolCall.name},耗时:${duration}ms,成功:${result.success}`);
},
onError({ error, context }) {
console.error('[执行错误]', error.message);
}
};
注册钩子:
import { commandLoggerHook } from './hooks/command-logger';
const { session } = await createAgentSession({
// … 其他配置
hooks: [commandLoggerHook]
});
注册后,每次工具调用都会自动打印日志,无需修改业务代码。
4.4.3 钩子开发最佳实践
4.5 多模型与自托管模型接入
4.5.1 模型注册表配置
PI Agent 的模型注册表支持配置多个提供商与多个模型,支持灵活切换。配置文件格式如下:
{
"providers": {
"anthropic": {
"apiKey": "sk-ant-xxx",
"baseUrl": "https://api.anthropic.com",
"models": [
{
"id": "claude-3.5-sonnet",
"name": "Claude 3.5 Sonnet",
"contextWindow": 200000,
"maxOutput": 8192
}
]
},
"openai": {
"apiKey": "sk-xxx",
"models": [
{
"id": "gpt-4o",
"name": "GPT-4o",
"contextWindow": 128000
}
]
}
}
}
4.5.2 接入本地 Ollama 模型
PI Agent 完美支持本地部署的 Ollama 模型,只需添加一个自定义提供商即可:
{
"providers": {
"ollama": {
"baseUrl": "http://localhost:11434/v1",
"apiKey": "ollama",
"apiType": "openai-compatible",
"models": [
{
"id": "qwen2.5-coder:7b",
"name": "Qwen2.5 Coder 7B",
"contextWindow": 128000
}
]
}
}
}
配置完成后,就可以像使用商业 API 一样使用本地模型,工具调用能力完全兼容。这对于数据敏感、不能上云的场景非常实用。
4.5.3 多账户轮换与故障转移
对于高可用场景,PI Agent 支持配置多个 API 密钥账户,自动轮换与故障转移:
{
"providers": {
"anthropic": {
"profiles": [
{ "apiKey": "sk-ant-xxx1", "name": "account-1" },
{ "apiKey": "sk-ant-xxx2", "name": "account-2" }
],
"rotation": "round-robin", // 轮询模式
"failover": true // 启用故障转移
}
}
}
启用故障转移后,如果当前账户调用失败,会自动切换到下一个账户重试,提升服务可用性。
第五部分 实战项目篇
5.1 实战一:代码审查 Agent
我们开发一个具备代码审查能力的 Agent,能够自动扫描项目代码,发现潜在问题并给出优化建议。
5.1.1 需求分析
核心能力:
5.1.2 自定义工具开发
开发一个代码文件遍历工具:
import * as fs from 'fs/promises';
import * as path from 'path';
export const scanFilesTool = {
name: 'scanCodeFiles',
description: '遍历指定目录下的代码文件,返回文件路径列表,支持指定文件后缀过滤',
parameters: {
type: 'object',
properties: {
dir: {
type: 'string',
description: '要遍历的目录路径,相对工作目录'
},
extensions: {
type: 'array',
items: { type: 'string' },
description: '文件后缀列表,例如 [".ts", ".js"],不填则遍历所有文件'
},
exclude: {
type: 'array',
items: { type: 'string' },
description: '排除的目录名,默认排除 node_modules、.git'
}
},
required: ['dir']
},
async execute(args, context) {
const { dir, extensions = [], exclude = ['node_modules', '.git', 'dist'] } = args;
const baseDir = path.join(context.workspace, dir);
async function walk(currentDir) {
const files = [];
const entries = await fs.readdir(currentDir, { withFileTypes: true });
for (const entry of entries) {
if (exclude.includes(entry.name)) continue;
const fullPath = path.join(currentDir, entry.name);
const relPath = path.relative(context.workspace, fullPath);
if (entry.isDirectory()) {
files.push(…await walk(fullPath));
} else {
if (extensions.length === 0 || extensions.includes(path.extname(entry.name))) {
files.push(relPath);
}
}
}
return files;
}
try {
const files = await walk(baseDir);
return { success: true, files, count: files.length };
} catch (error) {
return { success: false, error: error.message };
}
}
};
5.1.3 Agent 配置
{
"id": "code-reviewer",
"name": "代码审查助手",
"model": "deepseek/deepseek-reasoner",
"workspace": "./projects",
"tools": {
"allow": ["scanCodeFiles", "read", "write"]
},
"systemPrompt": "你是资深代码审查专家,擅长发现代码中的 Bug、性能问题与规范问题。审查时请按以下格式输出:\\n1. 问题概述\\n2. 问题位置(文件+行号)\\n3. 问题详情\\n4. 修改建议\\n\\n请重点关注:空指针风险、边界条件处理、性能优化点、代码规范问题。"
}
5.1.4 运行测试
将一个前端项目放入工作目录,向 Agent 发送指令:
请审查 src 目录下所有 .ts 文件,生成一份代码审查报告,保存为 review-report.md。
Agent 会自动遍历文件、逐个读取审查、汇总生成报告。整个过程完全自动化,无需人工干预。
5.2 实战二:知识库问答 Agent
开发一个基于本地文档的知识库问答 Agent,能够读取本地 Markdown 文档,基于文档内容回答用户问题。
5.2.1 核心思路
5.2.2 向量检索工具开发
使用 Chroma 作为向量数据库,开发检索工具:
import { ChromaClient } from 'chromadb';
const client = new ChromaClient();
const collection = await client.getOrCreateCollection({ name: 'knowledge-base' });
export const searchDocTool = {
name: 'searchKnowledgeBase',
description: '从本地知识库中检索与问题相关的文档片段',
parameters: {
type: 'object',
properties: {
query: {
type: 'string',
description: '检索查询词'
},
topK: {
type: 'number',
description: '返回最相关的片段数量,默认 3',
default: 3
}
},
required: ['query']
},
async execute(args) {
const { query, topK = 3 } = args;
try {
const results = await collection.query({
queryTexts: [query],
nResults: topK
});
const documents = results.documents[0] || [];
const sources = results.metadatas[0]?.map(m => m.source) || [];
return {
success: true,
results: documents.map((content, i) => ({
content,
source: sources[i]
}))
};
} catch (error) {
return { success: false, error: error.message };
}
}
};
5.2.3 Agent 系统提示词设计
你是专业的知识库问答助手,请严格基于检索到的文档内容回答用户问题。
回答规则:
1. 如果检索结果中没有相关信息,请明确说明"知识库中暂无相关内容",不要编造答案;
2. 回答要准确、简洁,引用原文内容时标注来源文档;
3. 优先使用文档中的原文表述,避免过度发挥。
5.2.4 使用流程
5.3 实战三:自动化运维 Agent
开发一个服务器运维 Agent,能够执行常用的运维命令,监控服务器状态,处理简单故障。
5.3.1 安全设计
运维场景涉及服务器操作,安全是第一位的,必须做好权限管控:
5.3.2 命令白名单工具
import { exec } from 'child_process';
import { promisify } from 'util';
const execAsync = promisify(exec);
// 允许执行的命令白名单
const ALLOWED_COMMANDS = [
'df -h', 'free -h', 'uptime', 'top -bn1',
'systemctl status', 'journalctl -n 50',
'ls', 'ps aux'
];
function isCommandAllowed(cmd: string): boolean {
return ALLOWED_COMMANDS.some(allowed =>
cmd.trim().startsWith(allowed)
);
}
export const safeExecTool = {
name: 'safeExec',
description: '安全执行服务器运维命令,仅支持白名单内的命令',
parameters: {
type: 'object',
properties: {
command: {
type: 'string',
description: '要执行的运维命令'
}
},
required: ['command']
},
async execute(args) {
const { command } = args;
if (!isCommandAllowed(command)) {
return {
success: false,
error: '命令不在白名单中,禁止执行'
};
}
try {
const { stdout, stderr } = await execAsync(command, { timeout: 10000 });
return {
success: true,
stdout: stdout.trim(),
stderr: stderr.trim()
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
};
5.3.3 应用场景
- 日常巡检:让 Agent 定时执行检查命令,生成巡检报告;
- 故障排查:服务器异常时,让 Agent 查看日志、检查服务状态,定位问题原因;
- 资源监控:监控 CPU、内存、磁盘使用率,超过阈值自动告警。
第六部分 性能优化与故障排查
6.1 性能优化指南
6.1.1 上下文性能优化
上下文是影响 Agent 速度与成本的核心因素,优化方向:
6.1.2 工具执行优化
6.1.3 并发性能调优
6.2 常见问题与故障排查
6.2.1 上下文溢出错误
现象:执行时报错 context_length_exceeded,任务中断。 排查步骤:
- 启用自动压缩并调低阈值;
- 对返回内容大的工具做结果截断或分页;
- 定期清理会话历史,或手动触发压缩;
- 更换更大上下文窗口的模型。
6.2.2 工具调用失败
现象:模型生成了工具调用,但执行失败,或者模型反复调用错误的工具。 排查步骤:
- 优化工具描述与参数说明,增加使用示例;
- 对于复杂参数,在 description 中给出格式示例;
- 开启参数校验,错误时返回明确的错误信息,引导模型修正;
- 更换推理能力更强的模型。
6.2.3 模型调用无响应
现象:发起任务后长时间没有输出,模型调用超时。 排查步骤:
- 配置超时时间与重试机制;
- 启用多账户故障转移;
- 检查网络代理配置;
- 精简上下文,降低生成长度。
6.2.4 会话数据丢失
现象:重启程序后历史会话消失。 排查步骤:
- 使用 FileSessionManager 持久化存储;
- 定期备份会话文件;
- 开启会话自动保存。
6.3 调试技巧
6.3.1 事件流调试
通过订阅所有事件,可以完整观察 Agent 的执行流程,定位问题节点:
session.subscribe((event) => {
console.log(`[事件] ${event.type}`, event);
});
推荐在开发环境开启全事件日志,生产环境只记录错误与关键事件。
6.3.2 Transcript 回放
会话的 JSONL 文件是最好的调试资料,你可以使用回放功能,用历史会话重新执行一遍,复现问题:
// 从 JSONL 文件加载会话,重新执行最后一条消息
const session = await sessionManager.loadSession('session-001');
await session.retryLastTurn();
配合单步调试,可以精准定位是哪一步出了问题。
6.3.3 沙箱调试模式
开启沙箱调试模式后,所有工具调用只会打印日志,不会真正执行,适合测试 Agent 的规划逻辑是否正确,避免产生实际副作用:
const { session } = await createAgentSession({
sandbox: {
enabled: true,
dryRun: true // 试运行模式,不真正执行
}
});
结语
PI Agent 以极简的设计哲学,为开发者提供了一个完全可控、高度透明、易于扩展的 Agent 运行时引擎。它不追求功能的大而全,而是把核心能力做到极致,把控制权完全交还给开发者。
从 OpenClaw 的嵌入式集成,到自定义项目的 SDK 接入;从简单的文件操作,到复杂的业务系统集成;从本地个人使用,到生产级服务部署,PI Agent 都能优雅地胜任。
掌握本教程的内容后,你已经具备了从零到一使用与定制 PI Agent 的完整能力。接下来可以结合自己的业务场景,探索更多 Agent 的可能性,打造专属的智能体应用。
技术在不断迭代,PI Agent 也在持续进化,但「极简、可控、透明」的核心设计理念不会改变。这正是它能够成为 OpenClaw 核心引擎的根本原因,也是下一代 Agent 框架的发展方向。
PI Agent 核心 API 完整速查表 + 生产级部署配置模板
以下内容承接前文教程,前者覆盖 8 大模块 40+ 核心 API,可作为开发过程中的快速查阅手册;后者提供开箱即用的生产级配置模板,覆盖容器化部署、安全沙箱、高可用、监控告警等全链路生产能力。
第一部分:PI Agent 核心 API 完整速查表
一、核心入口 API
@mariozechner/pi-coding-agent 封装的最高频入口,用于创建智能体会话实例。
| createAgentSession() | sessionManager、authStorage、modelRegistry、defaultModel、workspace、customTools、hooks、systemPrompt | Promise<{ session: AgentSession }> | 创建一个全新的 Agent 会话实例,是所有业务集成的统一入口 | const { session } = await createAgentSession({ defaultModel: 'anthropic/claude-3.5-sonnet', workspace: './workspace' }) |
| Agent 构造函数 | config: AgentConfig | Agent 实例 | 核心运行时的底层类,面向对象封装 Agent 循环,适合深度定制场景 | const agent = new Agent({ model: modelInstance, tools: toolList }) |
二、会话实例控制 API
AgentSession 实例上的核心方法,用于驱动任务、控制执行、干预流程。
| session.prompt(content) | content: string 用户输入内容 | Promise<void> | 发起一次用户任务,启动 Agent 循环,执行过程通过事件流推送结果 | await session.prompt('读取当前目录所有文件') |
| session.abort() | 无 | void | 立即中止当前正在执行的 Agent 循环与模型调用,中断后会话状态保留 | session.abort() |
| session.reset() | 无 | void | 重置会话,清空所有历史消息与状态,保留配置与工具 | session.reset() |
| session.retryLastTurn() | 无 | Promise<void> | 重新执行上一轮对话,常用于调试与错误重试 | await session.retryLastTurn() |
| session.steer(content) | content: string 干预指令 | void | 向 Steering 队列插入实时干预消息,当前工具执行完后立即生效 | session.steer('先不要修改,先确认方案') |
| session.followUp(content) | content: string 后置指令 | void | 向 Follow-up 队列插入后置任务,当前完整循环结束后自动执行 | session.followUp('做完后生成变更报告') |
| session.getState() | 无 | SessionState | 获取当前会话的完整状态快照,包含消息列表、配置、执行状态 | const state = session.getState() |
三、事件订阅与事件类型
通过事件流获取执行全链路数据,是流式交互、日志记录、状态同步的核心方式。
订阅 API
| session.subscribe(callback) | callback: (event: AgentEvent) => void | () => void 取消订阅函数 | 订阅会话的所有执行事件,返回取消订阅的方法 |
全量事件类型清单
| agent_start | Agent 循环开始执行时 | sessionId、timestamp |
| turn_start | 每一轮模型推理开始前 | turnIndex、messageCount |
| message_start | 模型开始生成回复时 | messageId、role |
| message_update | 模型流式输出 Token 时 | delta、text、assistantMessageEvent |
| message_end | 模型单条回复生成完成时 | message 完整消息对象 |
| tool_execution_start | 工具开始执行前 | toolCall 工具调用对象 |
| tool_execution_end | 工具执行完成后 | result 工具执行结果 |
| turn_end | 单轮推理+工具执行结束后 | turnIndex、toolResults |
| compaction_start | 上下文压缩开始前 | tokenCount、threshold |
| compaction_end | 上下文压缩完成后 | beforeTokens、afterTokens |
| agent_end | 完整 Agent 循环结束时 | totalTurns、totalTokens |
| agent_error | 执行过程发生错误时 | error 错误对象 |
典型流式输出示例
session.subscribe(event => {
if (event.type === 'message_update' && event.assistantMessageEvent?.type === 'text_delta') {
process.stdout.write(event.assistantMessageEvent.delta);
}
});
四、工具系统 API
工具定义标准结构
interface ToolDefinition {
name: string; // 工具唯一名称,驼峰命名
description: string; // 功能描述,直接影响模型调用准确率
parameters: JSONSchema; // 参数 JSON Schema 定义
execute: (args: any, context: ToolContext) => Promise<any>; // 执行函数
}
工具上下文 ToolContext
工具执行时注入的上下文对象,用于权限校验与环境获取:
| workspace | string | 当前会话的工作目录绝对路径 |
| sessionId | string | 当前会话 ID |
| userId | string | 当前用户 ID(可选) |
| permissions | string[] | 当前会话的权限标签列表 |
| sandbox | SandboxConfig | 沙箱配置 |
内置核心工具清单
| read | 读取指定文件内容 | path: string |
| write | 写入内容到文件,覆盖原有内容 | path: string, content: string |
| edit | 替换文件中的指定文本片段 | path: string, oldStr: string, newStr: string |
| exec / bash | 执行 Shell 命令 | command: string, timeout?: number |
| ls | 列出目录下的文件与子目录 | path: string |
| mkdir | 创建目录 | path: string |
| grep | 在目录中搜索文本 | pattern: string, path: string |
工具注册 API
| registerTool(toolDef) | toolDef: ToolDefinition | 向当前会话动态注册单个工具 |
| registerTools(toolDefs) | toolDefs: ToolDefinition[] | 批量注册多个工具 |
| unregisterTool(toolName) | toolName: string | 移除指定名称的工具 |
五、会话持久化管理 API
SessionManager 通用接口
| createSession(sessionId?) | sessionId?: string | Promise<Session> | 创建新会话,不指定 ID 则自动生成 |
| loadSession(sessionId) | sessionId: string | Promise<Session> | 加载指定 ID 的历史会话 |
| saveSession(session) | session: Session | Promise<void> | 保存会话状态到存储 |
| listSessions() | 无 | Promise<SessionMeta[]> | 列出所有会话的元数据 |
| deleteSession(sessionId) | sessionId: string | Promise<void> | 删除指定会话 |
两种实现对比
| InMemorySessionManager | 内存 | 开发调试、短生命周期服务 | 无 |
| FileSessionManager | 本地 JSONL 文件 | 单节点生产部署、本地使用 | storageDir: string 存储目录路径 |
示例
const sessionManager = new FileSessionManager({
storageDir: '/data/pi-agent/sessions'
});
六、模型注册与认证 API
AuthStorage 认证存储
| AuthStorage.create() | 无 | 创建默认认证存储实例,自动读取环境变量 |
| setApiKey(provider, key) | provider: string, key: string | 设置指定提供商的 API 密钥 |
| getApiKey(provider) | provider: string | 获取指定提供商的 API 密钥 |
ModelRegistry 模型注册表
| ModelRegistry.create(authStorage) | authStorage: AuthStorage | 创建模型注册表实例 |
| addProvider(config) | providerConfig | 添加一个模型提供商(OpenAI/Anthropic/Ollama 等) |
| addModel(provider, modelConfig) | provider: string, modelConfig | 向指定提供商添加模型 |
| getModel(modelId) | modelId: string | 获取指定模型实例,格式 provider/model-name |
| listModels() | 无 | 列出所有可用模型 |
多提供商配置示例
modelRegistry.addProvider({
id: 'ollama',
type: 'openai-compatible',
baseUrl: 'http://localhost:11434/v1',
apiKey: 'ollama'
});
七、钩子扩展 API
钩子标准结构
interface AgentHook {
name: string; // 钩子唯一名称
preRun?: (ctx: HookContext) => void | Promise<void>;
postRun?: (ctx: HookContext) => void | Promise<void>;
preToolCall?: (ctx: ToolHookContext) => void | Promise<void>;
postToolCall?: (ctx: ToolHookContext) => void | Promise<void>;
onError?: (ctx: ErrorHookContext) => void | Promise<void>;
onCompaction?: (ctx: CompactionHookContext) => void | Promise<void>;
}
注册方式
const { session } = await createAgentSession({
// …其他配置
hooks: [loggerHook, auditHook, rateLimitHook]
});
常用钩子场景对应表
| 请求限流、用户鉴权、内容审核 | preRun |
| 结果回调、记忆存储、用量统计 | postRun |
| 工具权限校验、操作审计、执行确认 | preToolCall |
| 结果格式化、异常上报、耗时统计 | postToolCall |
| 错误告警、故障自动恢复 | onError |
| 压缩事件通知、压缩日志记录 | onCompaction |
八、上下文与状态查询 API
| session.getContextTokenCount() | number | 获取当前上下文的预估 Token 数 |
| session.getMessages() | Message[] | 获取当前会话的所有消息列表 |
| session.setSystemPrompt(prompt) | void | 动态修改系统提示词,下一轮生效 |
| session.triggerCompaction() | Promise<void> | 手动触发一次上下文压缩 |
| session.getAvailableTools() | ToolDefinition[] | 获取当前会话可用的工具列表 |
第二部分:生产级部署配置模板
以下模板面向单节点/多节点生产环境,遵循最小权限、故障自愈、可观测、可审计四大生产原则,可直接修改后投入使用。
1. 核心 Agent 生产配置 agent.prod.json
{
"id": "prod-coding-agent",
"name": "生产环境编码智能体",
"version": "1.0.0",
"model": {
"default": "anthropic/claude-3.5-sonnet",
"fallback": "deepseek/deepseek-reasoner",
"maxRetries": 3,
"timeout": 120000,
"enableFailover": true
},
"workspace": {
"rootDir": "/data/pi-agent/workspace/prod",
"sandboxEnabled": true,
"allowSymlink": false,
"allowAbsolutePath": false,
"maxFileSizeMB": 10
},
"context": {
"compaction": {
"enabled": true,
"thresholdRatio": 0.75,
"preserveRecentTurns": 6,
"preserveSystemPrompt": true,
"summaryModel": "anthropic/claude-3-haiku",
"maxSummaryLength": 2000
},
"maxTurnsPerRun": 30,
"overflowRecoveryAttempts": 2
},
"tools": {
"allow": ["read", "write", "edit", "ls", "mkdir", "grep", "safe_exec"],
"deny": ["bash", "rm", "chmod", "chown"],
"execWhitelist": [
"git status", "git diff", "git log –oneline -n 20",
"npm run build", "npm run lint", "npm test",
"python -m pytest", "go build", "go test"
],
"execTimeout": 30000,
"requireConfirmForDangerousOps": true
},
"security": {
"enableAuditLog": true,
"maskSensitiveData": true,
"sensitiveKeywords": ["api_key", "password", "secret", "token"],
"maxConcurrentSessions": 50
},
"hooks": {
"enabled": ["command-logger", "audit-trail", "rate-limiter", "error-alert"]
},
"systemPrompt": "你是生产环境代码助手,严格在沙箱内操作,执行命令前确认安全性,所有修改必须可回溯。输出简洁准确,禁止编造信息。"
}
2. 全局服务配置 openclaw.prod.json
{
"mode": "server",
"host": "0.0.0.0",
"port": 8787,
"session": {
"manager": "file",
"storageDir": "/data/pi-agent/sessions",
"maxIdleHours": 72,
"autoCleanup": true
},
"gateway": {
"enableCors": true,
"corsOrigins": ["https://your-domain.com"],
"rateLimit": {
"global": 100,
"perUser": 10,
"windowMs": 60000
},
"auth": {
"enabled": true,
"type": "bearer",
"apiKeysEnv": "OPENCLAW_API_KEYS"
}
},
"logging": {
"level": "info",
"format": "json",
"output": [
{ "type": "file", "path": "/var/log/pi-agent/app.log", "maxSize": "100MB", "maxFiles": 30 },
{ "type": "stdout" }
],
"enableRequestLog": true,
"enableToolAuditLog": true
},
"monitoring": {
"enableMetrics": true,
"metricsPort": 9090,
"exposePrometheus": true,
"trackTokenUsage": true,
"trackLatency": true
},
"agents": [
{ "id": "prod-coding-agent", "configPath": "/etc/pi-agent/agent.prod.json" }
]
}
3. 环境变量文件 .env.prod
# 服务基础配置
NODE_ENV=production
TZ=Asia/Shanghai
# 模型 API 密钥(严禁硬编码到配置文件)
ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxxxxxxxxxx
DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxxxx
# 服务鉴权
OPENCLAW_API_KEYS=prod-key-xxxxxx,admin-key-xxxxxx
# 路径配置
PI_AGENT_WORKSPACE=/data/pi-agent/workspace
PI_AGENT_SESSIONS=/data/pi-agent/sessions
PI_AGENT_LOGS=/var/log/pi-agent
# 性能配置
UV_THREADPOOL_SIZE=16
NODE_OPTIONS=–max-old-space-size=4096
# 告警配置
ALERT_WEBHOOK_URL=https://your-webhook.com/alert
4. Dockerfile 生产镜像模板
# 构建阶段
FROM node:24-alpine AS builder
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN npm install -g pnpm && pnpm install –frozen-lockfile
COPY . .
RUN pnpm build
# 运行阶段
FROM node:24-alpine AS runtime
WORKDIR /app
# 安装基础系统依赖
RUN apk add –no-cache git python3 curl tini
# 创建非 root 用户,遵循最小权限原则
RUN addgroup -S piagent && adduser -S piagent -G piagent
# 复制构建产物
COPY –from=builder /app/dist ./dist
COPY –from=builder /app/node_modules ./node_modules
COPY package.json ./
# 创建数据目录并授权
RUN mkdir -p /data/pi-agent/workspace /data/pi-agent/sessions /var/log/pi-agent \\
&& chown -R piagent:piagent /data/pi-agent /var/log/pi-agent
# 切换到非 root 用户
USER piagent
# 健康检查
HEALTHCHECK –interval=30s –timeout=5s –retries=3 \\
CMD curl -f http://localhost:8787/health || exit 1
EXPOSE 8787 9090
# 使用 tini 作为 PID 1,处理僵尸进程
ENTRYPOINT ["/sbin/tini", "–"]
CMD ["node", "dist/server.js"]
5. docker-compose.yml 编排模板
version: '3.8'
services:
pi-agent:
build: .
container_name: pi–agent–prod
restart: always
env_file: .env.prod
ports:
– "8787:8787"
– "9090:9090"
volumes:
– ./config/agent.prod.json:/etc/pi–agent/agent.prod.json:ro
– ./config/openclaw.prod.json:/etc/pi–agent/openclaw.prod.json:ro
– workspace_data:/data/pi–agent/workspace
– session_data:/data/pi–agent/sessions
– log_data:/var/log/pi–agent
networks:
– agent–network
deploy:
replicas: 1
resources:
limits:
cpus: '4'
memory: 4G
reservations:
cpus: '1'
memory: 1G
security_opt:
– no–new–privileges:true
cap_drop:
– ALL
prometheus:
image: prom/prometheus:latest
container_name: pi–agent–prometheus
restart: always
ports:
– "9091:9090"
volumes:
– ./config/prometheus.yml:/etc/prometheus/prometheus.yml:ro
– prometheus_data:/prometheus
networks:
– agent–network
depends_on:
– pi–agent
loki:
image: grafana/loki:latest
container_name: pi–agent–loki
restart: always
ports:
– "3100:3100"
volumes:
– loki_data:/loki
networks:
– agent–network
volumes:
workspace_data:
session_data:
log_data:
prometheus_data:
loki_data:
networks:
agent-network:
driver: bridge
6. Nginx 反向代理配置
server {
listen 80;
server_name agent.your-domain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name agent.your-domain.com;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# 客户端请求体大小限制
client_max_body_size 10M;
# SSE 流式响应配置
location / {
proxy_pass http://pi-agent:8787;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_cache off;
chunked_transfer_encoding on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 长连接超时,适配长任务
proxy_read_timeout 600s;
proxy_send_timeout 600s;
}
# 指标接口限制内网访问
location /metrics {
allow 10.0.0.0/8;
deny all;
proxy_pass http://pi-agent:9090;
}
# 健康检查
location /health {
proxy_pass http://pi-agent:8787/health;
}
}
7. 生产部署核心最佳实践清单
安全合规
- 始终以非 root 用户运行进程,禁用不必要的系统权限
- 所有密钥通过环境变量或密钥管理服务注入,禁止写入配置文件
- 启用沙箱与命令白名单,严格限制 Agent 的操作边界
- 开启全量审计日志,所有工具调用可追溯、可回放
高可用保障
- 配置多模型故障转移,单提供商故障时自动切换
- 设置合理的超时与重试机制,避免单次失败导致任务中断
- 会话数据挂载持久化存储卷,容器重启不丢失数据
- 多节点部署时使用共享存储(NAS/分布式文件系统)存放会话
性能优化
- 根据机器配置限制最大并发会话数,避免资源耗尽
- 开启空闲会话自动清理,释放内存与存储资源
- 长任务场景调大 Nginx 与服务端的超时时间
- 定期清理过期会话日志,控制存储容量增长
可观测性
- 接入 Prometheus + Grafana 监控请求量、耗时、错误率、Token 消耗
- 接入 Loki 集中收集日志,支持按会话、用户、错误类型检索
- 配置错误告警,关键异常实时通知运维人员
- 定期审计工具调用日志,发现异常行为及时处置





