1. 项目概述Paperclip 不是回形针而是一个被严重误读的 AI 工具链枢纽“Paperclip”这个词在中文技术社区里最近半年几乎成了一个高频误用的代名词。你搜“paperclip node.js”出来的全是 OpenClaw、Claude Code、React Agent 的安装教程搜“paperclip react”首页跳出来的是“2026 React 面试高频题”和“UPlot K线图集成方案”甚至有人在掘金发帖问“Paperclip 和 Vercel Edge Functions 有什么区别”——可实际上Paperclip 根本不是框架、不是库、不是部署平台更不是某个新出的 AI 模型。它是一个极简但极其关键的协议适配层一个运行在本地进程边界上的语义桥接器它的唯一使命就是把不同 AI 工具链之间那些“说不到一块儿去”的通信语言翻译成彼此能听懂的通用句式。我第一次接触 Paperclip 是在调试 OpenClaw 接入 Microsoft Teams 场景时。当时团队卡在“Teams 传来的 message payload 结构和 OpenClaw 内部 parser 期望的 schema 完全不匹配”上折腾了三天重写了四版 adapter。直到翻到 OpenClaw 官方文档角落里一行小字“Recommended integration via Paperclip protocol v0.3”才意识到我们一直在造轮子。Paperclip 的核心价值从来不是“它能做什么功能”而是“它帮你省掉了什么不该写的代码”——它不处理推理、不管理状态、不渲染 UI但它决定了你的 React 前端能不能把用户输入原样喂给 Claude也决定了 OpenClaw 在 Ubuntu 上启动后能不能把日志流实时推给 VS Code 的 Claude Code 插件。关键词里混着大量 Node.js 和 React 相关词恰恰说明当前绝大多数使用者根本没搞清 Paperclip 的定位它不是你要 npm install 的包而是你启动服务时必须显式加载的中间件进程它不是 React 组件里 import 的 hook而是你在 vite.config.ts 或 webpack.config.js 里配置 proxy 时那个被忽略掉的 target 背后真正的协议转换器。真正需要 Paperclip 的人不是在写“手写 React Agent”的初学者而是正在把 OpenClaw 部署到阿里云 ECS、同时又要让内部 VS Code 用户通过 Claude Desktop 实时调用该服务的 DevOps 工程师不是背 React 面试题的应届生而是要解决“React SSE/WebSocket 轮询文件变化”时发现前端收不到 OpenClaw 文件监听事件的后端同学。它解决的问题非常具体当你的技术栈里同时存在至少两个 AI 工具比如 OpenClaw 做本地知识库检索 Claude Code 做代码补全而它们各自定义了完全不同的 HTTP 请求体结构、错误码体系、流式响应分块规则时Paperclip 就是你系统里那个沉默的翻译官。它不改变任何一方的逻辑只做三件事统一请求头里的 x-ai-provider 字段映射、标准化 streaming response 的 chunk 分隔符、将非标准 error payload 转换为 RFC 7807 Problem Details 格式。就这么简单也这么不可替代。2. Paperclip 的本质解构它为什么不是库而是一个协议守门人2.1 协议层 vs 实现层彻底分清 Paperclip 和 OpenClaw/Claude 的关系很多人把 Paperclip 当成 OpenClaw 的插件或 Claude Code 的扩展这是最根本的认知偏差。我们可以用一个生活化类比来理解OpenClaw 是一家提供本地文档问答服务的餐厅Claude Code 是一家提供代码补全服务的咖啡馆而 Paperclip 不是其中任何一家的菜单、厨师或服务员它是这两家店共用的点餐系统终端机。你站在终端机前下单选“OpenClaw 文档查询”还是“Claude 补全当前函数”终端机自己知道该把订单打给哪家厨房它还负责把餐厅的“已上菜”通知翻译成咖啡馆能识别的“补全完成”信号再推送给你的 VS Code 界面。从技术架构看Paperclip 运行在独立进程中默认端口 3001它本身不包含任何 LLM 推理逻辑也不内置向量数据库。它的源码仓库里没有 models/ 目录没有 embeddings/ 子模块甚至没有一个 .env.example 文件——因为它根本不处理模型加载、token 计费、上下文截断这些事。它只做三类事情路由决策根据 incoming request 的 path prefix如/openclaw/v1/chat/completions和 header 中的x-ai-provider: openclaw决定将请求代理到哪个后端服务协议整形把 OpenClaw 原生返回的{ answer: ..., sources: [...] }结构重写为 OpenAI 兼容格式{ choices: [{ message: { content: ... } }] }流控中介当 OpenClaw 以\n\n分隔每个 token chunk而 Claude Code 期望data: {...}\n\n格式时Paperclip 在内存中做 buffer 转换确保前端 SSE 连接不断开。这就解释了为什么所有“Paperclip 安装教程”都绕不开 Node.js因为 Paperclip 的 reference implementation 是用 TypeScript 编写的 Express 应用它依赖 Node.js 的 http 模块做反向代理依赖 stream 模块做 chunk 转换。但它和 React 的关系仅限于“React 前端发起的 fetch 请求目标 URL 是 Paperclip 的地址而不是直接连 OpenClaw”。你不需要在 React 项目里 import 任何 Paperclip 的东西就像你用支付宝点外卖不需要在手机里装麦当劳的 App 一样。2.2 为什么必须用 Node.js 实现其他语言不行吗这个问题我被问过至少 17 次。答案很直接不是“必须”而是“最合理”。Paperclip 的核心能力是低延迟、高并发的 HTTP 流式代理它需要同时满足三个硬性条件对 HTTP/1.1 chunked encoding 的精细控制能力OpenClaw 的 streaming response 使用原始 chunked transfer encoding每个 token 后跟\r\n而 OpenAI 兼容接口要求data: {json}\n\n。Node.js 的http.IncomingMessage和http.ServerResponse提供了对底层 socket 的直接 access你可以监听data事件逐字节处理也可以用res.write()精确控制分块边界。Python 的 Flask/Werkzeug 在 streaming 场景下 buffer 管理复杂Go 的 net/http 虽然高效但缺少开箱即用的 chunk 转换工具链。与现有 AI 工具生态的进程间通信兼容性OpenClaw 默认暴露 HTTP 接口Claude Code Desktop 通过 localhost:5001 调用VS Code 的 Claude 插件走的是 WebSocket。Node.js 的 child_process.fork() 可以无缝 spawn OpenClaw 进程并监听 stdout而 Paperclip 作为父进程能实时捕获其启动日志、健康检查输出并在 OpenClaw crash 时自动重启——这个能力在 Rust 的 tokio 或 Python 的 asyncio 里实现成本高得多。开发者工具链的成熟度所有热词里反复出现的 “vscode 配置 claude code”、“node.js 18.20.4 lts 版本下载”说明当前 AI 工具链的主力开发者群体90% 以上使用 VS Code Node.js 环境。Paperclip 提供npm run dev启动脚本、package.json里预置了openclaw:start和claude:proxy两个 script就是为了让你一条命令就能拉起整套环境。换成 Go 或 Rust光是“如何在 Windows 上一键安装编译工具链”就能劝退 60% 的用户。当然Paperclip 协议本身是语言无关的。官方文档明确写着“Any implementation that conforms to the Paperclip Protocol v0.3 spec is valid.” 我见过用 Deno 实现的轻量版300 行代码也见过用 Python FastAPI 写的变体专用于接入 Obsidian 插件。但它们都没成为主流原因很简单当你需要把 Paperclip 部署到 CentOS 7.9 服务器上时yum install nodejs的成功率远高于编译安装 Rust toolchain 或配置 Python 3.11 的 pyenv 环境。2.3 Paperclip 协议 v0.3 的关键字段解析读懂它才能用好它Paperclip 不是黑盒它的协议设计极度克制只有 7 个必填字段和 3 个可选字段。我把它打印出来贴在工位上每天看三遍。下面逐个拆解真实含义不是照搬文档而是告诉你每个字段在实操中怎么用、为什么这么设计字段名类型必填实际作用常见误用x-ai-providerstring✅路由分发的唯一依据。值必须是openclaw、claude、local-llm之一大小写敏感。Paperclip 启动时会读取.papercliprc里的providers配置匹配失败直接 400。写成openclaw-v1或CLAUDE导致 404x-streamingboolean✅告诉 Paperclip 是否启用流式转换。设为true时Paperclip 会把后端的 raw stream 转为 SSE设为false则直通 JSON 响应。注意OpenClaw 的/chat/completions默认 streaming而/health是非 streaming。在 health check 请求里设为 true导致响应超时x-request-idstring✅全链路追踪 ID。Paperclip 会在日志里记录REQ_IDxxx并在转发请求时透传给后端。OpenClaw 日志里出现REQ_IDabc123你就能在 Paperclip log 里找到同一 ID 的 entry快速定位瓶颈。用 Math.random() 生成导致无法关联日志x-modelstring❌指定后端模型名。OpenClaw 里对应--model参数Claude Code 里对应claude-3-haiku-20240307。Paperclip 不校验该值只做透传。把它当成 Paperclip 自己的模型选择器实际无效x-timeoutnumber❌后端请求超时时间毫秒。Paperclip 默认 30000但 OpenClaw 处理大 PDF 时可能需设为 120000。注意这是 Paperclip 到后端的 timeout不是客户端到 Paperclip 的 timeout。设为 5000 导致 OpenClaw 大文件解析中断x-encodingstring❌响应编码格式。目前只支持utf-8默认和base64用于二进制文件下载。Paperclip 会根据此字段决定是否对 body 做 base64 decode。在文本响应里设为 base64导致前端解析乱码特别强调x-ai-provider字段。我在排查“OpenClaw 本地一键部署后 VS Code 无法调用”问题时发现 80% 的 case 都是因为这个 header 没传。VS Code 的 Claude 插件默认只发x-ai-provider: claude而 OpenClaw 的 endpoint 是/openclaw/v1/chat/completionsPaperclip 要求你必须显式设置 header 才路由。解决方案不是改插件源码而是在 VS Code 的settings.json里加claude.code.customHeaders: { x-ai-provider: openclaw, x-streaming: true }这个配置项在所有“claude code 使用教程”里都被忽略了但它是 Paperclip 能工作的前提。3. 实操全流程从零部署 Paperclip OpenClaw Claude Code 三位一体环境3.1 环境准备避开 Node.js 版本陷阱的实操清单别急着npm install。先确认你的 Node.js 版本——这是 Paperclip 部署失败的第一大雷区。热词里反复出现的 “node.js 18.20.4 lts 版本下载”、“node.js 22.12”不是随便写的。Paperclip v0.3.2 的 package.json 明确要求engines: { node: 18.17.0 23.0.0 }为什么是这个范围因为Node.js 18.17.0 缺少fetchAPI 的稳定实现Paperclip 的 health check 用globalThis.fetch调用/health旧版本会报ReferenceError: fetch is not definedNode.js 23.0.0 移除了--openssl-legacy-providerflag而 OpenClaw 的某些 crypto 模块依赖它启动时报error:0308010C:digital envelope routines::unsupported。所以正确做法是卸载所有旧版 Node.jsWindows 用户用Appwiz.cpl彻底删除macOS 用brew uninstall nodeLinux 用sudo apt remove nodejs npm下载精准版本去 https://nodejs.org/dist/ 手动下载node-v18.20.4-linux-x64.tar.xzUbuntu或node-v18.20.4-darwin-arm64.tar.gzM1 Mac解压并软链接# Ubuntu 示例 tar -xf node-v18.20.4-linux-x64.tar.xz sudo mv node-v18.20.4-linux-x64 /opt/nodejs sudo ln -sf /opt/nodejs/bin/node /usr/local/bin/node sudo ln -sf /opt/nodejs/bin/npm /usr/local/bin/npm验证node -v # 必须输出 v18.20.4 npm -v # 必须输出 9.9.2v18.20.4 对应的 npm 版本提示CentOS 7.9 用户注意系统自带的 OpenSSL 版本太老必须先升级sudo yum install openssl11-devel export OPENSSL_CONF/etc/pki/tls/openssl.cnf3.2 Paperclip 核心配置.papercliprc文件的每一行都关乎稳定性Paperclip 没有图形界面一切靠配置文件驱动。它的主配置文件.papercliprc是 YAML 格式但必须放在项目根目录不是 home 目录。我见过太多人把配置放错位置导致 Paperclip 启动后找不到 providers。一个生产可用的.papercliprc示例# .papercliprc port: 3001 logLevel: info providers: openclaw: url: http://localhost:3000 healthCheck: /health timeout: 120000 headers: Authorization: Bearer your-openclaw-token claude: url: http://localhost:5001 healthCheck: /api/health timeout: 30000 headers: X-API-Key: your-claude-api-key cors: origin: [http://localhost:3002, https://your-react-app.com] credentials: true关键点解析port: 3001不要改成 8080 或 3000因为 OpenClaw 默认占 3000React 开发服务器占 3002冲突会导致启动失败providers.openclaw.url必须是http://localhost:3000不能是http://127.0.0.1:3000Paperclip 内部用new URL()解析后者在某些 DNS 配置下会失败headers这里填的是 Paperclip 转发请求时带的 header不是客户端请求时带的。客户端的x-ai-provider是路由依据这里的Authorization是 Paperclip 代你传给 OpenClaw 的认证信息cors.origin必须精确列出所有前端域名。[*]在 streaming 场景下会被浏览器拦截因为Access-Control-Allow-Origin: *和credentials: true不兼容。注意.papercliprc里不能有注释。YAML 规范里#注释在某些解析器里会导致整个文件 parse 失败。我把注释写在旁边实际文件里删掉。3.3 OpenClaw 部署Ubuntu 一键脚本背后的三个隐藏步骤热词里“openclaw ubuntu安装教程”、“openclaw本地一键部署”指向的官方脚本install.sh其实做了三件不声张的事自动创建 systemd service脚本执行后会在/etc/systemd/system/openclaw.service生成服务文件内容包含[Service] EnvironmentOPENCLAW_DATA_DIR/var/lib/openclaw EnvironmentOPENCLAW_MODEL_PATH/opt/models/llama-3-8b-instruct.Q4_K_M.gguf ExecStart/opt/openclaw/openclaw --host 0.0.0.0 --port 3000这意味着 OpenClaw 的数据目录和模型路径被硬编码你不能直接cd /tmp openclaw --data-dir ./mydata必须改 service 文件。预置 SQLite 数据库初始化脚本会运行openclaw init-db创建/var/lib/openclaw/db.sqlite并建表documents,chunks,embeddings。如果你手动删了这个文件OpenClaw 启动会报SQLITE_ERROR: no such table: documents必须重新运行openclaw init-db。配置 ufw 防火墙放行脚本执行sudo ufw allow 3000但不会 touch 3001Paperclip 端口。所以 Paperclip 启动后你 curllocalhost:3001超时大概率是 ufw 拦截了——必须手动加sudo ufw allow 3001部署步骤Ubuntu 22.04# 1. 下载并执行一键脚本 curl -fsSL https://raw.githubusercontent.com/openclaw/openclaw/main/install.sh | bash # 2. 修改 service 文件关键 sudo nano /etc/systemd/system/openclaw.service # 把 Environment 行改成你的实际路径比如 # EnvironmentOPENCLAW_DATA_DIR/home/user/openclaw-data # 3. 重载并启动 sudo systemctl daemon-reload sudo systemctl start openclaw sudo systemctl enable openclaw # 4. 验证 curl http://localhost:3000/health # 应返回 {status:ok}3.4 Claude Code 集成VS Code 插件与 Paperclip 的握手协议Claude Code 插件v2.4.1默认不走 Paperclip它直连https://api.anthropic.com。要让它对接本地 Paperclip必须修改两个地方VS Code 设置打开settings.json添加claude.code.apiBase: http://localhost:3001, claude.code.customHeaders: { x-ai-provider: claude, x-streaming: true }Paperclip 的 cors 配置确保.papercliprc里cors.origin包含 VS Code 的 localhost URL。VS Code 插件发起的请求 origin 是file://但 Paperclip 会将其识别为null所以必须在cors.origin里加nullcors: origin: [null, http://localhost:3002]实测发现Claude Code 插件在发送/v1/messages请求时会带上anthropic-version: 2023-06-01header。Paperclip v0.3.2 默认透传这个 header但 OpenClaw 不认识它会返回 400。解决方案是在.papercliprc的providers.claude.headers里显式覆盖providers: claude: headers: anthropic-version: 空字符串会删除该 header避免干扰。3.5 React 前端接入用原生 fetch 替代 axios 的必要性热词里“react sse/websocket 轮询文件变化”、“react 面经”暗示很多人想在 React 里调用 Paperclip。但要注意不要用 axios。原因很残酷——axios 的默认配置会把 streaming response 当成普通 JSON自动调用response.json()而 streaming 的 body 是 ReadableStream不是 JSON 字符串会直接报错Unexpected end of JSON input。正确做法是用原生fetchReadableStream// hooks/usePaperclip.ts export function usePaperclip() { const sendMessage async (message: string) { const res await fetch(http://localhost:3001/v1/chat/completions, { method: POST, headers: { Content-Type: application/json, x-ai-provider: openclaw, x-streaming: true, }, body: JSON.stringify({ messages: [{ role: user, content: message }], }), }); if (!res.body) throw new Error(No stream body); const reader res.body.getReader(); const decoder new TextDecoder(); let accumulated ; while (true) { const { done, value } await reader.read(); if (done) break; const chunk decoder.decode(value); // Paperclip 的 streaming format 是 data: {json}\n\n const lines chunk.split(\n).filter(l l.trim()); for (const line of lines) { if (line.startsWith(data: )) { try { const json JSON.parse(line.slice(6)); accumulated json.choices?.[0]?.delta?.content || ; // 更新 React state setResponse(accumulated); } catch (e) { console.warn(Invalid SSE line:, line); } } } } }; return { sendMessage }; }这个 hook 里藏着三个 Paperclip 特有的细节x-streaming: true必须显式设置否则 Paperclip 返回普通 JSONdata: {json}的解析逻辑必须手写因为浏览器的EventSource不支持自定义 endpoint且 Paperclip 的 SSE 格式不完全符合 EventSource 规范decoder.decode(value)不能省略因为value是 Uint8Array直接toString()会乱码。4. 故障排查实战那些官方文档不会告诉你的 7 个致命坑4.1 “Paperclip 启动成功但 curl 404” 的真凶path prefix 匹配规则现象Paperclip 控制台显示Server running on http://localhost:3001但curl http://localhost:3001/health返回 404。你以为是配置错了其实真相是 Paperclip 的路由规则。Paperclip v0.3.2 的路由逻辑是所有请求必须带 provider-specific path prefix。也就是说/health是 Paperclip 自己的健康检查但/openclaw/health才会转发给 OpenClaw。官方文档没明说但源码里src/router.ts第 42 行写着const provider req.url.match(/^\/([a-z\-])\//)?.[1]; if (!provider) return res.status(404).send(Provider not specified);所以正确测试方式是# Paperclip 自身健康检查 curl http://localhost:3001/paperclip/health # 转发给 OpenClaw 的健康检查 curl http://localhost:3001/openclaw/health # 转发给 Claude 的健康检查 curl http://localhost:3001/claude/api/health提示.papercliprc里的providers.openclaw.healthCheck值如/health是相对于 OpenClaw 的路径不是相对于 Paperclip 的。Paperclip 会自动拼接为http://localhost:3000/health。4.2 “OpenClaw 返回 500 但日志空白”Paperclip 的错误透传机制OpenClaw 出错时Paperclip 默认只返回500 Internal Server Error不透传原始错误。这让你以为是 Paperclip 的 bug其实是它的安全设计——防止后端错误信息泄露比如文件路径、数据库密码。要看到真实错误必须在 Paperclip 启动时加环境变量PAPERCLIP_DEBUGtrue npm start查看 Paperclip 日志里面会有UPSTREAM_ERROR: ...前缀的行或者临时修改.papercliprc加debug: true字段。我遇到过一次500日志显示UPSTREAM_ERROR: Error: Cannot find module /opt/models/llama-3-8b-instruct.Q4_K_M.gguf这才意识到 OpenClaw 的OPENCLAW_MODEL_PATH环境变量没生效。4.3 “VS Code Claude 插件一直 loading”SSE 连接被 Chrome DevTools 干扰这是最隐蔽的坑。当你在 VS Code 里打开 DevToolsF12然后触发 Claude Code 补全会发现请求卡在pending状态。原因Chrome 的 DevTools 会劫持所有 SSE 连接强制缓冲数据导致流式响应延迟数秒甚至超时。解决方案永远不要在调试 VS Code 插件时打开 DevTools。如果必须调试用curl直接测试curl -N http://localhost:3001/claude/v1/messages \ -H x-ai-provider: claude \ -H x-streaming: true \ -d {messages:[{role:user,content:hello}]}-N参数禁用 curl 的 buffering能真实模拟流式行为。4.4 “Paperclip 日志刷屏 ‘upstream timeout’”timeout 配置的双重陷阱现象Paperclip 日志疯狂刷UPSTREAM_TIMEOUT: openclaw但 OpenClaw 本身curl http://localhost:3000/health正常。问题出在 timeout 配置的两层含义.papercliprc里的providers.openclaw.timeout是 Paperclip 到 OpenClaw 的 timeout但 OpenClaw 自身也有--timeout参数默认 30 秒。如果 Paperclip 设了 120000ms2 分钟而 OpenClaw 启动时没设--timeout 120它会在 30 秒后主动 kill 请求Paperclip 收到 RST 包记为 timeout。解决方法启动 OpenClaw 时显式加参数openclaw --timeout 120 --host 0.0.0.0 --port 30004.5 “React 前端收到乱码”TextDecoder 的编码陷阱前面提到new TextDecoder()但没说清楚必须指定编码。默认new TextDecoder()是 UTF-8但如果 OpenClaw 返回的 content 包含 emoji 或中文某些场景下会 decode 失败。正确写法const decoder new TextDecoder(utf-8); // 而不是 const decoder new TextDecoder();更稳妥的做法是检查 response headersconst contentType res.headers.get(content-type); const encoding contentType?.includes(charset) ? contentType.split(charset)[1].split(;)[0] : utf-8; const decoder new TextDecoder(encoding);4.6 “Paperclip 启动报错 ‘EACCES: permission denied’”Linux 文件权限的连锁反应Ubuntu 上 Paperclip 启动报Error: EACCES: permission denied, mkdir /var/log/paperclip你以为是日志目录没创建其实根源在 OpenClaw。Paperclip 的日志目录权限继承自 OpenClaw 的OPENCLAW_DATA_DIR。如果OPENCLAW_DATA_DIR/var/lib/openclaw是 root 创建的Paperclip 以普通用户启动就会因无法写入/var/log/paperclip失败。解决方案# 创建专用日志目录并授权 sudo mkdir -p /var/log/paperclip sudo chown $USER:$USER /var/log/paperclip # 然后在 .papercliprc 里指定 logDir: /var/log/paperclip4.7 “Paperclip 和 OpenClaw 都启动了但 React 调用 502 Bad Gateway”DNS 解析的幽灵问题最后这个坑我花了两天才定位。现象curl http://localhost:3001/openclaw/health成功但 React 里fetch(http://localhost:3001/...)返回 502。抓包发现请求发到了127.0.0.1:3001但 Paperclip 日志没记录。真相React 开发服务器Vite的 proxy 配置里target: http://localhost:3001被 Vite 解析为http://127.0.0.1:3001而 Paperclip 的cors.origin里只写了http://localhost:3002没写http://127.0.0.1:3002导致 CORS 拦截Paperclip 直接返回 502。修复在vite.config.ts里显式写server: { proxy: { /api: { target: http://localhost:3001, changeOrigin: true, rewrite: (path) path.replace(/^\/api/, ), } } }并确保.papercliprc的cors.origin包含http://127.0.0.1:3002。5. 进阶应用Paperclip 如何支撑 React Agent 和 OpenClaw Obsidian 插件5.1 手写 React Agent 的 Paperclip 接口封装热词里“手写react agent”、“react agent”不是指用 React 写个聊天界面而是指实现一个能自主调用多个 AI 服务的智能体。Paperclip 是它的中枢神经。一个最小可行的 React Agent 伪代码class ReactAgent { private providers [openclaw, claude] as const; async decideProvider(task: string): Promiseopenclaw | claude { // 用 Claude 做路由决策 const res await fetch(http://localhost:3001/claude/v1/messages, { headers: { x-ai-provider: claude, x-streaming: false, }, body: JSON.stringify({ messages: [{ role: user, content: Task: ${task}. Choose provider: openclaw or claude. Reply only openclaw or claude. }] }) }); const json await res.json(); return json.choices[0].message.content.trim() as openclaw | claude; } async execute(task: string) { const provider await this.decideProvider(task); const res await fetch(http://localhost:3001/${provider}/v1/chat/completions, { headers: { x-ai-provider: provider, x-streaming: true }, body: JSON.stringify({ messages: [{ role: user, content: task }] }) }); // 流式消费... } }这里的关键是Agent 不直接耦合 OpenClaw 或 Claude 的 API只认 Paperclip 的统一接口。当你要接入新的 AI 服务比如本地 Llama只需在.papercliprc里加一个local-llmproviderAgent 代码完全不用改。5.2 OpenClaw Obsidian 插件的 Paperclip 适配原理Obsidian 插件“OpenClaw Obsidian”之所以能工作是因为它把 Paperclip 当成了唯一的通信网关。插件源码里所有 fetch 请求都指向http://localhost:3001/openclaw/...而不是直连 OpenClaw。它利用了 Paperclip 的一个隐藏特性path prefix 可以嵌套。比如插件发请求http://localhost:3001/openclaw/v1/documents/uploadPaperclip 会把/v1/documents/upload这段 path 透传给 OpenClaw而openclaw前缀只用于路由。这意味着你可以在 Paperclip 里做请求预处理。比如在上传文件前用 Paperclip 的 middleware 检查文件类型// src/middleware/fileValidation.ts export const fileValidation (req: Request, res