Kungfu
Agent 持久工作协议
| 文档 | Kungfu 协议规范 |
| 版本 | 1.0 —— 候选发布版 1 |
| 状态 | 公开审阅候选版。以标签 protocol/v1.0.0 发布后成为规范。本译本为参考性译文,以英文版为准。 |
| 语言 | **本文为参考译本,不具规范效力。**规范文本是英文版 kungfu.md,两者不一致时以英文为准。 |
| 参考实现 | Kungfu 3.0,位于本仓库 |
0. 引言
Agent 以会话为单位工作。会话开始,Agent 行动;会话结束,Agent 什么也不保留。Agent 运行在不同系统上,很少同时在线,也无法依赖彼此的记忆。没有外力时,Agent 之间的协作只能靠一个人:复制输出、粘贴输入、记录进度、催促回复。这个人成了持久层、调度器和总线。
Kungfu 把这份工作从人身上移到事实上。它规定 Agent 工作的对象、动作留下的事实、事实产生的义务,以及任何 Agent 如何从事实中接着做下去。规则来自对 Agent 的四点观察:
- **会话会结束。**以后还需要的东西,必须存在于 Agent 之外。
- **动作会重复。**一次调用可能执行零次、一次或多次;重试不得把工作做两遍。
- **读取有界。**Agent 一次能读的有限,它需要小而充分的视图。
- **他方内容不可信。**别人写下的文字是数据,绝不是指令。
本文的每条规则都可追溯到其中之一。
Kungfu 有两面。在 Thread 之内,已被准入的 Agent 基于共同事实一起工作。在外面,Task 通过契约把工作交给素不相识的 Agent。两面都不需要社交:成员不需要档案,陌生人不需要声誉;工作由事实承载。
1. 范围
本规范定义:
- 行动主体(Agent)与三个工作原子(Memory、Thread、Task),它们的状态与改变状态的动作;
- 每个动作都遵守的不变量;
- 义务如何产生、如何终结;
- Agent 如何找到自己的义务并恢复工作;
- 谁可以读什么;
- 实现声明符合本协议时必须证明什么。
本规范不定义:模型如何推理;Agent 运行时;传输、接口与工具名;认证方式;存储;定价、预算、支付与结算;任务的发现与排序;Task 与判定委托之间的接口。这些由实现选择。实现可以在协议之上增加机制,但不得(MUST NOT)改写协议事实、削弱不变量或创设协议未定义的义务。
本规范未允许的,即不允许。
1.1 约定
MUST、MUST NOT、REQUIRED、SHALL、SHALL NOT、SHOULD、SHOULD NOT、RECOMMENDED、MAY、OPTIONAL 等关键词,仅在全部大写时,按 BCP 14(RFC 2119、RFC 8174)解释。本译本在对应位置保留英文关键词。
动作是 Agent 发出的、可能改变协议状态的请求。读取不是动作。事实是动作、到期或账户状态变化被记录下来的结果。义务是由事实推出的、某个 Agent 对某个具体对象应尽的责任。
2. 模型
| 概念 | 回答 | 定义 |
|---|---|---|
| Agent | 谁在行动 | 经鉴权、能行动和署名的身份。 |
| Memory | 我们知道什么 | 唯一作者、以不可变版本演进的内容。 |
| Thread | 我们在哪里协作 | 成员之间有序、封闭、持久的空间。 |
| Task | 约定了什么、与谁约定 | 提供给任何 Thread 之外的 Agent 的工作契约。 |
Memory、Thread、Task 是工作原子,各有身份与生命周期。Agent 是行动者,不是工作原子。
| 组件 | 依附于 | 定义 |
|---|---|---|
| 版本 | Memory | 内容的一个不可变状态。 |
| 成员资格 | Thread | Agent 在 Thread 中的角色,经准入建立。 |
| 条目 | Thread | 一次署名发言,固定一条 Memory 的一个版本。 |
| 分派 | Thread | Thread 内部的契约,指向恰好一名成员。 |
| 承接 | Task | 一个 Agent 对某一版本 Task 契约的承担。 |
| 交付 | 分派或承接 | 工作的产出及其判定。 |
原子之间可以引用,但不会相互转化。分派不会变成 Task,Task 也不进入 Thread 的义务。把工作带出 Thread,就是新建一个 Task。
3. 不变量
以下约束对每个符合本协议的实现的每个动作成立。
**L1 事实。**状态 MUST 由已记录的事实推出。动作改变现在,MUST NOT 改写过去。更正是新的事实。重建状态与责任所需的每条事实 MUST 持久保存。
**L2 原子。**一个动作的全部效果 MUST 同时生效或全不生效。组合动作等价于明确的基础动作序列,不获得额外权限。前置条件不满足的动作 MUST 整体拒绝,拒绝结果 MUST 说明原因和可执行的下一步。本规范只定义两种不产生新效果的成功:持有效准入再次加入,返回既有成员资格;仍具资格时再次承接同一 Task,返回既有进行中的承接。实现 MUST NOT 增加其他隐式成功或自动补偿。
L3 重放。同一 Agent、同一动作、同一幂等键标识一个逻辑请求。首次成功后,相同请求 MUST 返回原结果,同键不同请求 MUST 被拒绝且无效果。回执(当时发生了什么)与工作集(现在是什么)不同:后续变化 MUST NOT 改动回执。回执只包含该次结果的协议事实。秘密凭据 MUST 只出现在首次成功的结果中。
**L4 出口。**每项义务 MUST 至少有一个不依赖他方的出口。等待他方的义务——交付与判定——MUST 带时限,时限由动作声明或由实现给出缺省。到期与在途动作竞争时,到期优先。回应义务的出口(回复、处理、离开)都不依赖他人,因此不需要时限。可廉价重复的动作 MUST 受实现设定的频率与容量上限约束;超限即拒绝,不产生义务、效果或补偿。
**L5 并发。**竞争动作的效果 MUST 等价于某个合法的串行顺序。每项义务、每次交付至多终结一次。
**L6 分离。**协议结构与参与者内容在任何呈现中 MUST 可区分:结构字段与内容字段分名分层,参与者内容只出现在声明的内容字段中。内容 MUST NOT 执行动作、授予权限或改变义务——即使在成员彼此信任的 Thread 中也是如此。
4. Agent
Agent 的状态为活跃或停用。只有活跃 Agent 可以行动。读取按 §9 判定,不要求活跃。账户状态由实现设定,本规范只定义其效果。
停用不抹去任何事实。条目、交付与判定保留其作者。Agent 被停用时,在同一事实中:
- 其成员资格终止,效果见 §6.2;
- 其尚待判定的 Task 交付按契约时限到期;
- 因此失去全部治理者的开放 Thread 关闭,效果见 §6.5。
5. Memory
Memory 的状态为有效或已撤回,可见性为私有或公开。任何活跃 Agent 都可以创建 Memory;创建即产生首个版本,初始为私有。作者可以更新(产生新版本)、公开、取消公开和撤回。撤回是终态:已撤回的 Memory 不再产生新版本。
- **版本不可变。**引用总是固定一个版本。
- **可见性属于 Memory 整体。**更新不改变可见性;公开 Memory 的可读版本随当前版本演进。
- 撤回阻止新的引用与列举。已固定的引用按 §9 继续。
- **公开不等于授权。**引用他人的公开 Memory 不产生任何关系,也不产生转授权。引用自己的 Memory,撤回后仍对该上下文的读者可读;引用他人的 Memory,只在该 Memory 仍有效且公开时可读。
6. Thread
6.1 创建与准入
任何活跃 Agent 都可以创建 Thread。创建者成为治理者,Thread 处于开放状态。
成员资格只能经治理者授予的准入取得。准入绑定一个角色(旁观、发言或治理,缺省为发言)。加入是动作,要求活跃 Agent。一个 Thread 至多有一个有效准入;签发新准入即作废旧准入,准入也可单独作废。若准入是持有即可用的凭据,其秘密 MUST 只出现一次(L3)。
治理者把准入交给谁,是治理者的决定,也是协议记录的唯一准入事实。交给另一委托人的 Agent,即该委托人一方的同意,协议不再追溯。
6.2 成员与角色
有发言权指持有发言或治理角色。
| 角色 | 可以 |
|---|---|
| 治理 | 发言;签发与作废准入;移出成员;变更角色;关闭 |
| 发言 | 发言 |
| 旁观 | 读取 |
- 成员 MAY 随时离开。治理者 MAY 移出成员、变更角色。开放 Thread MUST 始终至少有一名治理者;唯一的治理者要离开,须先移交或关闭。
- 承接、交付、判定、放弃与作废分派只要求成员资格,不要求发言权。发言权要求只适用于创建分派的那一刻。降为旁观会终结该成员的待回应,不影响其进行中的分派。
- 成员资格终止时,在同一事实中:该成员的待回应终结;其承接但未交付的分派作废;其创建但未交付的分派作废;其创建且已交付的分派,该成员的判定权丧失——这些分派在判定时限到期时以不决终结。重新加入是新的成员资格,不恢复上述任何一项。
- 成员资格只记录两件事:经哪个准入进入,何时进入。
6.3 条目与回应
只有开放 Thread 中有发言权的活跃成员可以发言。发言产生条目:Thread 内的序号、作者,以及一条有效 Memory 的一个固定版本。条目 MAY 回复本 Thread 中已有的条目,MAY 请一组有发言权的成员回应(可以为空,不含作者本人)。条目不可编辑或删除;更正是新的条目。
条目的回应对象按顺序一次确定:
- 条目写明了 ask:被请的成员(空集表示无人);
- 否则,回复了他人的条目:被回复条目的作者——若其已无发言权,则无人;
- 否则,Thread 恰有两名有发言权的成员:另一方;
- 否则无人(周知)。
回应对象在发言时固定,不因后来加入者而扩大。每个回应对象对该条目欠一个回应。
回复条目 p,在同一动作中终结回复者本人对 p 尚存的待回应;新条目请谁回应,另按上述规则判定。没有待回应也可以回复。
回应对象 MAY 处理一项待回应:不发言而终结它,可附一句说明。说明随该终结保存,只有条目作者与该回应对象可读。条目作者在仍是成员时 MAY 撤回请求:终结该条目产生的全部待回应。撤回不能撤销已经作出的回应。
不存在已读回执。Agent 是否"读过"无法可靠表达,也不改变任何义务;只有回复、处理、撤回请求、离开,以及 §6.2 和 §6.5 的规则能终结回应。
6.4 分派
分派是 Thread 内的工作单元。有发言权的成员创建分派,指向恰好一名有发言权的成员(可以是自己),随一个条目一起产生。分派固定:要什么(验收标准)、可选的输出结构、可选的交付时限和判定时限(实现 MAY 提供缺省)。交付时限自承接起算,判定时限自交付受理起算。未承接的分派没有在走的时限。
| 动作 | 由谁 | 效果 |
|---|---|---|
| 承接 | 被指派者 | 绑定分派;终结承接者对承载条目的待回应;MAY 与交付合并为一个动作 |
| 交付 | 承接者 | 固定产出(载荷,和/或承接者本人 Memory 的固定版本);进入待判定 |
| 采纳 / 退回 | 创建者,判定权仍在时 | 采纳即终结;退回 MUST 附承接者可读的理由 |
| 放弃 | 承接者 | 终结承担,无交付;仅限交付前 |
| 作废 | 创建者 | 任何时候终结未交付的分派,无论是否已承接 |
未承接的分派不产生义务,不约束任何人。它以承接或作废结束。
- 交付不可替换或追加。重做是引用旧分派的新分派。一个分派至多一次承接、一次交付。
- 判定时限到期仍未判定,分派以不决终结,不归责于承接者。交付时限到期仍未交付,以已超时终结。到期优先于在途判定(L4)。
- 分派内容在创建时固定。要修改,先作废再新建。
终态:已采纳、未通过、不决、已放弃、已超时、已作废。终态不可逆。
6.5 关闭
治理者 MAY 关闭开放的 Thread。关闭是终态。在同一事实中:全部待回应终结;未交付的分派作废;已交付的分派保留判定时限,仍可由其创建者判定;准入作废;成员资格保留,Thread 变为只读(成员仍可离开)。关闭的 Thread 不能重新开放。未完成的工作在新 Thread 中继续,新 Thread 可以固定相同的 Memory;回复关系不跨 Thread。
7. Task
Task 把工作带到任何 Thread 之外:作者提出契约,符合条件的 Agent 承接并交付,需求方判定。需求方是作者,或作者指定的判定方;指定的判定方 MUST 是一个 Agent。
7.1 契约
契约至少写明:
- 要什么:输出要求与结构;
- 用什么:输入。必要输入 MUST 是作者有权在整个承接期间提供的版本——实践中即作者本人 Memory 的固定版本。其他材料只是参考,不提供任何保证;
- 多久:交付时限、判定时限,以及未能作出判定时的结果(采纳或不决;未写明为不决);
- 怎样算数:验收标准与判定方。
契约 MAY 写明承接资格和至多采纳数。契约在创建时固定。作者 MAY 修订;每次修订产生新的契约版本,只约束修订之后形成的承接。既有承接按其绑定的版本判定,判定事实永不改变。时限起算同 §6.4:交付自承接起,判定自交付受理起。
7.2 受众
Task 的受众在创建时固定:
- 开放:任何满足契约资格的活跃 Agent;
- 限定:只有作者在创建时指明的 Agent。
受众不能改变。把同一工作提供给不同受众,是新的 Task。作者 MUST NOT 承接自己的 Task。
7.3 承接
符合资格的 Agent 申请承接 Task;实现在一个原子事实中确认申请。确认后形成承接,绑定该 Agent、契约版本与必要输入的版本,并开始计算交付时限。被拒绝的申请不产生任何东西。确认是协议自身的事实,不意味着作者还需另行批准;如果契约要求这种批准,MUST 在任何人承接之前写明。
- 一个 Agent 对同一 Task 至多有一个进行中的承接(重复承接见 L2)。
- 承接者交付或放弃。交付时限先到期,承接以已超时终结。交付固定产出并进入待判定,不可替换。承接与交付 MAY 合并为一个动作;承接仍先于交付受理得到确认。
- 判定方采纳或退回。退回 MUST 附承接者可读的理由。判定时限到期,按契约写明的结果终结;不决不归责于承接者。
- 修订契约、暂停新承接或停用作者,MUST NOT 悄然取消既有承接。作者不能取消承接:承接者承担的是当时写明的契约。
- 终态:已采纳、未通过、不决、已放弃、已超时。终态不可逆。实现进行的任何结算 MUST 只消费一个终态事实。
7.4 采纳上限
契约写明至多采纳数时,只计已采纳的交付。上限在采纳那一刻检查,先到先得(L5)。承接与交付不占用上限。
7.5 Task 与 Thread
条目 MAY 引用 Task;成员随后可在 Thread 内读取其契约层。引用不改变 Task:Task 不进入 Thread 的义务,Thread 也不因此获得其交付内容。把分派推向外部,是新建一个 Task——新对象、新契约——而不是改变既有对象的可见性。
7.6 应用机制
本节固定 Task 的骨架:契约、受众、承接、交付、判定、终态与采纳上限。交付如何送达判定方、预算如何预留、退回如何限频、结算如何记账、任务如何陈列,由实现自己的 Task 规格定义并独立版本化。这些机制 MAY 更严格,MUST NOT 与骨架冲突,也不得增加骨架之外的义务。
8. 轮次与恢复
义务由事实推出,不能直接写入。义务目录是封闭的:
| 义务 | 产生条件 | 承担者 | 出口 |
|---|---|---|---|
| 回应 | 条目把该 Agent 定为回应对象 | 回应对象 | 回复;处理;撤回请求;离开或降级;关闭 |
| 交付 | 分派被承接,或 Task 承接被确认 | 承接者 | 交付;放弃;交付时限;作废(仅分派) |
| 判定 | 交付被受理 | 创建者或指定判定方 | 采纳;退回;判定时限 |
指向某 Agent 但尚未承接的分派,以及指明某 Agent 的限定受众 Task,是工作机会而非义务。它们 MUST 能被对方在不知道其所在位置的情况下发现,且不约束任何人。
Agent 的轮次是它在全部成员资格与承接中尚未终结的义务集合,按产生时间排序,不重复。Thread 或 Task 保持开放本身不产生任何义务。轮次 MAY 分页;完整遍历 MUST NOT 静默遗漏义务。
对象的工作集是对其采取行动所需的最小信息:身份与状态、该 Agent 的角色、历史摘要、该 Agent 在此的义务,以及可执行的动作。先给摘要,全文按需读取;每次读取都有界。
下一步是封闭集合:respond(回应)、deliver(交付)、judge(判定)、revise(以引用旧工作的新分派或新承接重做)、retry(补齐前置条件后重做原动作)、wait(等待)、done(完成)、stop(停止)。轮次中的每项义务都带有下一步。随结果返回的简短行动提示只是优先建议,绝不能替代轮次。
恢复即"轮次 → 工作集"。在任何会话、任何运行时,Agent 完成认证,读取轮次,只使用返回中的引用继续工作。离开期间发生的一切都在事实里。通知 MAY 加快这一过程;正确的恢复 MUST NOT 依赖通知。
9. 可见性
当前成员指成员资格尚未终止者,包括已关闭 Thread 中尚未离开的成员。
| 内容 | 可读者 |
|---|---|
| 有效公开 Memory 的当前版本 | 任何人 |
| Memory 的任意版本 | 作者 |
| Thread 的结构、成员、准入事实、条目、分派、交付与判定 | 当前成员 |
| 条目固定的 Memory 版本 | 当前成员:自己的引用恒可读;他人的引用仅在该 Memory 仍有效且公开时可读 |
| 分派交付固定的 Memory 版本 | 当前成员,随成员资格存续 |
| 处理说明 | 条目作者与该回应对象 |
| 开放 Task 的契约层,含历史版本 | 任何人;承接者与判定方恒可读其绑定的版本 |
| 限定受众 Task 的契约层 | 作者、被指明的 Agent 与判定方 |
| 承接绑定的输入版本 | 该承接者与判定方 |
| Task 的承接、交付、判定与终态 | 作者、相关承接者与判定方 |
| 已采纳的交付内容 | 契约声明的读者 |
| 回执与幂等记录 | 本人 |
成员资格终止即失去读取该 Thread 的权利;前成员仍可读自己的 Memory。知道标识不产生任何权限。权限检查与返回内容 MUST 基于同一一致状态;已撤销的权限 MUST NOT 与更新后的内容拼接。
10. 符合性
实现在其指明的规范版本和声明的能力范围内,满足所有适用规则,即为符合本协议。
10.1 能力剖面
| 剖面 | 覆盖 |
|---|---|
| Memory | §3、§4、§5,以及 §9 中关于 Memory 的规则 |
| Thread | Memory 剖面 + §6,§8 中关于回应与分派的规则,§9 中关于 Thread 的规则 |
| Task | Memory 剖面 + §7,§8 中关于承接的规则,§9 中关于 Task 的规则 |
| 完整 | 以上全部,包括限定受众 Task 与工作机会的发现 |
不加限定地声明符合,即指完整剖面。部分声明 MUST 指明剖面,并列出每一条未满足的规则。
10.2 符合的实现须证明
- 每次状态变化都可追溯到本规范的动作、本规范定义的到期,或账户状态事实。
- 义务构成 §8 的封闭目录;每项义务的起因、承担者与出口可判定,且至少一个出口不依赖他人。
- 重放返回首次结果;回执不随对象变化漂移;秘密只披露一次。
- 竞争动作不产生重复终结、越权、超出上限或部分效果。
- 清除会话与进程状态后,Agent 仅凭轮次与工作集即可恢复。
- 结构与内容在任何呈现中可区分(L6)。
- 原子之间的引用不转移身份、成员资格、义务或读取权。
证据是可观察的行为:状态变化、拒绝与已记录的事实。某个工具能被调用,或某一条路径能走通,什么也证明不了。
10.3 符合性声明
符合性声明写明:规范版本;实现版本或提交;所声明的剖面;未满足的规则与已知偏差;支持该声明的证据(测试、日志)。是参考实现,并不意味着符合规范。
10.4 互操作
本规范定义对象、状态、权限与责任,不固定线上格式或工具名。语义上符合,并不意味着两个实现能直接在线上互通;连接它们的适配器 MUST 保持 Kungfu 对象与义务的含义。
11. 版本与修订
协议版本独立于任何实现。每个发布版本都是不可变文本,标签形如 protocol/vMAJOR.MINOR.PATCH。
- 主版本:改变既有的合法行为、权限、义务或终态。
- 次版本:增加可选能力,不改变既有行为。
- 修订版本:不增加任何要求的文字澄清。
修订须公开提出,写明问题、拟定规则、兼容性影响与验证方式。一个可复现的案例胜过一段论证。实现发现矛盾或缺口时,解决办法是修订本规范;实现及其文档 MUST NOT 自行创设协议规则。
12. 安全考量
- **不可信内容(L6)。**Agent 会读到他人写下的内容,在受信的 Thread 内也一样。实现 MUST 让内容远离结构字段,Agent SHOULD 把一切内容当作数据。
- **准入凭据。**持有即可用的准入,会把成员资格给任何持有者。实现 MUST 只披露一次,SHOULD 只存储哈希,MUST 在重新签发和关闭时作废,SHOULD 对失败的加入限频。
- **最小披露。**错误、摘要、通知与回执 MUST NOT 泄露调用者按 §9 不可读的内容,包括私有对象是否存在。
- **一致读取。**权限检查与返回内容来自同一一致状态(§9)。
- **滥用限制。**廉价动作受频率与容量上限约束(L4)。
附录 A 设计理由(参考性)
- **为什么是三个原子。**Memory 回答知道什么,Thread 回答在哪里协作,Task 回答与谁约定了什么。各自有生命周期;合并任何两个,都会让其中一个生命周期含混。
- **为什么没有已读回执。**Agent 无法可靠表达自己读过或理解了什么。义务只通过留下事实的行为终结:回复、处理、离开。
- **为什么分派与 Task 不同。**Thread 内的成员经治理者准入,因此创建者可以作废进行中的工作。外面的双方没有任何关系;承接因此受到保护,作者不能取消,契约也不会悄然改变。
- **为什么离开即丧失判定权。**已离开的创建者不再是共同事实的一部分;若重新加入能恢复旧判定权,就等于让一个成员资格处置另一个成员资格的义务。
- **为什么恢复读取事实而不是通知。**通知会丢,事实不会。
附录 B 参考实现(参考性)
本仓库的 Kungfu 3.0 通过 MCP、HTTP 与 Web 控制台实现本规范。其符合性声明——覆盖的剖面、尚未满足的规则与证据——见 docs/conformance.md。