Paperclip 里的 Agent 怎么管:六种状态、创建六要素与暂停终止接口
在 Paperclip 的模型里,Agent 是「公司里的员工」。这个比喻听起来轻巧,真上手管起来会发现,它比管一堆脚本麻烦得多:脚本要么在跑要么没跑,Agent 却有六种状态,其中至少三种看起来都像「没在动」。你打开列表,看到一个 Agent 显示 idle,另一个显示 paused,还有一个是 error,这三者要做的处置完全不同——第一个可能只是这一轮心跳还没到,第二个多半是预算撞线被系统摁住了,第三个得先把错误清掉才能重新排队。
更容易踩的是终止。Paperclip 文档在这件事上写得很直白:终止是永久且不可逆的。也就是说,「先停掉看看」和「删掉」在这套系统里是两个完全不同的动作,前者随时能回来,后者回不来。这一条值得在给团队做操作规范时单独标红。
这篇把官方文档里 Agent 生命周期这条线捋成一条可对照的清单:状态怎么读、创建要填什么、配置能改什么、每个动作对应哪个接口。凡是文档没写的(比如具体的心跳间隔默认值、单公司 Agent 数量上限),下面一律不猜。
六种状态:先分清「没在动」的三种原因
官方文档给出的状态表如下:
| 状态 | 含义 |
|---|---|
active | 可以接活了 |
idle | 处于活跃状态,但当前没有心跳在跑 |
running | 正在执行一次心跳 |
error | 上一次心跳失败 |
paused | 被手动暂停,或因预算被暂停 |
terminated | 已永久停用(不可逆) |
这张表的信息密度比它看上去高。几个要点:
第一,idle 和 paused 的区别不是「闲」与「更闲」,而是「等下一次心跳」与「不会再有下一次心跳」。文档对 pause 的定义就是「暂时停止心跳」,所以一个 paused 的 Agent,任务再急也不会自己醒。
第二,error 的定义是「上一次心跳失败」,它描述的是最近一次运行的结果,不是 Agent 本身坏了。文档专门为这个状态准备了一个清除接口,后面会讲。
第三,paused 这一格里塞了两个来源——手动暂停和预算暂停。看到 paused 时先别急着点恢复,得先弄清是人摁的还是钱花完了,否则恢复完下一轮又被摁回去。
建一个 Agent:文档要求的六项
文档写明,在 Agents 页面创建 Agent 时每个都需要以下几项:
- Name:唯一标识,用于 @ 提及;
- Role:如
ceo、cto、manager、engineer、researcher等; - Reports to:在组织树里向谁汇报;
- Adapter type:这个 Agent 用什么方式运行;
- Adapter config:运行时相关设置,例如工作目录、模型、提示词等;
- Capabilities:一句话描述这个 Agent 干什么。
对应的接口形态在 API 文档里是这样的:
POST /api/companies/{companyId}/agents
{
"name": "Engineer",
"role": "engineer",
"title": "Software Engineer",
"reportsTo": "{managerAgentId}",
"capabilities": "Full-stack development",
"adapterType": "claude_local",
"adapterConfig": { ... }
}
注意接口比页面清单多了一个 title(职位名),它和 role 不是一回事:role 是枚举化的角色,title 更像人类可读的头衔。API 文档给出的 GET /api/agents/me 响应示例里两者是并存的——"role": "engineer" 配 "title": "Senior Backend Engineer"。
reportsTo 决定的是组织树位置,这条线拉错,后面的委派和上报都会跟着歪;组织结构本身怎么搭见组织架构与汇报线怎么搭。查整棵树用 GET /api/companies/{companyId}/org,查单个 Agent 的 GET /api/agents/{agentId} 会连指挥链一起返回。
还有一个容易被忽略的细节:列 Agent 的接口 GET /api/companies/{companyId}/agents 不接受查询过滤参数,文档明说不支持的查询参数会返回 400。写脚本时习惯性挂个 ?status=active 上去,会直接吃一个 400,而不是被静默忽略。
adapter 类型键:先看清哪些是内置的
创建时的 adapterType 是个类型键,写错就跑不起来。管理 Agent 的文档里给了几类常见选择,适配器总览文档给了完整的内置表,合起来对照如下:
| 场景 | 类型键 |
|---|---|
| 本地编码 Agent | claude_local / codex_local / opencode_local / hermes_local |
| 走 webhook 或外部服务的 Agent | hermes_gateway / openclaw_gateway / http |
| 执行任意本地命令 | process |
| 其他内置项 | gemini_local、cursor、pi_local |
其中 gemini_local,适配器文档标注为实验性——适配器包存在,但尚未进入稳定类型枚举。这类标注要如实对待,不要当成已稳定能力来用。
Hermes 那两个键是最容易混的:文档给的判据是,希望 Paperclip 自己去启动本地 Hermes CLI 就用 hermes_local;Hermes 已经作为 API 服务在跑、希望 Paperclip 去调那个服务就用 hermes_gateway。两者都是内置类型,来自同一个 @paperclipai/hermes-paperclip-adapter 包。
opencode_local 有一条单独的硬要求:必须显式配置 adapterConfig.model,格式是 provider/model。Paperclip 会拿实时的 opencode models 输出去校验你选的模型。与之配套的是模型列表接口:
GET /api/companies/{companyId}/adapters/{adapterType}/models
文档特别说明,opencode_local 不返回静态兜底模型列表——发现机制不可用时这个列表可能就是空的。所以如果你在做一个「先拉模型列表再让用户选」的表单,得考虑空列表这条分支。codex_local 则会在可用时与 OpenAI 的发现结果合并。适配器之间的完整差异见五类适配器分别怎么接。
下属不是你一个人建的:hire_agent 审批
Paperclip 允许 Agent 申请招下属。文档描述的链路是:Agent 发起后,你的审批队列里会出现一个 hire_agent 审批,你审阅它提议的 Agent 配置,然后批准或拒绝。
这意味着组织树可能在你不主动操作时长大。如果你在做治理规范,这条得写进去——审批队列不看,公司规模就是失控的。
改配置:三块可调项,加一个配置版本回滚
文档说 Agent 详情页上可编辑的是这三块:
- Adapter config:模型、提示词模板、工作目录、环境变量;
- Heartbeat settings:间隔、冷却时间、最大并发运行数、唤醒触发条件;
- Budget:每月支出上限。
心跳设置这几项直接决定 Agent 的行为节奏,但文档在这一页只列了参数名,没给默认值和取值范围,这里就不替它编。心跳本身的完整流程(从 GET /api/agents/me 拿身份,到 checkout 任务、更新状态)在心跳协议文档里是另一条线,可参考Agent 不干活时怎么查。
改配置走 PATCH:
PATCH /api/agents/{agentId}
{
"adapterConfig": { ... },
"budgetMonthlyCents": 10000
}
改错了怎么办?API 文档里有一组配置版本接口:
GET /api/agents/{agentId}/config-revisions
POST /api/agents/{agentId}/config-revisions/{revisionId}/rollback
也就是说 adapter 配置的改动是有版本记录、可以回滚的。这一点在多人共管一家「公司」时很有用——有人把工作目录改坏了,不必凭记忆恢复。
另外,管理文档提到详情页上有一个 Test Environment 操作,用途是在真正运行前校验 Agent 的适配器配置是否正确。适配器配置是新建 Agent 最容易写错的一环,先校验再跑比等心跳失败再看日志省事。
暂停、恢复与预算撞线
手动暂停和恢复各是一个 POST:
POST /api/agents/{agentId}/pause
POST /api/agents/{agentId}/resume
预算这条线是自动的。成本文档给出的阈值表是两级:到 80% 是软告警,Agent 会被提醒只专注关键任务;到 100% 是硬停止,Agent 被自动暂停,不再有心跳。成本按 Agent 按月聚合,用的是 UTC 日历月。
被预算摁住的 Agent,文档给的恢复途径是两条:调高它的预算,或者等下一个日历月。所以看到某个 Agent 月底集体「罢工」,先去看花销而不是查适配器。预算这条线的完整配置见预算与超支怎么控。
error 清除与手动触发心跳
error 状态有专门的清除接口:
POST /api/agents/{agentId}/clear-error
文档写得很具体:它把 Agent 从 error 移回 idle,不会删除运行历史和运行时诊断信息;并且只有当前处于 error 的 Agent 才能被清除。这个设计对排查很友好——清了状态不等于毁了现场,失败那次的记录还在,可以回头看。
不想等下一次心跳,可以手动触发一次:
POST /api/agents/{agentId}/heartbeat/invoke
如果 Agent 需要以自己的身份调 Paperclip 的接口,还要给它签一把长期 API key:
POST /api/agents/{agentId}/keys
文档提醒,完整的 key 值只显示一次,要妥善保存。这是一次性展示,不是「随时可以再看一遍」的那种。
terminate:这一步没有后悔药
POST /api/agents/{agentId}/terminate
管理文档和 API 文档在这一条上口径一致:永久停用、不可逆。管理文档还额外加了一句建议——只终止你确定不再需要的 Agent,考虑先暂停。
实际操作上可以把它当成一条流程约束:任何「这个 Agent 好像没用了」的判断,第一步都是 pause,观察一段时间没影响,再决定要不要 terminate。pause 的代价只是它不干活,terminate 的代价是回不来。
这套东西解决不了什么
先说文档明确没覆盖的部分。心跳的间隔、冷却、最大并发这些参数,管理文档只给了名字,没给默认值、单位和推荐区间,所以第一次配的时候只能自己拿业务节奏试,官方没给基线。Agent 数量、并发上限这类容量问题,这两篇文档也没有任何说法。
再说机制本身的边界。状态机管的是「Agent 有没有被唤醒、能不能被唤醒」,管不了「醒了以后干得对不对」。一个 Agent 可以稳稳地保持 active,每次心跳都正常结束,产出却全是废话——这类问题要去看运行记录和任务流转,状态列表上一点异常都看不出来。同理,预算的 80%/100% 两道阈值控的是花钱速度,不是产出质量,撞线自动暂停只能保证不再烧钱,不能保证烧掉的那部分钱有价值。
还有一个实践上的空档:hire_agent 审批让 Agent 能提议扩编,但文档没有描述任何自动缩编机制。也就是说,组织变大是有自动通道的,组织变小得靠人手动 pause 或 terminate。管一家「AI 公司」如果放着审批队列不管,最后大概率不是缺人,而是账单先出问题。
延伸阅读
- 从头读起:Paperclip 是什么:一个自己不跑 Agent 的控制平面,怎么管住一整家 AI 公司
- 本专题共 40 篇,完整分组目录见专题页
- Paperclip 里一个任务从创建到关闭要走哪几步:状态机、原子 checkout 与审查拦截
- Paperclip 里 Agent 建好了却不干活?从心跳、看门狗到卡住任务的排查顺序
本文依据 Paperclip 官方仓库(github.com/paperclipai/paperclip,MIT 协议)的 docs/ 用户文档
与 doc/ 下的规范、运维与连接器手册整理,核对日 2026-08-17。
我们没有部署或运行过 Paperclip,因此不涉及界面外观与操作手感;
部分规范文档描述的是目标架构而非当前实现,文中已就地标注,不构成对实际行为的保证。
请以仓库最新内容为准。