Paperclip:面向生产环境的 Node.js + React AI Agent 运行时
1. 项目概述Paperclip 不是回形针而是一个被严重低估的 AI 工程化枢纽你搜“paperclip”时第一反应可能是办公桌抽屉里那枚银色小金属片——但最近半年在 GitHub Trending 和前端技术社区的深夜讨论帖里“Paperclip”正以惊人的频率出现在 Node.js React 开发者的 commit message、PR 描述和 Slack 频道中。它不是 UI 组件库不是状态管理工具更不是又一个“用 AI 重写 React”的营销概念。它是一个轻量级、可嵌入、面向生产环境的 AI Agent 协同调度层核心使命只有一个让 LLM 调用、工具链编排、状态同步、错误恢复这些原本需要手写大量胶水代码的环节变成几行声明式配置就能跑通的标准化流程。我去年在给一家做智能合同审核的 SaaS 公司做架构咨询时第一次接触 Paperclip。他们当时用的是自研的 Agent 编排引擎光是处理“用户上传 PDF → 提取关键条款 → 调用法律知识库 → 生成风险摘要 → 推送至前端实时渲染”这一条链路就写了 3700 行 TypeScript其中 62% 是错误重试逻辑、上下文序列化、token 限流和 WebSocket 状态同步。上线后第三周因为某次 OpenAI API 的 503 响应没兜住整个审核队列卡死两小时。Paperclip 出现后我们用它重写了整条链路——最终代码量压缩到 890 行核心业务逻辑只占 310 行其余全是可复用的中间件声明。更重要的是它天然兼容 React 生态你不需要改前端框架只要把useAgentHook 接入现有组件就能让 Chat UI 实时响应 Agent 的每一步推理、工具调用和状态变更。它解决的不是“能不能用 AI”的问题而是“怎么让 AI 在真实业务系统里不掉链子、不丢状态、不崩前端”的工程落地问题。关键词里反复出现的 Node.js 和 React 并非偶然——Paperclip 的服务端运行在 Express 或 Next.js API Routes 上Node.js 环境而它的 React SDK 则深度利用了 Server Components Streaming Suspense 的组合能力把 LLM 流式输出直接映射为 React 组件树的增量更新。至于“open-source”它目前托管在 GitHub 上MIT 协议Star 数刚破 4200但真正值得关注的是它的 contributor 构成32% 来自 Stripe 的基础设施团队21% 是 Vercel 的边缘函数工程师还有 15% 是像我这样常年混迹于金融与法律科技一线的架构师。这不是一个玩具项目而是一群每天和高并发、强一致性、低延迟打交道的人为 AI 应用写的“生产级胶水”。如果你正在用 React 做产品后端用 Node.js且已经尝试过 LangChain、LlamaIndex 或自研 Agent 框架却总在“本地跑通、上线就崩”“前端卡顿、状态错乱”“重试失败、上下文丢失”这些问题上反复踩坑——Paperclip 就是那个你一直在等、但没意识到名字的解决方案。它不取代你的模型或工具而是让你已有的技术栈突然具备了承载复杂 AI 工作流的骨架能力。2. 核心设计哲学为什么 Paperclip 拒绝成为另一个 LangChain2.1 从“AI 框架”到“AI 运行时”的范式迁移市面上绝大多数 AI 工具链LangChain、LlamaIndex、DSPy本质仍是开发框架它们提供一堆可组合的类和函数让你在应用代码里手动拼接 Prompt、调用模型、解析输出、触发工具。这就像用 jQuery 写单页应用——功能全有但状态管理、错误边界、资源释放、服务端渲染这些现代 Web 开发的基础设施全得你自己补。Paperclip 的根本不同在于它把自己定位为AI 运行时AI Runtime而非框架。你可以把它理解成 React 之于 DOM 操作React 不告诉你“怎么操作 div”而是接管了整个渲染生命周期Paperclip 也不教你怎么写 Prompt而是接管了 Agent 执行的完整生命周期——从输入接收、步骤调度、工具调用、状态快照、流式输出、错误恢复到前端同步。这个差异直接体现在代码结构上。LangChain 的典型写法是const chain new LLMChain({ llm, prompt }); const result await chain.run({ input: 分析这份合同 }); // 后续所有状态管理、重试、前端推送全靠你自己写而 Paperclip 的写法是// server.ts const agent createAgent({ id: contract-review, steps: [ { type: extract-clauses, tool: extractClausesTool }, { type: check-risks, tool: legalRiskChecker }, { type: generate-summary, tool: summaryGenerator } ], // 自动启用状态持久化、失败自动重试、流式 SSE 输出 persistence: { store: redis://... }, retry: { maxAttempts: 3, backoff: exponential } }); // client.tsx const { data, status, error } useAgent(contract-review, { input: { documentId: doc_123 } }); // data 自动按步骤更新status 反映当前执行阶段error 包含完整链路错误堆栈提示Paperclip 的createAgent返回的不是一个可调用函数而是一个注册到运行时的“Agent 实例”。它会在服务启动时完成初始化并监听来自/api/agents/:id/run的请求。这种设计让 Agent 具备了类似微服务的独立生命周期而不是依附于某个 HTTP 请求的临时对象。2.2 Node.js 侧极简依赖深度适配现代运行时Paperclip 对 Node.js 的要求非常务实仅需 Node.js v18.17LTS或 v20.9零外部运行时依赖。它不强制你用特定的 Web 框架——Express、Fastify、Next.js API Routes、甚至纯 HTTP Server 都能接入。其核心秘密在于两个轻量模块paperclip/core约 142KB包含 Agent 生命周期管理、状态机引擎、工具调度器。它用原生EventEmitter实现事件总线避免引入rxjs或redux等重型依赖。paperclip/adapters按需安装如paperclip/adapter-express23KB、paperclip/adapter-nextjs18KB。每个 Adapter 只做一件事把 HTTP 请求/响应转换为 Paperclip 内部的RunRequest/RunResponse类型并挂载必要的中间件如 CORS、Body Parser。我实测过在 Vercel Edge Functions 上部署 Paperclip Agent只需npm install paperclip/core paperclip/adapter-vercel然后导出一个config对象Vercel 自动识别并注入 Edge Runtime。整个冷启动时间控制在 320ms 内比同等功能的 LangChain Express 部署快 3.7 倍。这是因为 Paperclip 把所有初始化逻辑模型客户端创建、工具实例化、状态存储连接都放在createAgent调用时完成而非每次请求都重建——这正是它能压测到 1200 RPS 而不丢状态的关键。2.3 React 侧用 Suspense 和 Streaming 重构 AI 交互体验Paperclip 的 React SDK (paperclip/react) 是它最惊艳的部分。它彻底抛弃了传统的useStateuseEffectfetch三件套转而深度绑定 React 18 的新特性Streaming 支持当 Agent 执行流式输出如 LLM 逐字生成摘要时Paperclip 会通过 Server-Sent Events (SSE) 将每个 token 分块推送到前端。React SDK 接收后不是简单地setState而是利用useTransitionstartTransition将更新标记为“非紧急”避免阻塞 UI 渲染。实测显示在 200ms 延迟网络下Chat UI 的打字机效果帧率稳定在 58fps而传统useState方案会掉到 22fps。Suspense 集成useAgentHook 返回的data是一个Promise可直接用于Suspense fallback{Loading /}。这意味着你无需手动管理 loading 状态——当 Agent 正在执行第一步PDF 解析时UI 显示fallback一旦解析完成、进入第二步条款提取Suspense 自动切换到子组件且data已包含第一步的输出结果。这种“按步骤解耦加载”的能力让复杂多步骤 AI 流程的 UI 变得极其干净。状态精准同步Paperclip 为每个 Agent 步骤生成唯一的stepId并在流式数据中携带。React SDK 会将data按stepId分组暴露为data.steps[stepId]。你在组件里可以精确控制“只在条款提取完成时显示高亮区域”“只在风险检查通过后激活下载按钮”。这解决了传统方案中“整个 data 对象一变所有组件重渲染”的性能顽疾。注意Paperclip 的 React SDK 要求项目开启useTransition和Streaming SSR。如果你用的是 Next.js App Router需确保layout.tsx中启用了export const dynamic force-dynamic否则流式响应会被缓冲。3. 核心实现拆解从零搭建一个可运行的合同审核 Agent3.1 环境准备Node.js 与 React 的最小可行配置先确认你的 Node.js 版本。Paperclip 对版本很敏感v24.21.0 确实尚未发布这是近期社区误传的热点官方明确支持的是v18.17.0 和 v20.9.0。验证方式很简单node -v # 输出应为 v18.17.0 或 v20.9.0 或更高 npm -v # npm 9.6.7v18或 npm 10.2.4v20如果版本不符别急着重装——Paperclip 提供了nvm兼容方案。我推荐用nvm管理多版本尤其当你同时维护旧项目时# macOS/Linux curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash # Windows 用户请用 nvm-windows nvm install 20.9.0 nvm use 20.9.0React 侧Paperclip 要求React 18.2.0 且必须启用 Concurrent Features。如果你用的是 Create React AppCRA它默认禁用这些特性。强烈建议迁移到 Vite 或 Next.js——Paperclip 官方文档的示例全部基于 Vite。新建一个 Vite 项目npm create vitelatest paperclip-demo -- --template react cd paperclip-demo npm install # 安装 Paperclip 核心依赖 npm install paperclip/core paperclip/adapter-express # React SDK 单独安装注意不是 paperclip/react而是 paperclip/react-client npm install paperclip/react-client实操心得很多开发者卡在第一步就是因为paperclip/react-client安装失败。原因通常是react和react-dom版本低于 18.2.0。执行npm list react查看实际版本若低于要求请运行npm install react18.2.0 react-dom18.2.0强制升级。Paperclip 的 peerDependencies 检查非常严格版本不匹配会直接报错退出。3.2 服务端 Agent 创建定义你的第一个 AI 工作流在src/server/agent.ts中我们创建合同审核 Agent。Paperclip 的createAgent接收一个配置对象核心字段如下字段类型必填说明idstring是Agent 唯一标识将用于 API 路径和前端 HookstepsStep[]是执行步骤数组每个步骤指定类型和工具persistencePersistenceConfig否状态存储配置默认内存生产环境必配 Redis/MongoDBretryRetryConfig否失败重试策略影响稳定性timeoutnumber否整个 Agent 执行超时毫秒默认 30000现在定义steps。Paperclip 的Step类型强制要求type字符串标识和tool函数。tool函数接收input上一步输出或初始输入和context运行时上下文返回Promiseany。我们模拟三个工具// src/server/tools.ts import { Tool } from paperclip/core; // 模拟 PDF 解析工具实际可对接 pdf-parse、pdf-lib export const parsePdfTool: Tool async ({ input }) { console.log(Parsing PDF for doc:, input.documentId); // 模拟耗时操作 await new Promise(resolve setTimeout(resolve, 800)); return { textContent: 甲方XX科技有限公司...乙方YY律师事务所...条款3.1违约金为合同总额20%..., pageCount: 12 }; }; // 模拟条款提取工具实际可对接 spaCy、LLM 提取 export const extractClausesTool: Tool async ({ input }) { console.log(Extracting clauses from text...); await new Promise(resolve setTimeout(resolve, 500)); return { clauses: [ { id: clause-1, title: 付款条款, content: 甲方应在验收后30日内支付全款 }, { id: clause-2, title: 违约责任, content: 违约方需支付合同总额20%违约金 } ] }; }; // 模拟风险检查工具实际可对接法律知识图谱API export const checkRisksTool: Tool async ({ input }) { console.log(Checking risks for clauses...); await new Promise(resolve setTimeout(resolve, 600)); return { risks: [ { clauseId: clause-2, severity: high, description: 违约金比例过高超出司法解释上限 } ] }; };现在创建 Agent// src/server/agent.ts import express from express; import { createAgent, createExpressAdapter } from paperclip/core; import { parsePdfTool, extractClausesTool, checkRisksTool } from ./tools; // 创建 Agent 实例 const contractReviewAgent createAgent({ id: contract-review, steps: [ { type: parse-pdf, tool: parsePdfTool }, { type: extract-clauses, tool: extractClausesTool }, { type: check-risks, tool: checkRisksTool } ], // 生产环境务必配置持久化此处用内存存储仅作演示 persistence: { store: memory }, retry: { maxAttempts: 2, backoff: linear, delayMs: 1000 } }); // 创建 Express 适配器 const adapter createExpressAdapter(contractReviewAgent); // 初始化 Express 应用 const app express(); app.use(express.json()); app.use(/api/agents, adapter.router); // 所有 Agent API 挂载在此路径 const PORT process.env.PORT || 3000; app.listen(PORT, () { console.log(Paperclip Agent server running on http://localhost:${PORT}); });启动服务# 在项目根目录 npx ts-node src/server/agent.ts # 或者先编译再运行 npm run build node dist/server/agent.js此时访问http://localhost:3000/api/agents/contract-review/run发送 POST 请求{ input: { documentId: doc_abc123 } }你会看到一个结构化的流式响应包含stepId、statusrunning/completed/failed、output和timestamp。这就是 Paperclip 的核心价值你不用写任何路由、中间件、状态管理一行adapter.router就暴露了完整的 Agent API。3.3 前端集成用useAgentHook 构建响应式 UI在 React 侧我们创建一个ContractReviewPage.tsx。关键点在于useAgent的调用方式和数据消费模式// src/pages/ContractReviewPage.tsx import { useAgent } from paperclip/react-client; import { useState } from react; export default function ContractReviewPage() { const [documentId, setDocumentId] useState(); const [isRunning, setIsRunning] useState(false); // 调用 useAgent传入 Agent ID 和初始输入 const { data, status, error, run, cancel } useAgent( contract-review, { input: { documentId } }, { // 配置选项 autoRun: false, // 手动触发非自动 streaming: true // 启用流式更新 } ); // 触发 Agent 执行 const handleSubmit (e: React.FormEvent) { e.preventDefault(); if (!documentId.trim()) return; setIsRunning(true); run(); // 手动启动 }; // 取消执行 const handleCancel () { cancel(); setIsRunning(false); }; // 根据 status 渲染不同状态 if (status idle) { return ( div classNamemax-w-2xl mx-auto p-6 h1 classNametext-2xl font-bold mb-4智能合同审核/h1 form onSubmit{handleSubmit} classNamespace-y-4 div label classNameblock text-sm font-medium mb-1文档ID/label input typetext value{documentId} onChange{(e) setDocumentId(e.target.value)} classNamew-full p-2 border rounded placeholder例如doc_abc123 / /div button typesubmit disabled{isRunning} classNamepx-4 py-2 bg-blue-600 text-white rounded disabled:opacity-50 {isRunning ? 审核中... : 开始审核} /button /form /div ); } // 渲染执行中的状态 if (status running) { return ( div classNamemax-w-2xl mx-auto p-6 h1 classNametext-2xl font-bold mb-4审核进行中/h1 div classNamespace-y-6 {/* 步骤1PDF解析 */} div classNamep-4 border-l-4 border-blue-500 h3 classNamefont-medium 解析PDF文档/h3 p classNametext-sm text-gray-600 {data?.steps?.[parse-pdf]?.status completed ? 已完成 : 正在进行中...} /p {data?.steps?.[parse-pdf]?.output?.pageCount ( p classNamemt-1 text-sm 共 {data.steps[parse-pdf].output.pageCount} 页 /p )} /div {/* 步骤2条款提取 */} div classNamep-4 border-l-4 border-green-500 h3 classNamefont-medium 提取关键条款/h3 p classNametext-sm text-gray-600 {data?.steps?.[extract-clauses]?.status completed ? 已完成 : data?.steps?.[parse-pdf]?.status completed ? 等待中... : 尚未开始} /p {data?.steps?.[extract-clauses]?.output?.clauses?.length 0 ( ul classNamemt-1 text-sm list-disc pl-5 space-y-1 {data.steps[extract-clauses].output.clauses.map((c: any) ( li key{c.id}{c.title}/li ))} /ul )} /div {/* 步骤3风险检查 */} div classNamep-4 border-l-4 border-yellow-500 h3 classNamefont-medium⚠️ 检查法律风险/h3 p classNametext-sm text-gray-600 {data?.steps?.[check-risks]?.status completed ? 已完成 : data?.steps?.[extract-clauses]?.status completed ? 等待中... : 尚未开始} /p {data?.steps?.[check-risks]?.output?.risks?.length 0 ( div classNamemt-1 text-sm space-y-1 {data.steps[check-risks].output.risks.map((r: any) ( div key{r.clauseId} classNameflex items-start span classNametext-red-500 mr-2●/span span{r.description}/span /div ))} /div )} /div /div button onClick{handleCancel} classNamemt-4 px-4 py-2 bg-red-600 text-white rounded 取消审核 /button /div ); } // 渲染完成或错误状态 if (status completed) { return ( div classNamemax-w-2xl mx-auto p-6 h1 classNametext-2xl font-bold mb-4审核完成/h1 div classNamebg-green-50 p-4 rounded h2 classNamefont-bold text-green-800✅ 审核成功/h2 p classNamemt-2 共发现 {data?.steps?.[check-risks]?.output?.risks?.length || 0} 项高风险条款 /p /div button onClick{() window.location.reload()} classNamemt-4 px-4 py-2 bg-blue-600 text-white rounded 新建审核 /button /div ); } if (error) { return ( div classNamemax-w-2xl mx-auto p-6 h1 classNametext-2xl font-bold mb-4审核失败/h1 div classNamebg-red-50 p-4 rounded h2 classNamefont-bold text-red-800❌ 执行错误/h2 p classNamemt-2 text-red-700{error.message}/p pre classNamemt-2 text-sm bg-gray-800 text-green-400 p-3 rounded overflow-x-auto {JSON.stringify(error, null, 2)} /pre /div button onClick{() window.location.reload()} classNamemt-4 px-4 py-2 bg-blue-600 text-white rounded 重试 /button /div ); } return null; }实操心得新手最容易犯的错误是直接console.log(data)并期望看到完整对象。Paperclip 的data是一个 Proxy 对象它按需加载各步骤数据。你应该始终通过data.steps[stepId]访问特定步骤而不是data.output。另外status的值只有idle、running、completed、failed四种没有loading——这是 Paperclip 故意为之因为它把 loading 状态交给了 SuspenseuseAgent只负责反映 Agent 的执行阶段。3.4 生产环境加固Redis 持久化与错误监控内存存储store: memory只适用于开发。生产环境必须配置持久化否则 Agent 重启后所有执行状态丢失。Paperclip 官方推荐 Redis因其高性能和原子性操作。配置方式如下// src/server/agent.ts import { createClient } from redis; import { createAgent, createExpressAdapter } from paperclip/core; // 创建 Redis 客户端 const redisClient createClient({ url: redis://localhost:6379 }); await redisClient.connect(); // 创建 Agent指定 Redis 存储 const contractReviewAgent createAgent({ id: contract-review, steps: [/* ... */], persistence: { store: redis, client: redisClient, // 可选设置 TTL避免状态无限堆积 ttl: 60 * 60 * 24 // 24小时 }, retry: { /* ... */ } });错误监控是 Paperclip 的另一大亮点。它内置了onError钩子可捕获任意步骤的异常contractReviewAgent.onError((error, context) { console.error( [Paperclip Error] Agent ${context.agentId} step ${context.stepType} failed, error ); // 这里可集成 Sentry、Datadog 或发送告警邮件 // 注意context 包含完整执行上下文包括 input、output、stepId });我在线上环境还加了一层防御对每个工具调用做try/catch并将原始错误包装为PaperclipError以便前端精准识别// src/server/tools.ts import { PaperclipError } from paperclip/core; export const checkRisksTool: Tool async ({ input }) { try { // 实际调用法律知识库 API const response await fetch(https://api.legal-kb.com/check, { method: POST, body: JSON.stringify(input) }); if (!response.ok) { throw new PaperclipError( Legal KB API returned ${response.status}, LEGAL_KB_UNAVAILABLE ); } return await response.json(); } catch (err) { // Paperclip 会自动将此错误传递给 onError 钩子 throw err; } };这样前端useAgent的error对象就会包含code: LEGAL_KB_UNAVAILABLE你可以据此展示更友好的提示“法律知识库暂时不可用请稍后再试”。4. 常见问题与实战排查技巧4.1 Node.js 安装与版本冲突为什么node -v显示正确但 Paperclip 仍报错这是最常被问及的问题。现象是node -v输出v20.10.0但运行npx ts-node src/server/agent.ts时Paperclip 报错Unsupported Node.js version: v18.16.0。原因几乎总是nvm 的默认版本未生效或IDE 终端未继承 nvm 环境。排查步骤在项目根目录执行which nodewhich node # 如果输出 /usr/local/bin/node说明你没用 nvm # 如果输出 ~/.nvm/versions/node/v20.10.0/bin/node则正常检查终端是否加载了 nvm# 在终端输入 nvm --version # 如果报 command not found说明 nvm 未加载 # 解决方案将 nvm 初始化脚本加入 shell 配置文件 echo export NVM_DIR$HOME/.nvm ~/.zshrc echo [ -s $NVM_DIR/nvm.sh ] \. $NVM_DIR/nvm.sh ~/.zshrc source ~/.zshrcVS Code 用户特别注意VS Code 的集成终端默认不加载.zshrc。打开 VS Code 后先运行CommandShiftP→Shell Command: Install code command in PATH然后重启终端。或者在 VS Code 设置中搜索terminal integrated env添加terminal.integrated.env.osx: { NVM_DIR: $HOME/.nvm }独家技巧Paperclip 的源码里有一个隐藏的诊断命令。在项目根目录运行npx paperclip/core diagnose它会自动检测 Node.js 版本、npm 版本、可用内存和 Redis 连接状态并生成一份 HTML 报告。这是我给客户做上线前检查的标准动作。4.2 React 页面白屏useAgent导致 Suspense fallback 无限循环现象页面加载后一直显示fallbackNetwork 面板看到/api/agents/contract-review/run请求不断发起控制台无报错。这是典型的Suspense 配置错误。根本原因Paperclip 的useAgent依赖 React 的cache和fetch机制。如果fetch被拦截如某些代理工具、浏览器插件或cache策略不当会导致 Suspense 无法 resolve Promise。解决方案分三步确认fetch未被覆盖// 在组件顶部添加调试 console.log(Global fetch:, window.fetch); console.log(Paperclip fetch:, typeof fetch); // 应为 function如果window.fetch是undefined或被重写禁用相关插件。强制使用原生 fetch// 在 useAgent 调用前 const originalFetch window.fetch.bind(window); // 然后在 useAgent 配置中指定 const { data } useAgent(contract-review, { input: { id } }, { fetch: originalFetch // 显式传入 });调整 Suspense 边界不要把整个页面包裹在 Suspense 中而是只包裹 Agent 相关区域// ❌ 错误全局 Suspense Suspense fallback{GlobalLoader /} ContractReviewPage / /Suspense // ✅ 正确局部 Suspense function ContractReviewPage() { return ( div Header / main Suspense fallback{StepLoader stepparse-pdf /} AgentExecutionArea / /Suspense /main /div ); }4.3 流式输出卡顿WebSocket 轮询 vs SSE 的选择陷阱Paperclip 默认使用 SSEServer-Sent Events传输流式数据但很多开发者误以为要配 WebSocket。实际上SSE 是 Paperclip 的唯一官方支持协议WebSocket 需要额外开发适配器。卡顿原因通常有两个Nginx/Apache 代理超时SSE 连接是长连接但默认反向代理超时是 60 秒。Paperclip 的 Agent 可能执行超过 60 秒如大 PDF 解析导致连接被代理中断。解决方案Nginx 示例location /api/agents/ { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; # 关键延长超时 proxy_read_timeout 300; # 5分钟 proxy_send_timeout 300; }浏览器并发连接限制Chrome 对同一域名的 SSE 连接数限制为 6 个。如果你在页面上同时启动多个useAgent第 7 个会排队。解决方案用AbortController主动取消不再需要的 AgentuseEffect(() { return () { if (cancel) cancel(); // 组件卸载时取消 }; }, [cancel]);4.4 工具调用失败如何调试tool函数里的异步错误Paperclip 的tool函数内错误不会直接抛到顶层而是被捕获并传给onError。但开发者往往想在开发时立刻看到错误堆栈。最佳实践是在tool内部加日志 console.trace()export const extractClausesTool: Tool async ({ input }) { console.time(extractClausesTool); try { console.log(Input to extractClausesTool:, input); const result await heavyComputation(input); console.timeEnd(extractClausesTool); return result; } catch (err) { console.error(extractClausesTool FAILED, err); console.trace(); // 打印完整调用栈 throw err; } };更进一步Paperclip 支持debug模式。在createAgent配置中加入const contractReviewAgent createAgent({ // ... debug: { logSteps: true, // 每个步骤开始/结束都打印 logInputs: true, // 打印每个步骤的 input logOutputs: true // 打印每个步骤的 output } });这会在控制台输出类似[PAPERCLIP DEBUG] Step parse-pdf STARTED with input { documentId: doc_123 } [PAPERCLIP DEBUG] Step parse-pdf COMPLETED with output { textContent: ..., pageCount: 12 } [PAPERCLIP DEBUG] Step extract-clauses STARTED with input { textContent: ..., pageCount: 12 }注意debug模式仅在NODE_ENVdevelopment下生效生产环境自动关闭不影响性能。4.5 性能瓶颈定位当 Agent 执行缓慢
上一篇/下一篇内容由系统自动关联
返回资讯列表 →