Paperclip 里的 Agent 怎么管:六种状态、创建六要素与暂停终止接口

2026-08-17

在 Paperclip 的模型里,Agent 是「公司里的员工」。这个比喻听起来轻巧,真上手管起来会发现,它比管一堆脚本麻烦得多:脚本要么在跑要么没跑,Agent 却有六种状态,其中至少三种看起来都像「没在动」。你打开列表,看到一个 Agent 显示 idle,另一个显示 paused,还有一个是 error,这三者要做的处置完全不同——第一个可能只是这一轮心跳还没到,第二个多半是预算撞线被系统摁住了,第三个得先把错误清掉才能重新排队。

更容易踩的是终止。Paperclip 文档在这件事上写得很直白:终止是永久且不可逆的。也就是说,「先停掉看看」和「删掉」在这套系统里是两个完全不同的动作,前者随时能回来,后者回不来。这一条值得在给团队做操作规范时单独标红。

这篇把官方文档里 Agent 生命周期这条线捋成一条可对照的清单:状态怎么读、创建要填什么、配置能改什么、每个动作对应哪个接口。凡是文档没写的(比如具体的心跳间隔默认值、单公司 Agent 数量上限),下面一律不猜。

六种状态:先分清「没在动」的三种原因

官方文档给出的状态表如下:

状态含义
active可以接活了
idle处于活跃状态,但当前没有心跳在跑
running正在执行一次心跳
error上一次心跳失败
paused被手动暂停,或因预算被暂停
terminated已永久停用(不可逆)

这张表的信息密度比它看上去高。几个要点:

第一,idlepaused 的区别不是「闲」与「更闲」,而是「等下一次心跳」与「不会再有下一次心跳」。文档对 pause 的定义就是「暂时停止心跳」,所以一个 paused 的 Agent,任务再急也不会自己醒。

第二,error 的定义是「上一次心跳失败」,它描述的是最近一次运行的结果,不是 Agent 本身坏了。文档专门为这个状态准备了一个清除接口,后面会讲。

第三,paused 这一格里塞了两个来源——手动暂停和预算暂停。看到 paused 时先别急着点恢复,得先弄清是人摁的还是钱花完了,否则恢复完下一轮又被摁回去。

建一个 Agent:文档要求的六项

文档写明,在 Agents 页面创建 Agent 时每个都需要以下几项:

  • Name:唯一标识,用于 @ 提及;
  • Role:如 ceoctomanagerengineerresearcher 等;
  • 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 的文档里给了几类常见选择,适配器总览文档给了完整的内置表,合起来对照如下:

场景类型键
本地编码 Agentclaude_local / codex_local / opencode_local / hermes_local
走 webhook 或外部服务的 Agenthermes_gateway / openclaw_gateway / http
执行任意本地命令process
其他内置项gemini_localcursorpi_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 官方仓库(github.com/paperclipai/paperclip,MIT 协议)的 docs/ 用户文档 与 doc/ 下的规范、运维与连接器手册整理,核对日 2026-08-17。 我们没有部署或运行过 Paperclip,因此不涉及界面外观与操作手感; 部分规范文档描述的是目标架构而非当前实现,文中已就地标注,不构成对实际行为的保证。 请以仓库最新内容为准。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。