欢迎光临
我们一直在努力

【PI Agent 】PI Agent 极简教程:OpenClaw 背后的嵌入式 Agent 引擎全解 &「极简、可控、透明」的核心设计理念赏析

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 框架的三大痛点:

  • 不可控的上下文:多数框架会在后台隐式注入大量 Prompt,开发者无法精确控制输入模型的每一个 Token,导致输出不稳定;
  • 黑盒式调试体验:Agent 执行出错时,无法定位是 Prompt、模型还是工具执行的问题;
  • 自托管兼容性差:依赖云端 SDK,对接本地部署的大模型(如 Ollama、vLLM)时工具调用频繁出错。
  • 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 的能力栈分为四层,从底层到上层依次叠加:

  • 基础工具层:PI 原生提供的编码基础工具,包括 read、bash、edit、write 四个核心工具,覆盖文件操作与命令执行的核心需求;
  • 自定义替换层:宿主应用(如 OpenClaw)可以替换基础工具的实现,比如用带沙箱的 exec 替换原生 bash,用带路径限制的 read/write 替换原生文件工具,实现安全管控;
  • 平台工具层:OpenClaw 注入的平台级工具,包括消息发送、浏览器自动化、画布操作、会话管理、定时任务、网关控制等;
  • 渠道工具层:针对不同消息渠道的专属工具,比如 Telegram 的消息回复、Discord 的频道管理等。
  • 每一层工具都遵循统一的注册与调用规范,上层工具可以复用下层能力,同时通过策略过滤机制,按配置文件、模型提供商、智能体角色、群组、沙箱等级别控制工具的可用范围。

    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(上下文组装)

    上下文组装是整个循环中最关键的环节之一,直接决定了模型的输出质量与稳定性。该阶段负责构建发送给大模型的完整上下文,包括:

  • 系统提示词:定义 Agent 的核心身份、行为准则与工具使用规则;
  • Bootstrap 上下文:启动时注入的基础信息,比如工作目录、可用工具列表、环境信息等;
  • 历史会话消息:当前会话的历史对话与工具调用记录,按时间顺序排列;
  • 工具定义:当前可用工具的 Schema 描述,供模型识别与调用;
  • 记忆内容:从长期记忆中检索到的相关信息(可选)。
  • PI Agent 在该阶段会严格控制上下文的 Token 数量,当接近模型上下文窗口上限时,会触发自动压缩机制,这部分会在后续章节详细讲解。

    2.2.3 阶段三:Model Inference(模型推理)

    模型推理阶段负责调用大语言模型,基于组装好的上下文生成回复。PI Agent 原生支持流式输出(Streaming),可以逐 Token 返回模型生成的内容,提升交互体验。

    该阶段的核心逻辑:

  • 通过 pi-ai 抽象层调用指定的大模型,传入上下文与工具定义;
  • 接收模型的流式输出,实时分发事件给上层应用;
  • 解析模型输出,判断是普通文本回复还是工具调用请求。
  • 如果模型输出的是普通文本,循环会进入最终的结果输出阶段;如果模型输出了工具调用(Tool Call),则进入工具执行阶段。

    2.2.4 阶段四:Tool Execution(工具执行)

    工具执行阶段负责解析模型的工具调用请求,校验工具权限,执行对应的工具函数,并获取执行结果。 执行流程包括:

  • 校验工具名称是否在可用列表中,校验参数是否符合 Schema 定义;
  • 调用对应工具的处理函数,传入参数;
  • 捕获工具执行中的错误,标准化为错误信息;
  • 将工具执行结果(成功/失败)格式化为消息,回填到上下文中。
  • 工具执行完成后,循环会回到「模型推理」阶段,将工具结果交给模型,让模型基于执行结果继续思考,生成下一步操作或最终回答。

    2.2.5 阶段五:Response(结果输出)

    当模型生成最终的自然语言回答、不再调用工具时,循环进入收尾阶段。该阶段负责:

  • 汇总本次循环的所有消息与工具执行记录;
  • 更新会话状态与持久化存储;
  • 触发后置钩子(Post-run Hook);
  • 向调用方返回最终结果与完整的会话快照。
  • 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 会自动触发上下文压缩。 压缩的核心逻辑:

  • 保留系统提示词、Bootstrap 上下文与最近的几条消息;
  • 将较早的历史对话交给大模型进行总结,生成一段精简的历史摘要;
  • 用摘要替换原始的历史消息,大幅减少 Token 占用;
  • 压缩后的上下文重新组装,继续执行任务。
  • 压缩过程是自动且透明的,开发者不需要手动干预,也可以通过配置调整压缩阈值与摘要策略。

    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 启动初始化向导,按提示完成基础配置:

  • API 密钥配置:选择你使用的大模型提供商,输入对应的 API Key。支持 Anthropic、OpenAI、DeepSeek、通义千问等主流厂商,也可以后续配置本地模型;
  • 默认模型选择:选择默认使用的模型,推荐编码场景使用 DeepSeek Reasoner 或 Claude Opus;
  • 渠道配置:选择需要接入的消息渠道(Telegram、Discord 等),新手可以选择「Skip for now」跳过,后续再添加;
  • 钩子功能配置:推荐启用 command-logger(命令日志)和 session-memory(会话记忆)两个钩子,提升调试与记忆能力;
  • 启动模式选择:选择「Hatch in TUI」,进入终端交互界面。
  • 完成向导后,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 工具由三部分组成:

  • 元数据:工具的名称、描述、版本,用于模型识别;
  • 参数 Schema:输入参数的 JSON Schema 定义,用于参数校验与模型理解;
  • 处理函数:工具的具体执行逻辑,接收参数,返回结果。
  • 工具定义的 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 支持从三个维度控制工具权限:

  • 白名单/黑名单:通过 tools.allow 和 tools.deny 配置允许或禁止的工具;
  • 执行上下文隔离:工具执行时传入的 context 对象包含会话信息、用户信息、权限等级,工具内部可以根据上下文做权限校验;
  • 路径沙箱:文件操作类工具默认限制在工作目录内,禁止访问上级目录与系统敏感路径。
  • 对于高危工具(如命令执行、系统操作),建议开启执行确认机制,在工具执行前向用户确认,避免误操作。

    4.1.4 工具开发最佳实践
  • 单一职责:每个工具只做一件事,功能清晰,模型更容易正确调用;
  • 描述精准:工具的 description 要写清楚功能、适用场景与注意事项,这直接影响模型调用的准确率;
  • 错误处理:工具内部必须捕获所有异常,返回标准化的错误结果,不要直接抛出异常导致 Agent 中断;
  • 返回简洁:工具返回结果尽量精简,避免返回大量无关信息占用上下文 Token;
  • 幂等设计:尽量让工具具备幂等性,重复调用不会产生副作用,避免重试时造成重复操作。
  • 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 钩子开发最佳实践
  • 保持轻量:钩子逻辑不要太复杂,避免阻塞 Agent 的主执行流程;
  • 错误隔离:钩子内部的错误不要影响主流程,必须捕获异常;
  • 上下文传递:通过 context 对象在不同钩子间传递数据,不要使用全局变量;
  • 可配置:钩子支持传入配置参数,提升复用性。
  • 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 使用流程
  • 提前将知识库文档导入向量数据库(可写一个导入脚本,也可以让 Agent 自己调用导入工具);
  • 用户提问后,Agent 自动调用检索工具获取相关内容;
  • 基于检索内容生成回答,确保答案有据可依。
  • 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 速度与成本的核心因素,优化方向:

  • 精简系统提示词:只保留核心规则,删除冗余描述。PI Agent 的设计理念就是极简提示词,不要堆砌过多规则;
  • 控制工具数量:只注册当前场景需要的工具,工具越多,Tool Definition 占用的 Token 越多;
  • 优化工具返回值:工具返回结果尽量精简,只返回核心信息,避免大量冗余内容;
  • 合理设置压缩阈值:阈值设置过低会频繁压缩,增加模型调用开销;设置过高容易触发溢出。建议设置在上下文窗口的 70%-80%。
  • 6.1.2 工具执行优化
  • 并行工具调用:如果多个工具调用之间没有依赖,可以开启并行执行,同时调用多个工具,减少总耗时;
  • 工具结果缓存:对于查询类工具,相同参数的调用结果可以缓存,避免重复执行;
  • 异步长任务处理:对于执行时间长的工具,可以采用异步模式,立即返回任务 ID,后续轮询任务状态,避免阻塞 Agent 循环。
  • 6.1.3 并发性能调优
  • 限制最大并发数:根据服务器 CPU 与内存配置,设置合理的最大并发会话数,避免资源耗尽;
  • 会话复用:同一用户的多次请求复用同一个会话,避免频繁创建销毁会话的开销;
  • 空闲会话回收:长时间不活跃的会话自动清理,释放内存资源。
  • 6.2 常见问题与故障排查

    6.2.1 上下文溢出错误

    现象:执行时报错 context_length_exceeded,任务中断。 排查步骤:

  • 检查是否开启了自动压缩功能;
  • 检查压缩阈值是否设置过高;
  • 检查是否有单次工具返回结果特别长;
  • 检查是否历史会话积累了太多消息。 解决方案:
    • 启用自动压缩并调低阈值;
    • 对返回内容大的工具做结果截断或分页;
    • 定期清理会话历史,或手动触发压缩;
    • 更换更大上下文窗口的模型。
    6.2.2 工具调用失败

    现象:模型生成了工具调用,但执行失败,或者模型反复调用错误的工具。 排查步骤:

  • 检查工具参数是否符合 Schema 定义;
  • 检查工具名称是否拼写正确;
  • 检查工具描述是否清晰,模型是否正确理解工具用途;
  • 检查工具是否在可用白名单中。 解决方案:
    • 优化工具描述与参数说明,增加使用示例;
    • 对于复杂参数,在 description 中给出格式示例;
    • 开启参数校验,错误时返回明确的错误信息,引导模型修正;
    • 更换推理能力更强的模型。
    6.2.3 模型调用无响应

    现象:发起任务后长时间没有输出,模型调用超时。 排查步骤:

  • 检查网络连接是否正常,能否访问模型 API;
  • 检查 API Key 是否有效,是否有额度;
  • 检查模型是否支持当前地区访问;
  • 检查是否上下文过大导致生成速度极慢。 解决方案:
    • 配置超时时间与重试机制;
    • 启用多账户故障转移;
    • 检查网络代理配置;
    • 精简上下文,降低生成长度。
    6.2.4 会话数据丢失

    现象:重启程序后历史会话消失。 排查步骤:

  • 检查是否使用了内存会话管理器;
  • 检查文件会话的存储目录是否正确;
  • 检查存储目录是否有写入权限;
  • 检查 JSONL 文件是否损坏。 解决方案:
    • 使用 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 封装的最高频入口,用于创建智能体会话实例。

    API 名称核心参数返回值功能说明最简示例
    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 实例上的核心方法,用于驱动任务、控制执行、干预流程。

    API 名称核心参数返回值功能说明最简示例
    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
    API 名称参数返回值功能说明
    session.subscribe(callback) callback: (event: AgentEvent) => void () => void 取消订阅函数 订阅会话的所有执行事件,返回取消订阅的方法
    全量事件类型清单
    事件类型触发时机核心 Payload
    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
    API 名称参数功能说明
    registerTool(toolDef) toolDef: ToolDefinition 向当前会话动态注册单个工具
    registerTools(toolDefs) toolDefs: ToolDefinition[] 批量注册多个工具
    unregisterTool(toolName) toolName: string 移除指定名称的工具

    五、会话持久化管理 API

    SessionManager 通用接口
    API 名称参数返回值功能说明
    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 认证存储
    API 名称参数功能说明
    AuthStorage.create() 创建默认认证存储实例,自动读取环境变量
    setApiKey(provider, key) provider: string, key: string 设置指定提供商的 API 密钥
    getApiKey(provider) provider: string 获取指定提供商的 API 密钥
    ModelRegistry 模型注册表
    API 名称参数功能说明
    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

    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: piagentprod
    restart: always
    env_file: .env.prod
    ports:
    "8787:8787"
    "9090:9090"
    volumes:
    ./config/agent.prod.json:/etc/piagent/agent.prod.json:ro
    ./config/openclaw.prod.json:/etc/piagent/openclaw.prod.json:ro
    workspace_data:/data/piagent/workspace
    session_data:/data/piagent/sessions
    log_data:/var/log/piagent
    networks:
    agentnetwork
    deploy:
    replicas: 1
    resources:
    limits:
    cpus: '4'
    memory: 4G
    reservations:
    cpus: '1'
    memory: 1G
    security_opt:
    nonewprivileges:true
    cap_drop:
    ALL

    prometheus:
    image: prom/prometheus:latest
    container_name: piagentprometheus
    restart: always
    ports:
    "9091:9090"
    volumes:
    ./config/prometheus.yml:/etc/prometheus/prometheus.yml:ro
    prometheus_data:/prometheus
    networks:
    agentnetwork
    depends_on:
    piagent

    loki:
    image: grafana/loki:latest
    container_name: piagentloki
    restart: always
    ports:
    "3100:3100"
    volumes:
    loki_data:/loki
    networks:
    agentnetwork

    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 集中收集日志,支持按会话、用户、错误类型检索
    • 配置错误告警,关键异常实时通知运维人员
    • 定期审计工具调用日志,发现异常行为及时处置
  • 赞(0)
    未经允许不得转载:171主机测评 » 【PI Agent 】PI Agent 极简教程:OpenClaw 背后的嵌入式 Agent 引擎全解 &「极简、可控、透明」的核心设计理念赏析
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址