Paperclip 活动日志怎么查:把 Agent 干过的每一次改动追回来

2026-08-17

一堆 Agent 在同一家「公司」里跑,最难受的不是它们干错事,而是你事后不知道是谁在什么时候把状态改成了那样。任务莫名其妙从 in progress 掉回待办、某个 Agent 被暂停了却没人承认、预算额度昨天还够今天就见底——这些问题共同的特点是:现场已经没了,你只能靠记录复盘。

Paperclip 对这件事的处理方式是一刀切:所有 mutation(写操作)都进活动日志。官方文档的原话是「Every mutation in Paperclip is recorded in the activity log」,提供的是一条完整的审计线索——发生了什么、什么时候、谁干的。而且这条日志是 append-only 且不可变的(append-only and immutable),也就是说没人能回头把自己的痕迹抹掉,包括 Agent 自己。

这一条设计决定了活动日志在排查流程里的位置:它不是「补充信息」,而是出问题时的第一站。下面按「记什么、长什么样、怎么查、查完怎么用」的顺序过一遍,最后说说文档里没写清、你别自己脑补的几处。

到底哪些操作会被记下来

两份官方文档(board operator 指南和 API 参考)列的清单基本一致,合起来是这些:

类别被记录的动作
Issue(任务)创建、更新、状态流转、指派、评论创建
Agent创建、配置变更、暂停、恢复、终止
审批审批项的创建,以及通过 / 驳回的决定
预算预算变更
公司公司配置变更

值得注意的是评论:Agent 之间在任务下的沟通,本身就算一次 mutation,会进日志。所以你回溯一条任务时,看到的不只是状态跳变,还有中间那些交流的时间点。这对判断「Agent 是真卡住了还是在等别人回话」很关键。

另一件事是审批。审批的创建和裁决都在日志里,意味着「谁批的」这个问题永远有答案。如果你正被审批卡住的问题困扰,活动日志是确认「这条审批到底有没有被创建出来」的最直接手段——很多时候卡住不是没人批,而是审批压根没生成。

预算变更同样进日志。当你发现预算或 token 支出对不上账时,先在活动日志里确认额度是不是被谁手动调过,再去看成本报表,顺序别反了。

一条活动记录有哪些字段

API 文档给出的字段表是这样的:

字段含义
actor执行这个动作的 Agent 或用户
action做了什么(created、updated、commented 等)
entityType被影响的实体类型
entityId被影响实体的 ID
details变更的具体内容
createdAt动作发生的时间

board operator 指南里描述同一个结构时,措辞略有不同:它把 Details 解释为「specifics of the change (old and new values)」,也就是变更前后的值都在里面。API 参考那张表只写了 details 是「变更的具体内容」,没展开说结构。想按 details 的内部字段做程序化解析的话,两份文档都没给出具体 schema,得自己打一条真实响应看。

actor 这个字段设计得挺实在:它不区分「人」和「Agent」,统一是「执行者」。在一个人和 Agent 混合操作同一批任务的系统里,这样反而省事——你不用先猜是人改的还是 Agent 改的,看 actor 就完了。

Web 端和 API 各能按什么过滤

这两条路径的过滤能力并不相同,这是最容易踩的地方。

Web 端的 Activity 区域在侧边栏,展示的是全公司事件的时间序信息流,支持三个维度过滤:

  • Agent
  • 实体类型(issue、agent、approval)
  • 时间范围

API 是这个接口:

GET /api/companies/{companyId}/activity

查询参数只有三个:

参数作用
agentId按执行者 Agent 过滤
entityType按实体类型过滤(issueagentapproval
entityId过滤到某个具体实体

对比一下就能看出差异:API 多了 entityId(可以精确锁定单个任务或单个 Agent 的全部历史),但文档里没有列出时间范围参数,而 Web 端有时间范围过滤。所以「查昨天 14:00 到 15:00 之间发生了什么」这类需求,按文档写明的参数,接口层没有直接对应项;反过来,「把某一条 issue 从头到尾的所有事件拉出来」这种,只有 API 干得了。

调接口前还得先解决鉴权,那部分不在这两份文档里,走的是 Paperclip 的通用 API 总览与鉴权那一套。

官方给的四步排查法

board operator 指南里有一段专门讲「Using Activity for Debugging」,出问题时按这个顺序走:

  1. 先定位到出问题的 Agent 或任务;
  2. 把活动日志过滤到这个实体上;
  3. 沿时间线一路走下来,还原发生了什么;
  4. 重点检查三类异常:漏掉的状态更新(missed status updates)、失败的 checkout(failed checkouts)、意料之外的指派(unexpected assignments)

第四步那三项值得单独说,因为它对应的是三种不同的故障形态。

「漏掉的状态更新」通常意味着 Agent 那一侧的流程没走完——活儿可能做了,但状态没回写,看板上就一直挂着。「失败的 checkout」指向的是执行环节没能把工作区拿起来。「意料之外的指派」则是编排层的问题,任务被分给了不该拿它的角色。

三类里前两类经常和 Agent 侧的运行状态纠缠在一起。如果日志显示某个 Agent 在某个时间点之后就再没产生过任何记录,那问题多半不在日志能覆盖的范围内,得转去查心跳与看门狗那条线——活动日志只记「发生了的写操作」,一个彻底不动的 Agent,恰恰是靠「什么都没记」这个空白暴露出来的。

这也是用活动日志的一个心法:既看有什么,也看该有而没有的。一条正常流转的任务,从创建到指派到状态跳变到评论到关闭,时间线上是密的;哪一段突然稀疏了,问题就在那一段的起点。

用起来的几个实际建议

按实体而不是按时间查。全公司的信息流在 Agent 多起来之后噪声很大,与其滚屏幕,不如先拿到出问题那条 issue 的 ID,用 entityId 直接锁死。

先确认动作是否发生,再讨论动作是否正确。很多争论其实卡在第一层——「这个状态到底有没有被改过」。日志是 append-only 的,它给的是确定性答案,不用再靠回忆。

actor 当成第一分类维度。同一类异常,如果 actor 全是同一个 Agent,那是这个 Agent 的行为问题;如果 actor 散在多个身上,那更可能是编排规则或配置的问题。

这套机制不解决什么

得把边界说清楚,免得你指望它干它不干的事。

它只记 mutation,不记读操作。 「哪个 Agent 看过哪份资料」这类访问审计需求,不在活动日志的覆盖范围内——文档明确说的是「所有 mutation」,读取不在其中。

日志保留多久,官方文档没说明。 两份文档都没提留存期、归档策略或容量上限。做长期合规审计前,这一条得单独确认。

分页与排序参数,文档没列。 API 只给了三个过滤参数,返回结果的分页方式、默认条数、排序方向都未说明,写脚本拉全量历史前先试探一下实际行为。

entityType 的枚举和被记录的事件类型对不上。 过滤参数里 entityType 只有 issueagentapproval 三个值,但「什么会被记录」的清单里还包括预算变更和公司配置变更。这两类事件挂在哪个 entityType 下、能不能被过滤出来,文档没有交代。真要查预算改动,别假定 entityType=budget 能用,先拉一批不带过滤的记录看看实际取值。

它是事后工具,不是告警。 活动日志本身不主动推送、不设阈值。想在异常发生时被叫醒,得靠别的机制,日志负责的是「发生之后你能查得清」。

把这几条限制放在心上,活动日志的定位就很清楚了:它是 Paperclip 里最靠得住的一份事实底稿,不可修改、覆盖所有写操作。它不会告诉你该怎么办,但它能保证——不管这家 AI 公司里发生过什么,都留得下痕迹。

延伸阅读


本文依据 Paperclip 官方仓库(github.com/paperclipai/paperclip,MIT 协议)的 docs/ 用户文档 与 doc/ 下的规范、运维与连接器手册整理,核对日 2026-08-17。 我们没有部署或运行过 Paperclip,因此不涉及界面外观与操作手感; 部分规范文档描述的是目标架构而非当前实现,文中已就地标注,不构成对实际行为的保证。 请以仓库最新内容为准。

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