Coding Agent Harness 选型与接入:OpenCode、Pi、DeepSeek Harness 等六款对比

最近在看 OpenCode、Pi、DeepSeek Harness、Codex、Claude Agent SDK 和 OpenHands,顺带翻了翻 OpenClaw、Hermes Agent 这类助手项目。起因很实际,我要回答两个问题:它能不能作为一个进程部署?现有业务怎么调用它?

只看演示,这些工具长得都差不多:读文件、跑命令、改代码、调工具。接进系统以后差别才暴露出来——有没有 HTTP 接口,Session 能不能恢复,任务怎么取消,多个用户怎么隔离,出了问题能不能查清一次运行到底做了什么。

所以这篇不比“谁写代码更聪明”,只比两件事:怎么选,选完怎么接。

先交代版本和边界。判断基于 2026 年 9 月的官方资料,核对版本是 OpenCode v1.18.31、Pi v0.85.1、DeepSeek Harness v0.1.6-alpha.2、Codex v0.155.0、Claude Agent SDK Python v0.2.156 / TypeScript v0.3.276、OpenHands v1.20.0、OpenClaw v2026.9.4、Hermes Agent v2026.9.14。领域变化快,接口以你实际采用的版本为准。

丑话说在前面:这是文档调研,不是实测。全文没有性能、并发、成本数据;“建设量”是量级判断,不是人月承诺。个别小节我只看过文档没跑过代码,会在文里直接标出来。

先说结论

按常见的建设目标,我会这么选:

建设目标 优先看什么
已有 Go、Java、Python 服务,想尽快接一个独立 Agent Runtime OpenCode
想把 Agent 内核嵌进自己的 Node.js 产品 Pi
想验证插件化架构,或深度使用 DeepSeek 模型 DeepSeek Harness
已经确定使用 OpenAI 或 Claude Codex / Claude Agent SDK
需要完整仓库、容器、浏览器和远程开发环境 OpenHands
想给自己或团队部署一个现成的 AI 助手 OpenClaw / Hermes Agent

这不是能力排名。OpenCode 强在接入快,Pi 强在容易改,DeepSeek Harness 强在插件化架构,OpenHands 解决的是更重的执行环境。团队的问题不同,答案自然不同。

还有一条我很确定:能跑 Shell 不等于能当业务后端。 Demo 能工作,离生产还差会话、取消、隔离、权限、审计和任务恢复。

这些工具属于同一类吗

不完全是。

我把 Harness 理解成模型外面的执行环境:组织上下文,让模型挑工具,把工具结果送回模型,循环到任务结束。

1
2
3
4
5
6
7
8
9
10
Agent = Model + Harness

Harness =
Agent Loop
+ Context
+ Tool Runtime
+ Session
+ Permission
+ Workspace / Sandbox
+ Event Stream

按这个定义,常见项目分四类:

类型 代表工具 更像什么
成品 Harness / Agent SDK OpenCode、Pi、DeepSeek Harness、Codex、Claude Agent SDK 已提供 Agent Loop,可以直接运行或嵌入应用
Agent 开发框架 LangGraph、AutoGen、PydanticAI、Semantic Kernel 用来自己组装执行引擎的零件
一体化助手平台 OpenClaw、Hermes Agent 自带 Agent 内核(或嵌入别家 Harness)、聊天渠道和定时任务的助手产品
协议和基础设施 MCP、ACP、A2A、Sandbox 连接工具、Agent 或运行环境的标准

LangGraph 和 OpenCode 经常被放在一起比,其实不在一层。用 LangGraph,任务状态、节点、路由、持久化都得自己设计;用 OpenCode,Agent Loop、Session、工具现成摆在那里。

OpenCode:现成的 Agent Backend

我对 OpenCode 的终端界面兴趣不大,真正有用的是它把 Server、SDK、Session、事件和扩展这几块接到了一起。

官方提供 opencode serve,业务侧通过 HTTP 创建 Session、发消息,SSE 收事件。工具可以用 Bash、Custom Tool、Plugin,或者接 MCP Server;Agent、Subagent、Skill 的配置方式也都现成。

1
2
3
4
5
6
7
8
Business Service
│ HTTP / SSE
▼
OpenCode Server
├── Agent / Skill
├── Custom Tool
├── Bash
└── MCP Server

适合这样的团队:业务服务已经存在、不想为 Agent 改成 Node.js;希望 Runtime 独立部署;想先把任务、过程、结果跑通;模型还没定下来。

要留意它的边界。它解决的是“一次任务怎么执行”,多租户隔离、任务排队、跨实例存储、凭证管理、故障恢复都不在职责内。内部原型直接用没问题;要承载大量用户和并发任务,外面还得补调度、权限、存储和运行隔离。

Pi:可以嵌进产品的 Agent 内核

Pi 和 OpenCode 的手感不一样。OpenCode 像一个能对外提供服务的进程,Pi 像一组小而清晰的构件。实用的接法有两种:

  • 在 TypeScript/JavaScript 服务里用 SDK,直接创建和控制 Agent Session;
  • 以 RPC 模式跑长驻进程,stdin/stdout 上用 JSONL 发命令、收事件。

Session 这块有个小改动值得一提:v0.85.0 加了 SessionManager.inMemory(),能把外部系统存的会话条目恢复进来,自己做持久化省不少事。

还有个插曲很能说明 Pi 的现状:0.85.0 不小心把内部实验性的 client/server 代码发了出去,0.85.1 马上退回到仅源码可用。官方支持的接口就两个,本地 SDK 和 stdio RPC,原生 HTTP API 至今没有时间表。做架构时按“不会有现成远程接口”来规划,比等它补齐靠谱。

Extension 可以注册工具、命令和事件钩子,加上 Skill、Prompt Template、Package,做产品级组合比较顺手。想自己决定外部 API、UI、会话存储和任务状态、只复用 Agent Loop 的团队,Pi 是这几款里最合适的。

代价也直接,企业控制面一样不给:认证、租户、数据库、Worker 调度、配额、运维接口,全要自己做。Go 或 Java 服务走 JSONL RPC 能接,但子进程退出、背压、重启、协议版本这些都得自己处理。

一句话定位:自由度最高,建设量也最大。

DeepSeek Harness:插件化值得看,变化也要留空间

第一印象是 everything-is-a-plugin。官方定位就是插件化的 Agent Harness SDK,Session、工具、MCP、Sandbox、Plan、LLM 全是独立 package,按需替换组合。把“可替换”放在架构第一位,这点跟 OpenCode、Pi 都不一样。

仓库主体 TypeScript,MIT 协议,9 月下旬 star 约 23 万。它同时提供 TypeScript 和 Python 两套进程外 SDK,CLI、Web、Plugin、ACP 都能用;v0.1.6-alpha.1 加了 Headless 模式,stdin 接任务、--session-id 续会话、--json 逐行输出运行事件,形态跟 Pi 的 JSONL RPC 很接近。Python 项目确实能接,但别把它理解成“面向 Python 团队的 Harness”。模型默认偏 DeepSeek,Anthropic、OpenAI、Kimi、GLM 也都接了。Session 支持持久化和回放,排查问题、恢复会话时好用。

它就是个 Agent 运行时。训练、评测、微调都没有,别指望它提供模型迭代闭环。

风险写在明面上:官方标着 Developer Preview,明说会有破坏性变更。9 月 17 日的 v0.1.6-alpha.2 为了支持会话多实例共存,改掉了客户端 Session 的 API 和 slot;插件依赖换成运行时解析、支持运行时卸载,发布说明干脆让开发者自查加载和卸载逻辑。上生产前,除了文末那张通用清单,还得单独验三件事:Plugin 和 SDK 升级的兼容性、多模型 Provider 够不够用、事件日志怎么落库和脱敏。

我的建议是尽早试,但业务接口别直接依赖它当前的 SDK 类型。外面包一层 Adapter,升级或切回其他 Runtime 都从容得多。

Codex 和 Claude Agent SDK:定了平台就别折腾

公司已经定了模型平台的话,“模型中立”就不是必选项。为了抽象而抽象,成本是真的。

Codex 有非交互执行、SDK 和 App Server 三种用法,Thread、Turn、事件、审批、结构化输出、MCP、Sandbox 都能管;App Server 走 WebSocket 对外给 JSON-RPC,远程调用不用自己再包一层。Claude Agent SDK 把 Claude Code 的 Agent Loop、工具、Session、Hook 和权限开放给 Python、TypeScript 应用。只想远程调一个 Claude Agent 的话,看 Anthropic 另外的 Managed Agents,托管 REST API,跟 Agent SDK 不是一个产品。

版本节奏要有心理准备。Codex 稳定版 v0.155.0 是 9 月 17 日发的,第二天 0.156.0 的 alpha 就出来了;Claude Agent SDK 的 Python 包还在 0.2.x,TypeScript 在 0.3.x,基本天天发版。迭代快是好事,接口也跟着频繁变,升级回归的时间别省。

厂商 Runtime 的好处是模型和 Harness 配合完整,官方新能力出现后直接用得上。坏处是账号、模型、协议、运行时绑成一串。定了平台就用;想做多模型通用平台的,谨慎。

OpenHands:要的是一台远程开发机时再看

OpenHands 比上面几个都重:SDK、Agent Server、远程 Sandbox、Web UI,一套面向软件工程任务的完整执行环境。这块我看得最少,只翻了 SDK 和 Agent Server 的文档,没实测。

任务要拉仓库、装依赖、起服务、跑测试、开浏览器、跑很久,它的价值才显出来。只是读几项业务数据、生成一份结构化结果,这套平台太重了。

结论就一句:想清楚你要的是“一个循环”,还是“一台能远程用的开发机”。

顺带说说一体化助手

OpenClaw 和 Hermes Agent 是另一个物种(9 月下旬 star 约 39 万和 25 万):内核、聊天渠道、定时任务、会话管理全都建好,直接交付一个长驻助手。它们回答的是“怎么给自己或团队部署一个一直在线的助手”,跟本文“业务怎么程序化调用 Agent”不是一个问题。要在公司 IM 里放一个能干活的 Agent,部署它们改改配置更划算;想当多租户 Runtime 塞进业务系统,会话模型和安全假设都不支持。留一条旁证:OpenClaw 内核基于 Pi、接 Codex 用的 app-server 在 Codex 仓库里还标着 experimental——Pi 那条路走得通,集成的坑也有下游项目先替你踩了。

选型时我会重点看什么

先拆开三个常被混着说的能力,它们也是后面对比表的列口径。可独立运行:不必嵌进业务主进程就能跑完整 Agent Loop(不代表模型可以离线部署)。原生 HTTP API:官方直接提供远程可调的 HTTP、SSE 或 WebSocket,SDK、stdin/stdout、JSONL RPC 属于程序化接口,不等于远程服务。会话管理:任务能否继续、恢复、查询、回收,跟进程怎么启动、用什么协议调用无关。

拆开之后,我会这样验:

能不能独立运行。 部署方式先问清楚:能直接交给 Docker、Kubernetes、systemd 跑,还是必须嵌进某个宿主程序?这决定它怎么进你的发布流程。

有没有原生 HTTP API。 只能启动一次 CLI、等进程退出读 stdout 的话,取消、审批、进度展示、故障恢复都难做。有 HTTP API 也别急着放心:认证、会话、流式事件、取消和并发语义,逐个确认。

Session 归谁管。 别只看有没有 Session ID。要问:能不能创建、查询、继续、删除;历史在内存还是能持久化重放;进程或容器重启能不能恢复;多用户、多任务、多实例怎么隔离;超时、过期、归档谁负责。还要分清 Harness Session 和业务任务,前者解决上下文延续,后者承担业务状态、重试和审计,映射办法后面讲。

工具有没有契约。 几乎所有 Coding Agent 都能跑 Shell,我更关心能不能把工具描述成带 Schema 的接口:参数什么类型、允许什么值、返回稳不稳定、哪些调用要审批。靠 Prompt 让模型“按这个格式拼命令”能跑,跑不久。

任务能不能停。 用户取消后不能只把页面状态改成 cancelled。模型请求、Shell 子进程、浏览器任务、远程工具要一起结束,不然后台继续烧钱,甚至继续执行有副作用的操作。

隔离够不够。 工作目录不是安全边界。并发任务至少要考虑目录、进程、网络、凭证、缓存、Session 的隔离。涉及代码执行或不可信输入,看容器和 Sandbox。

结果能不能被程序用。 业务系统要 JSON,不要一段“看起来不错”的 Markdown。最好原生支持 JSON Schema 或结构化结果;其次用一个专门的 Tool 提交最终结果;最差才是从自由文本里解析。

放在一起比较

只比作为业务 Runtime 关心的部分,不比代码补全体验。

工具 可独立运行 原生 HTTP API 会话管理 其他程序化接口 远程接入判断
OpenCode 是,CLI / Server 进程 是,HTTP / SSE 内置 Session API,可创建、查询和继续会话 TypeScript SDK 可以直接作为独立 Runtime 接入
Pi 是,CLI / RPC 进程 否 提供 Agent Session,本地持久化和生命周期可由 SDK 控制,v0.85 起可恢复外部存储的会话 TypeScript SDK、stdin/stdout JSONL RPC 需要自行封装 HTTP 服务
DeepSeek Harness 是,CLI / Web 有限,Web Host API 默认面向本机 事件日志式 Session,支持持久化、回放和恢复 TypeScript/Python SDK、ACP、Headless(stdin / JSONL 事件) 需要验证接口稳定性和远程暴露方式
Codex 是,codex / codex exec 是,App Server 支持 WebSocket(HTTP + JSON-RPC) Thread / Turn,可保持、继续和管理对话生命周期 SDK、App Server 进程协议 可以作为进程运行,App Server 可远程调用
Claude Agent SDK 需要宿主程序 否 支持 Session ID 和恢复,持久化策略仍需结合宿主设计 Python/TypeScript SDK 需要自行建设 Agent 服务
OpenHands 是,Agent Server 是,Agent Server API Conversation 支持持久化、暂停和恢复 SDK 原生支持远程 Agent 服务

表里的会话管理只表示有没有会话标识、历史和恢复能力。数据存哪、多实例能不能共享、崩溃后怎么恢复、谁负责过期删除,都要单独确认。

工具扩展、模型、服务化路径和建设量放在一起看。相对建设量按“已有业务服务、先做内部工具”的口径估算,不是人月承诺;要做到多租户生产级,每一行都要显著上浮:

工具 工具扩展 模型选择 服务化路径 相对建设量 主要代价
OpenCode Custom Tool、Plugin、MCP 多 Provider 可配置,不绑定单一模型 自带 HTTP/SSE Server,接入链路最短 小:认证、结果校验、任务队列 认证、隔离、调度等控制面要自己补
Pi Extension、Tool、Skill、Package 多 Provider 要自己包一层 HTTP 服务和会话存储 中到大:HTTP 服务、会话存储、任务调度、认证、配额、运维接口 外部服务层基本要自己建
DeepSeek Harness Plugin、工具和协议扩展 默认 DeepSeek,已接 Anthropic、OpenAI、Kimi、GLM 等 Web Host API 面向本机,远程暴露方式要自行验证 小到中:版本隔离层、远程暴露方案、升级回归 Developer Preview,接口可能破坏性变更
Codex MCP、Skill、Sandbox、Approval 可扩展到 Bedrock、Ollama 等,但协议层是 OpenAI Responses 格式 CLI / SDK / App Server(WebSocket)都可以远程化 中:服务封装、审批流、发版回归 平台绑定较强,迁出需要做协议转换
Claude Agent SDK MCP、自定义 Tool、Hook、Permission Claude 需要用宿主程序把 SDK 包成服务 中:服务封装、审批流、发版回归 平台绑定较强,服务层要自己建
OpenHands Tool、MCP、Remote Sandbox 可配置 Agent Server 本身就是远程服务 中:部署、Sandbox 和资源管理 部署和资源成本较高

同样,有 HTTP API 不等于能承担生产业务。认证、并发、Session 持久化、取消、隔离、故障恢复,还得逐项过。

按团队情况怎么选

先说结论那张表是按建设目标正着查,这里给一条反向排除的路径,判断顺序也代表我的优先级:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
想要的其实是"一直在线的个人或团队助手",不是业务后端?
├─ 是 → OpenClaw / Hermes Agent
└─ 否 ↓
任务是否需要完整的远程开发环境(拉仓库、装依赖、起服务、跑浏览器)?
├─ 是 → OpenHands
└─ 否 ↓
是否已确定单一模型平台,且没有真实的多模型需求?
├─ 是 → Codex / Claude Agent SDK
└─ 否 ↓
是否要把 Agent 内核嵌进自己的 Node.js 产品,自己定 API 和会话层?
├─ 是 → Pi
└─ 否 ↓
是否想验证插件化架构,或深度使用 DeepSeek 模型?
├─ 是 → DeepSeek Harness(记得留 Adapter 隔离层)
└─ 否 → OpenCode(HTTP/SSE 接入现有服务最快)

分述之外补充两点:DeepSeek Harness 值得固定版本跑一批影子任务,用数据判断插件化架构是否值得投入;OpenCode 上手先只跑只读任务,把认证、结果校验、并发限制补上,再放写操作。

最后看建设量。上面合并表里的相对建设量是选型里最现实的变量,按路线能差出一个量级,比“哪个模型更聪明”重要得多。团队没有专人补控制面的话,选建设量小的路线通常更划算。

为什么不从头写一套

自己写一个最小 Agent Loop 不难:拼上下文、调模型、解析 Tool Call、执行工具、把结果送回去。麻烦的是后面的细节——超时、中断、权限确认、上下文过长、子进程残留、Session 恢复。每一项都不复杂,叠在一起很耗时间。

现成 Harness 的价值就在这里:执行循环它搭好了,业务团队的时间花在更实际的问题上。现有 API 和 CLI 够不够清楚,模型拿到工具能不能完成任务,哪些步骤必须人工确认,最终结果怎么验收。

顺带说一句,这是检验内部工具质量的好机会。很多 CLI 是给人用的,错误全是文本,参数命名不一致,输出格式还会变。Agent 连续调几次,问题很快暴露。把参数、错误码、JSON 输出补齐后,受益的不只是 Agent,普通自动化脚本也更可靠。

业务经验也不必全塞进一段长 Prompt。操作步骤写成 Skill,真实动作交给 Tool,权限放进 Policy,判断结果交给固定的评测集。以后换模型或者换 Runtime,这些东西大多还能接着用。

Harness 能替我们做什么

把 OpenCode、Pi 或 DeepSeek Harness 放在业务系统后面,我把它们当执行面。一次 Run 内部的事情,尽量交给 Harness:

  • 调用模型并维护 Agent Loop;
  • 保存本轮会话上下文;
  • 注册和调用工具;
  • 载入 Skill、Agent 或扩展;
  • 处理文件、Shell 和工作目录;
  • 发送消息、工具和错误事件;
  • 做基础的权限确认和任务取消;
  • 在支持的情况下约束结构化输出。

这些够把一个业务想法跑起来了。客服助手先查订单和历史工单再组织回复,数据助手先查指标、发现异常继续查明细,研发助手改代码跑测试,都是这么起步的。

别把业务控制面也交给 Harness

Harness 只负责“怎么执行”。下面这些,还得留在自己的业务系统里。

业务任务状态

Harness 认识的是 Session 和 Message,业务认识的是工单、审核单、报表任务、订单、代码变更。两者画不了等号。

一次业务任务可能超时重跑两次,也可能先由 OpenCode 执行、后来交给 Pi 复核。更合适的关系:

1
BusinessTask 1 ── N AgentRun 1 ── N HarnessSession

我会保留三个 ID:

  • task_id:业务任务;
  • run_id:一次执行尝试;
  • session_id:具体 Runtime 内的会话。

这样以后做重试、回放、替换 Runtime,业务数据模型不用动。

身份和权限

Harness 不知道用户属于哪个部门,也不知道他能不能看某个客户、数据集、项目。它提供的工具权限只是第一层,资源级授权要在业务系统或 Tool Gateway 里做。

每次 Run 签发短期身份,让工具按租户、用户、任务检查权限。别把长期管理员 Token 放进 Agent 容器。

幂等、重试和审批

模型调用失败可以重试,查询工具超时也可以重试,但“提交退款”“发布内容”“修改配置”不能简单重放。

业务侧要清楚一个操作有没有执行过、能不能再执行、谁审批的。Harness 的确认弹窗可以承载交互,审批规则和最终状态存在业务系统。

结果是否正确

Harness 能让模型输出一份报告,不知道这份报告符不符合公司的业务定义。

数据分析结果可能必须带统计周期、数据口径、样本量;审核结果要有规则编号和证据;代码修改必须过指定测试。最终结果过 Schema 和业务规则校验,别只看文字通不通顺。

调度、容量和高可用

任务队列、Worker、限流、优先级、失败补偿、成本配额、跨机房部署,通常也不属于单个 Harness。把 Harness 当 Worker 用比较清楚,别让业务请求同步等一个 CLI 进程退出。

数据合规和审计

一次 Run 的上下文、工具输出、结果里往往带着业务数据,几件事提前确认,别等上线前才补:

  • 数据发给哪个模型供应商,留不留存、训不训练,合同和模型配置里是否明确;
  • 事件日志和工具输出落库前脱敏,凭证、个人信息、客户数据不能原样进日志;
  • 高风险动作能否追溯到人、run_id 和审批记录,审计记录留多久、能不能防篡改;
  • 跨境部署时,模型调用和日志存储的数据出境合规。

接入时怎么分层

我倾向拆成四层:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌───────────────────────────────────────────┐
│ Business Control Plane │
│ API / Tenant / Task / Retry / Approval │
│ Result / Notification / Billing │
└──────────────────┬────────────────────────┘
│ internal API
┌──────────────────▼────────────────────────┐
│ Harness Adapter │
│ OpenCode / Pi / DeepSeek / Codex │
│ event normalize / capability / routing │
└──────────────────┬────────────────────────┘
│ run
┌──────────────────▼────────────────────────┐
│ Execution Runtime │
│ Session / Context / Skill / Workspace │
└──────────────────┬────────────────────────┘
│ tool call
┌──────────────────▼────────────────────────┐
│ Tool Plane │
│ CLI / Harness Tool / MCP / Workflow API │
│ Auth / Schema / Timeout / Audit │
└───────────────────────────────────────────┘

控制面保存业务事实;Adapter 屏蔽 Runtime 差异;Harness 完成一次执行;工具层访问真实系统。

工具怎么接:CLI、原生工具和 MCP

三种方式不互斥,通常并存。已有成熟 CLI 的话先复用,尤其适合 PoC;文件处理、本地脚本、一次性迁移任务也适合 CLI。

已有 CLI:最快接入

最简单的做法,把 CLI 固化到 Runtime 镜像并加入 PATH:

1
2
3
biz-ticket get --id TICKET-001 --output json
biz-data query --dataset sales --range 7d --output json
biz-content inspect --content-id C-1001 --output json

再写一份 Skill,说明每个命令什么时候用、要哪些参数、返回什么。OpenCode、Pi 这类工具都能通过 Shell 执行它们。

但别把二进制临时复制到每个任务目录,让模型自由组合命令。目录只是文件位置,不是权限边界。至少处理这几件事:

  • CLI 版本固定,镜像可追溯;
  • 只开放允许执行的命令,参数经校验,不直接拼 Shell;
  • 默认只读,写操作走独立入口,用短期凭证;
  • 统一 JSON 输出和错误码,并设超时、输出大小、资源上限;
  • 记录调用人、参数、耗时和结果摘要。

Schema Wrapper:给高频命令加契约

问题是模型得理解命令行语法,参数转义、长输出、错误文本都带不确定性。进试生产后,最好在 CLI 外面加一层 Schema Wrapper:把命令包装成带 JSON Schema 的工具,工具名、用途、每个参数的类型和取值范围都用 Schema 描述,模型只传结构化参数。

比如先给 biz-ticket get 定一份 Schema:

1
2
3
4
5
6
7
8
9
10
11
{
"name": "get_ticket",
"description": "查询单个工单的详情",
"parameters": {
"type": "object",
"properties": {
"ticket_id": { "type": "string", "pattern": "^TICKET-[0-9]+$" }
},
"required": ["ticket_id"]
}
}

模型调用的是:

1
2
3
4
5
6
{
"tool": "get_ticket",
"arguments": {
"ticket_id": "TICKET-001"
}
}

Wrapper 校验 ticket_id 符合 Schema 后,执行固定命令 biz-ticket get --id TICKET-001 --output json。整段 Shell 不交给模型生成;参数不合法直接返回统一错误码,命令不会执行。

写 Wrapper 有开发成本,所以这层只加在 Agent 反复调用的高频命令上。偶尔用一次的,让模型走 Bash 就行。

Harness 原生工具:与当前 Runtime 集成最紧密

这里的 Native Tool 指通过某个 Harness 自己的 SDK、插件或扩展机制注册的工具,跟操作系统原生程序无关。OpenCode Custom Tool、Pi Extension、厂商 Agent SDK 里的自定义 Tool 都算。

这类工具直接向模型提供名称、用途和参数 Schema。模型发起调用后,Harness 负责参数解析、执行、事件通知、权限确认、错误回传。实现可以写在宿主进程里,也可以继续调内部 API——关键不在是否同进程,在于用的是该 Harness 专有的工具接口。

调用频率高、交互复杂、要细粒度权限的核心能力,原生工具比让模型拼 Shell 稳得多。代价是绑定具体 Runtime:OpenCode Custom Tool 拿不到 Pi 里用,换 Harness 往往要重写适配。

MCP:更适合共享能力

日志、订单、知识库、数据查询这类能力要同时给多个 Agent 客户端用,MCP 更合适。业务接口和凭证留在独立服务里,OpenCode、Pi、Codex、Claude 都通过同一套工具协议访问。

1
2
3
OpenCode ─┐
Pi ───────┼── MCP / Tool Gateway ── Business APIs
Codex ────┘

MCP 解决连接方式,企业还得在它前后补身份、资源授权、限流、缓存、脱敏、审计。

落地顺序

我会这么推进:

  1. 已有 CLI 先接进来,把任务跑通;
  2. 高频 CLI 增加 Schema Wrapper;
  3. 少量强交互能力做成 Harness 原生工具;
  4. 跨团队、跨 Runtime 的公共能力迁到 MCP 或 Tool Gateway;
  5. 高风险写操作走确定性 Workflow API 和人工审批。

不用一上来建个重平台,也不会长期停在“模型随便执行 Shell”的状态。

在业务和 Runtime 之间加一层 Adapter

不管先选哪个,业务服务最好只依赖自己的接口:

1
2
3
4
5
6
7
8
type Harness interface {
CreateRun(ctx context.Context, req CreateRunRequest) (Run, error)
Send(ctx context.Context, runID string, input Input) error
Subscribe(ctx context.Context, runID string) (<-chan Event, error)
GetResult(ctx context.Context, runID string) (Result, error)
Approve(ctx context.Context, runID string, approval Approval) error
Cancel(ctx context.Context, runID string) error
}

然后分别实现 OpenCodeAdapter、PiAdapter、DeepSeekAdapter。

Adapter 不需要把所有产品抹成一样,只统一业务真正依赖的部分:Run 状态、事件、取消、最终结果。Structured Output、Session Fork、特定 Sandbox 这类能力用 capability 标记暴露。

哪些业务值得先试

先选“需要理解上下文,但做错后还能被拦住”的任务。

场景 适合先交给 Agent 的部分 暂时不要自动化的部分
客服和工单 查订单、整理历史、分类、生成建议回复 退款、补偿、封禁
数据分析和报告 按中间结果继续查询,整理口径和结论 直接访问生产库或执行任意 SQL
内容审核 风险分类、规则匹配、证据整理 影响用户权益的最终裁决
运维诊断 查询日志、指标、Trace 和变更记录 未经审批直接修复生产环境
研发自动化 读代码、修改文件、运行测试 绕过 Review 直接发布
企业流程助手 制度查询、材料检查、表单准备 把文字回复当成流程已经办结

步骤固定、规则能完全枚举、或者一次错就造成不可逆损失的任务,普通程序和工作流更合适。Agent 只负责其中需要理解和判断的节点就行,不必接管整条流程。

从 PoC 走到生产

分四步走,别第一天把所有基础设施建齐。

第一步:只证明任务有价值

选一个 Runtime、一个模型、几项只读工具,准备固定输入、工具和结果格式,跑一批真实任务。至少记录:

  • 任务完成率;
  • 工具调用是否正确;
  • 无依据结论的比例;
  • 人工接管次数;
  • p50、p95 完成时间;
  • Token 和基础设施成本;
  • 超时、取消、恢复是否正常。

一次演示效果好,可能只是模型碰巧选对路径。稳定跑完几十个真实任务,才算 Harness、工具、上下文设计基本合适。

这一步别追求多模型多 Agent。单 Agent 加几个工具都跑不稳的话,加角色只会让问题更难定位。

第二步:把工具和结果收紧

工具侧按上面的落地顺序升级,把高频命令换成 Schema Wrapper,参数和资源范围收紧。结果侧用 Schema 校验,事实、证据、推断、建议分开。

有副作用的工具全部放审批后面。

第三步:补业务控制面

加任务表、队列、异步 Worker、幂等、分层重试、取消。task_id、run_id、session_id 串起来,模型、工具、审批事件记录下来。

到这步,Harness 才从个人工具变成业务执行器。

第四步:再考虑 Runtime 替换和共享工具层

准备固定回放集,候选 Runtime 跑影子任务,对比质量、成本、耗时、失败恢复。

社区出新项目别急着迁移。Adapter 和回放集的意义,就是让切换建立在数据上。

上生产前我会检查这些问题

这张清单把前面散落的验收点集中一遍,方便直接对着过:

  • 用户取消后,模型请求和子进程是否真的停止;
  • Runtime 崩溃后,任务能否安全恢复或重试;
  • 不同租户的目录、Session 和凭证是否隔离;
  • 工具参数和资源范围是否可限制;
  • 工具返回超长内容或恶意文本时怎样处理;
  • 最终结果是否经过 Schema 和业务规则校验;
  • 写操作是否有幂等键和审批记录;
  • 一次 Run 的模型、工具、审批和结果能否完整追踪;
  • 单任务的时间、Token、工具次数和资源是否有限额;
  • 事件日志和工具输出落库前是否脱敏;
  • 模型供应商的数据留存、使用和出境政策是否确认;
  • Runtime 升级失败时能否回滚。

这些问题没处理完,系统可以内部试用,不适合承担重要业务动作。

总结

这次比较下来最深的感受:独立运行、原生 HTTP API、会话管理,三个词必须拆开看。能独立跑不等于有远程服务——Codex 的 App Server 已经能走 WebSocket 了,认证、并发、限流照样自己补;有 Session ID 不等于解决了多租户、持久化、过期回收。

选型本身不难,决策树过一遍就有答案。真正决定成本的是两件事:自己要补多少控制面,业务数据、权限、审计放哪一侧。无论选谁,我都不会让业务直接依赖它的 Session 和消息格式——自己的 task_id、run_id、事件、结果先立住,通过 Adapter 调 Runtime;PoC 先让 Harness 调已有 CLI,跑通了再补 Schema、权限、审计、隔离、恢复。比一上来造“Agent 平台”实际得多。

参考资料

常见问题

OpenCode、Pi、DeepSeek Harness 都能调用自定义 CLI 吗?

原则上都可以。OpenCode 可以通过 Bash、自定义 Tool 和 MCP,Pi 可以通过 Extension 注册工具或执行命令,DeepSeek Harness 可以通过 Plugin、SDK 或 ACP 扩展。正式使用时最好为 CLI 增加结构化参数、权限和审计,而不是让模型自由拼接 Shell。

哪个更适合接到已有业务服务后面?

如果希望通过 HTTP/SSE 快速接入,OpenCode 的路径较短;如果准备把 Agent 内核嵌入自己的 Node.js 服务并自行设计控制面,Pi 更灵活;如果想验证插件化架构或深度使用 DeepSeek 模型,可以验证 DeepSeek Harness,但要给早期版本变化留出隔离层。