Pi Agent vs LangGraph:从人机交互、企业 RAG 到持久化工作流的完整选型指南

最近我一直在研究 Pi、OpenCode、Codex 这类 Coding Agent。它们已经具备模型调用、工具执行、会话管理、流式输出和扩展机制,甚至可以在执行过程中向用户提出结构化问题,等待用户选择后继续运行。

这很容易引出两个问题:

  1. Pi Agent 已经可以嵌入应用、注册工具、保存会话,它能不能直接做企业 RAG?
  2. 如果 Pi 可以做这些事情,LangGraph 还有什么是它做不了的?

我最终得到的结论是:

Pi Agent 与 LangGraph 不是简单的竞品关系。Pi 更接近一个可嵌入、可扩展的模型驱动 Agent Harness;LangGraph 更接近一个以显式状态和持久化执行为核心的工作流运行时。

两者都能完成工具调用,也都有状态,但它们把不同问题放在了架构中心。

一、先建立共同基础:Agent Loop 到底做了什么

不管是 Pi、OpenCode 还是 Codex,最小 Agent 都离不开下面这个反馈循环:

text 复制代码
用户输入
  → Agent 把消息和工具描述发送给模型
  → 模型输出文本或 tool_call
  → Agent 根据工具名找到执行函数
  → 验证参数并执行工具
  → 把 tool_result 写入 Context
  → 再次调用模型
  → 直到没有新的工具调用

模型本身不能直接读取本地文件、数据库或者企业知识库。它只是生成一个结构化的行动请求,例如:

json 复制代码
{
  "type": "function_call",
  "call_id": "call_42",
  "name": "kb_search",
  "arguments": {
    "query": "差旅报销需要哪些材料?"
  }
}

Agent Runtime 收到以后,调用真正的检索服务,再把结果写成对应的工具返回:

json 复制代码
{
  "type": "function_call_output",
  "call_id": "call_42",
  "output": {
    "results": [
      {
        "title": "员工差旅报销制度",
        "content": "报销时需要提交......",
        "source": "https://knowledge.example/policy/42"
      }
    ]
  }
}

模型下一轮能够回答,是因为工具结果重新进入了 Context。

因此,一个 Coding Agent 的核心并不是"模型会写代码",而是它建立了模型与外部环境之间持续反馈的闭环。

二、Agent 为什么能暂停并询问用户

OpenCode 或 Pi 在执行过程中弹出问题,让用户从几个选项中选择,本质上仍然是一次工具调用。

模型可能输出:

json 复制代码
{
  "name": "ask_user",
  "call_id": "question_123",
  "arguments": {
    "question": "你希望采用哪种实现?",
    "options": [
      {
        "label": "方案 A",
        "description": "改动较少,兼容现有实现"
      },
      {
        "label": "方案 B",
        "description": "重构成本较高,但边界更清晰"
      }
    ]
  }
}

接下来不是模型服务一直保持连接等待用户,而是 Agent Runtime 保存等待状态:

text 复制代码
模型调用 ask_user
      │
      ▼
Runtime 创建 pending[question_123]
      │
      ▼
向 TUI / Desktop / Web UI 发送问题事件
      │
      ▼
用户选择方案 B
      │
      ▼
前端回传 answer(question_123, "方案 B")
      │
      ▼
Runtime 完成等待,将答案作为 tool_result 返回模型

OpenCode 的方式

OpenCode 核心中存在 question 工具。其 Question Service 会创建 Question ID 和一个 Deferred,把问题放入 Pending Map,发布 Asked 事件,然后等待 Reply。客户端回传答案后,对应的 Deferred 被完成,Agent 才继续运行。

Pi 的方式

Pi 扩展可以调用 ctx.ui.select()、confirm()、input() 和 editor(),也可以通过 pi.registerTool() 注册一个模型可调用的 question 工具。

在交互式终端中,Pi 自己渲染界面;在 RPC 模式中,Pi 只发送 JSON 请求,由外部客户端负责展示。

三、RPC 模式解决的是什么问题

RPC 是 Remote Procedure Call。这里的"远程"可以只是本机中的两个进程,并不一定经过公网。

Pi 使用普通 TUI 时:

text 复制代码
Pi Runtime + 终端渲染 + 键盘输入

Pi 使用 RPC 模式时:

text 复制代码
Pi 后台进程
   │ JSON 请求和事件
   ▼
桌面应用 / VS Code 插件 / 企业 Web 后端

例如 Pi 发出:

json 复制代码
{
  "type": "extension_ui_request",
  "id": "uuid-1",
  "method": "select",
  "title": "选择处理方式",
  "options": ["直接回答", "转人工复核"]
}

客户端选择后返回:

json 复制代码
{
  "type": "extension_ui_response",
  "id": "uuid-1",
  "value": "转人工复核"
}

RPC 让 Agent Runtime 与界面解耦。同一个 Pi 后端可以连接终端、桌面软件、编辑器插件或者企业自己的网页。

但需要注意:当前进程中的 UI 等待,和能够跨进程重启、跨天恢复的持久化审批,不是同一种能力。这一点正是 Pi 与 LangGraph 的重要边界之一。

四、Pi 如何实现企业知识库 RAG

Pi 不是向量数据库,也不应该承担所有文档解析和权限管理。更合理的架构是:

text 复制代码
Pi:对话、推理和工具调度
RAG 服务:文档解析、索引、权限、检索和重排
身份系统:用户、租户、组织和角色
业务系统:工单、ERP、CRM、审批等真实数据与副作用

4.1 离线知识摄取

text 复制代码
企业网盘 / Wiki / PDF / Word / 数据库
  → 连接器同步
  → 文本、标题、表格和 OCR 解析
  → 按语义和标题结构分块
  → 补充文档元数据和 ACL
  → 生成 Embedding
  → 建立关键词与向量索引

一个企业 Chunk 不应该只有文本和向量,还应保存:

json 复制代码
{
  "chunkId": "expense-policy#3.2",
  "documentId": "expense-policy",
  "title": "员工差旅报销制度",
  "content": "......",
  "source": "https://knowledge.example/expense-policy",
  "tenantId": "tenant-a",
  "allowedGroups": ["all-employees"],
  "department": "finance",
  "version": "2026-08",
  "updatedAt": "2026-08-20T10:00:00+08:00"
}

4.2 在线问答

text 复制代码
用户问题
  → Pi 调用 kb_search
  → RAG 服务读取可信登录态
  → ACL 权限过滤
  → 关键词+向量混合检索
  → Reranker 重排
  → 返回少量证据片段和来源
  → Pi 根据证据生成回答与引用

在 Pi 中可以注册一个自定义工具。下面是简化示例:

ts 复制代码
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
import { Type } from "typebox";

export default function (pi: ExtensionAPI) {
  pi.registerTool({
    name: "kb_search",
    label: "企业知识库检索",
    description:
      "搜索企业内部知识库。回答内部政策、产品和流程问题前调用。",
    parameters: Type.Object({
      query: Type.String({
        description: "完整且适合检索的问题",
      }),
      topK: Type.Optional(
        Type.Number({ minimum: 1, maximum: 10 }),
      ),
    }),

    async execute(_toolCallId, params, signal) {
      const response = await fetch(
        "https://knowledge.internal/api/search",
        {
          method: "POST",
          signal,
          headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${process.env.KB_SERVICE_TOKEN}`,
          },
          body: JSON.stringify({
            query: params.query,
            topK: params.topK ?? 6,
          }),
        },
      );

      if (!response.ok) {
        throw new Error(`检索失败:${response.status}`);
      }

      const data = await response.json();

      return {
        content: [
          {
            type: "text",
            text: JSON.stringify({ results: data.results }),
          },
        ],
        details: data,
      };
    },
  });
}

4.3 为什么要把 RAG 做成独立服务

这样做至少有五个好处:

  1. 检索能力可以被 Pi、网页搜索框、客服机器人等多个入口复用;
  2. 权限逻辑集中在可信服务端,而不是依赖 Prompt;
  3. 文档更新和重新索引不影响 Agent Runtime;
  4. 可以独立评测召回率、重排质量和检索延迟;
  5. 更换 Pi、LangGraph 或模型时,企业知识层不需要重做。

4.4 企业 RAG 中最容易被忽略的安全问题

不要让模型自己传入用户身份:

json 复制代码
{
  "query": "查询董事会薪酬制度",
  "userId": "admin"
}

userId、tenantId 和权限组必须来自登录态、网关或服务端 Token。否则用户可能通过 Prompt 诱导模型修改参数,实现越权检索。

权限过滤也必须发生在检索层,而不是先把所有结果返回模型,再要求模型"忽略无权内容"。只要敏感内容进入模型上下文,就已经发生了数据暴露。

五、LangGraph 与 Pi 的核心差异

如果只问"能不能写出来",Pi 扩展可以执行任意 TypeScript,理论上可以继续实现状态机、数据库、队列和恢复机制。因此,很难说某个功能在绝对意义上 Pi 永远做不了。

但工程选型应该比较的是:哪些能力由框架提供,哪些需要项目自己维护。

维度 Pi Agent LangGraph
核心抽象 Agent、Messages、Model、Tools、Events State、Nodes、Edges、Commands、Subgraphs
控制流 模型通常决定下一工具 固定边、条件边、规则或模型共同决定
工具调用 原生,Coding Agent 体验成熟 原生,但需要自行组装产品界面
自定义交互 扩展 UI、Question Tool、RPC Interrupt 返回任意可序列化信息
并行能力 可并行执行工具 原生 fan-out/fan-in、superstep、reducer
会话保存 Messages 与会话树 完整图状态 Checkpoint
失败恢复 业务级恢复需要自行实现 可从检查点恢复节点执行
长期人工等待 需要外部数据库和恢复协议 Checkpointer + interrupt 原生组合
时间旅行 会话历史分支 工作流状态检查、重放和分叉
流程强约束 Prompt 或外部代码 图拓扑直接约束
最适合 开放式工具任务、Coding、MVP 长流程、审批、故障恢复、审计

六、LangGraph 真正原生解决、Pi 需要自己补齐的能力

6.1 显式且强制的业务状态机

假设退款流程规定:

text 复制代码
身份校验
  → 订单查询
  → 规则检查
  → 金额超过阈值时人工审批
  → 执行退款
  → 写入审计

如果只给 Pi 一段 Prompt:"务必先校验,再审批,最后退款",模型仍然可能由于上下文、工具描述或异常情况跳过步骤。

LangGraph 可以把顺序直接写成图。模型只负责某个节点内部的开放式判断,不能越过不存在的边。

6.2 并行分支与确定性的状态合并

企业问题可能需要同时查询:

text 复制代码
订单系统 ─┐
设备系统 ─┼─► 汇总诊断
知识库   ─┘

Pi 可以并行执行多个工具,但 LangGraph 进一步定义了并行节点属于同一个 superstep,以及不同节点对共享状态的更新怎样通过 Reducer 合并。

这使得"并行执行"和"并行工作流状态管理"成为两个不同层次的问题。

6.3 持久化检查点与故障恢复

LangGraph 的 Checkpointer 可以在执行步骤边界保存图状态:

json 复制代码
{
  "currentStep": "human_review",
  "ticketId": "T-1001",
  "retrievedEvidence": ["chunk-1", "chunk-9"],
  "confidence": 0.63,
  "approvalStatus": "waiting"
}

如果服务重启,可以从当前 Thread 的检查点恢复,而不是重新执行已经完成的查询。

Pi 能保存会话和工具消息,但这不自动等于完整业务状态检查点。项目仍需回答:

  • 当前业务节点是什么?
  • 哪些并行任务已经成功?
  • 哪个 API 调用不能重复?
  • 恢复后应该重试、跳过还是补偿?
  • 审批结果属于哪个业务版本?

6.4 跨天 Human-in-the-loop

Pi 的 select() 很适合当前交互会话中的选择。

但是如果任务需要等待两天,期间服务可能发布、扩容或重启,仅仅在内存中等待一个 Promise 并不可靠。

LangGraph 的 interrupt() 会把图状态写入 Checkpointer,通过 thread_id 恢复。人工可以查看、批准、拒绝甚至修改状态后,再从相同流程位置继续。

6.5 时间旅行与问题排查

当一个生产 Agent 给出错误决定时,排查问题不能只看最终对话。往往需要知道:

text 复制代码
当时的状态是什么?
哪个节点修改了哪个字段?
采用了哪条条件分支?
如果修改某个状态,后续结果会怎样变化?

LangGraph 的状态历史和检查点可以支持回看、重放和分叉。Pi 的会话树适合对话历史导航,但业务工作流状态仍需应用自行建模。

七、三个选型场景

场景一:简单企业知识问答

需求:员工询问制度,系统检索知识库并返回引用。

text 复制代码
问题 → kb_search → Pi 生成带引用答案

选择:Pi + 独立 RAG 服务。

原因是流程很短,主要不确定性来自自然语言理解和检索,没有必要为了两个节点引入完整图编排。

场景二:跨系统售后工单

需求:识别问题、补齐信息、查询设备与订单、检索 SOP、判断保修、人工审批、创建派工单,流程可能持续数天。

选择:LangGraph 更合适。

这里的主要难点已经不是模型会不会调用工具,而是状态、顺序、恢复、幂等和审计。

场景三:既要可靠流程,又要开放式推理

选择:LangGraph 编排 + Pi Agent 节点。

text 复制代码
LangGraph
  ├── 权限校验节点
  ├── 订单查询节点
  ├── Pi 开放式诊断节点
  ├── 人工审批节点
  ├── 业务执行节点
  └── 审计节点

在这种结构里:

  • LangGraph 管理必须可靠的业务流程;
  • Pi 负责需要模型自主探索和多工具推理的局部任务;
  • RAG 服务继续保持独立;
  • 所有真实写操作使用幂等键并接受权限控制。

八、为什么不能只用 Prompt 控制流程

Prompt 是柔性约束,程序拓扑和权限策略才是硬约束。

适合写进 Prompt 的内容包括:

  • 回答风格;
  • 如何引用资料;
  • 什么时候建议调用某个工具;
  • 证据不足时应该怎样表达。

不应该只依赖 Prompt 的内容包括:

  • 是否允许查看某份敏感文档;
  • 是否必须经过审批;
  • 是否允许退款或创建工单;
  • 某个步骤失败后是否能够继续;
  • 恢复执行时是否会重复扣款或重复创建记录。

这些要求必须落实到权限系统、状态机、幂等机制和持久化层。

九、如何通过一个小实验做选型

不要只阅读框架介绍,可以选一条脱敏流程,同时用两种方式实现:

text 复制代码
客户报修
  → 补齐序列号
  → 查询保修
  → 检索 SOP
  → 给出处置建议
  → 人工批准
  → 创建模拟派工单

两组使用相同模型、Prompt、知识库和工具。

Pi 组

  • 用工具描述和 Prompt 引导流程;
  • 用自定义工具实现检索和模拟派工;
  • 自己补充审批状态、恢复和幂等逻辑;
  • 记录为此新增的框架外代码。

LangGraph 组

  • 把业务事实放入 Typed State;
  • 把查询、检索、审批和执行拆成节点;
  • 使用 Checkpointer 和 interrupt;
  • 在多个位置主动终止进程,验证恢复行为。

建议比较的指标

类别 指标
正确性 任务完成率、工具参数正确率、引用准确率
恢复 崩溃恢复成功率、重复副作用次数、审批续跑正确率
工程 胶水代码量、新增分支改动面、测试和调试时间
运行 P50/P95、Token、模型调用次数、基础设施成本
治理 权限拦截、审批记录、Trace 完整度、人工接管体验

正确的问题不是谁的 Demo 代码更短,而是谁在目标 SLA 和风险等级下拥有更低的完整系统成本。

十、最终结论

Pi Agent 的优势是轻量、直接、交互性强、工具扩展方便,能够快速构建 Coding Agent、内部助手和企业知识问答。

LangGraph 的优势是显式状态、确定性流程、并行汇合、持久化检查点、故障恢复、长期人工介入以及工作流级别的观察和重放。

所以:

text 复制代码
单 Agent + 开放式工具任务
    → 优先 Pi

简单 RAG 问答
    → Pi + 独立检索服务

固定步骤 + 分支 + 审批 + 恢复 + 审计
    → 优先 LangGraph

复杂业务流程中包含开放式 Agent 推理
    → LangGraph 编排 + Pi 节点

与其争论"谁会替代谁",更值得掌握的是 Agent Loop、Tool Calling、状态建模、权限、幂等、Checkpoint、Human-in-the-loop 和 RAG 检索。这些知识不会因为下一个 Agent 框架出现而失效。

相关推荐
Johny_Zhao2 小时前
FreeRADIUS + 华为AC/AP + 802.1X/WPA2-Enterprise 无线认证对接部署完整指南
网络·网络安全·信息安全·ldap·radius·huawei·系统运维·centos8
EatFan2 小时前
Spring Boot 4 落地观察:从 yudao-cloud、matecloud、JPower 看国产脚手架的升级路线与迁移清单
java·spring boot·后端·spring cloud·微服务·后端开发·jdk 21
Maiko Star3 小时前
* LangChain 提示词模板详解:ChatPromptTemplate 的使用与高级特性
java·人工智能·langchain
天远API3 小时前
零信任架构实战:基于天远人企关联构建自动化图谱网关
网络·人工智能·架构·自动化
vipjx14 小时前
百度网盘限速怎么破?2026实测PanDownload多线程提速方案
网络·智能路由器
现任明教教主~5 小时前
Thinkphp站群蜘蛛池SaaS系统YanyvSEO含多用户/积分/六大引擎计费/易支付对接
java·开发语言·spring
一条破秋裤5 小时前
Linux 线程创建:pthread_create 与基本回收
java·linux·运维
布吉岛的石头6 小时前
Java 程序员第 49 阶段5:BERT 预训练目标 MLM+NSP 的工程含义
java·人工智能·深度学习·bert·transformer
不会就选b6 小时前
Linux之应用层协议HTTP(二)
网络·网络协议·http
hasty6 小时前
只监听本机为何仍需鉴权?Cline Hub 的 WebSocket 信任边界解析
网络·websocket·网络协议