交接汇报 只汇报 · 不直接接力 https://ai.njwl.ai/handoff/ · 维护者 ben22

多 agent 协作的规矩:没有 agent 直接接着另一个 agent 干。每个 agent 只做一件事——把进展汇报给人,人做决策、人做接力。所有 agent(Cursor / Codex / Claude / DSH)共用下面这段提示词。

手交卡 · 低成本交接(推荐)

每个项目维护一张「手交卡」.handoff.md(Markdown,人机共读,约 300 token),作为交接的主入口。浏览器可视化入口:/project/(总索引),每项目一张 /project/led/。原始存储(SQLite / transcript)只在卡缺失或过期时才挖。

接手 agent · 只读、便宜

  1. 读总索引 /project/ 找到项目卡;
  2. 读这一张卡(固定字段,~300 token);
  3. 校验新鲜度:卡里 updatedAt / transcriptBytes 与真实文件对不上 → 卡过期,才回退到下面「找对话与原文」的 SQLite / transcript 深挖;
  4. 汇报 / 继续。

干活 agent · 收尾必写卡

完成 / 报错 / 被中止,三种结局都先把进展写回 .handoff.md。只写路径/指针,不写密钥、.env、密码。

机器字段(Markdown 文末嵌一段 JSON)

{
  "schema": "handoff-card/v1",
  "slug": "led",
  "project": "LED 屏数据管理",
  "folder": "D:/…/项目文件夹",
  "composerId": "dd329bdb-…",
  "updatedAt": "2026-09-03T10:18:25+08:00",
  "status": "in_progress",
  "todos": [{"id":"…","content":"…","status":"done|in_progress|pending"}],
  "nowDoing": "…",
  "blocker": "…",
  "next": "…",
  "recentFiles": ["…"],
  "source": {"transcript":"…","transcriptBytes":0,"plan":"…"},
  "agents": {"cursor":"…","codex":null,"claude":null,"dsh":null}
}

status 取值:done / in_progress / pending / error / blocked。首次进入 handoff 的项目做一次「全量索引」生成卡,之后每次收尾增量刷新即可。

进展汇报提示词

把整段复制给任意 agent,它只读、只汇报,不改代码、不部署、不写任何账本。返回一份固定格式的「进展说明」给你。

你是当前项目的进度汇报 agent,向用户汇报。只读:不改代码、不部署、不写任何账本,只返回一份「进展说明」。

【任务】找到指定的项目,按下面顺序收集信息,最后用固定格式返回说明。

0. 先读手交卡(若有)
- 读项目根目录的 .handoff.md(Markdown,人机共读,约 300 token),或读 https://ai.njwl.ai/project/<slug>/ 对应卡片。
- 卡缺失或过期(updatedAt / transcriptBytes 与真实文件对不上)才执行下面 1–3 步深挖。

1. 找对话(Cursor)
- 查 %APPDATA%\Cursor\User\globalStorage\conversation-search.db 的 conversations 表,按标题找 id(SQLite 用 file:...?mode=ro&immutable=1 只读打开,时间戳是毫秒)。
- 查 state.vscdb 的 composerHeaders 表,拿 workspace、最后更新时间、改了哪些文件(totalLinesAdded / filesChangedCount)。

2. 找原文与计划
- 读 ~\.cursor\projects\<hash>\agent-transcripts\<composerId>.jsonl 末尾,看上一回合做了什么、有没有报错(turn_ended / error)。
- 读 ~\.cursor\plans\*.plan.md 的 todos 状态(in_progress / pending)。

3. 找文件与归属
- 按 workspaceIdentifier 找到项目文件夹,列出最近修改的几个文件(= 上次现场)。
- 若有其他 agent(Codex / Claude / DSH)参与,去 ~\.codex、~\.claude、DSH 的 .agents\notes 看一眼对应记录。

【输出】用这个格式返回「进展说明」:
- 项目 / 文件夹:
- 对话 id + 标题 + 最后更新时间:
- 干到哪了(最近改的文件 + todo 状态):
- 卡点 / 报错(若有):
- 下一步(下一个 pending 的 todo):
- 参与过的 agent 与 source 指针:

为什么「只汇报」,不「直接接力」

❌ 直接接力(不推荐)✅ 只汇报 + 人做决策
谁决定下一步agent 自己接着写代码人看汇报后决定
归属agent 互相写、容易暴力写入、来源被抹掉汇报里带 source 指针,谁干的一目了然
风险agent 可能跑偏、直接改上线每一步都要过人,可控
规则就一条:agent 的产出永远是一份「进展说明」交给人,不直接改代码、不直接写回、不直接接力。人看完,再决定让谁、干什么。

参考 · 找到对话与原文

提示词第 1、2 步的展开,人工排查时用。

Cursor 数据目录(Windows)

%APPDATA%\Cursor\User\
├── globalStorage\
│   ├── state.vscdb            ← 主状态库(很大,别整体读)
│   └── conversation-search.db ← 对话搜索索引(小,先查它)
└── workspaceStorage\<workspaceId>\

按标题找对话 id

import sqlite3
con = sqlite3.connect(f"file:{r'%APPDATA%/Cursor/User/globalStorage/conversation-search.db'}?mode=ro&immutable=1", uri=True)
for id, title, updated_at, archived in con.execute(
    "SELECT id, title, updated_at, is_archived FROM conversations WHERE title LIKE ?",
    ("%关键词%",)):
    print(id, title, updated_at, archived)

再查 state.vscdb 的 composerHeaders 表拿元数据(workspaceId / lastUpdatedAt / value 里的 workspaceIdentifier、totalLinesAdded 等)。workspaceIdentifier.uri.external 才是「对话 → 文件夹」的权威映射——标题 ≠ 文件夹名。

完整对话全文

~\.cursor\projects\<项目hash>\agent-transcripts\<composerId>\
├── <composerId>.jsonl   ← 主对话全文
├── subagents\*.jsonl     ← 子 agent
└── ..\..\terminals\*.txt ← shell 输出

计划文件:~\.cursor\plans\<名字>_<hash>.plan.md(YAML 头有 todos + status)。转写末尾 "turn_ended","status":"error" = 上一回合报错(常见:模型用量超限、手动中止)。

参考 · 归属(哪段是谁干的)

汇报里必须带「参与过的 agent + source 指针」,这样人转发时归属不会丢。

agent原文在哪指针写法
Cursor~\.cursor\projects\<hash>\agent-transcripts\<composerId>.jsonlcomposerId
Codex~\.codex\session_index.jsonl(索引)+ state_5.sqlite / thread_history_1.sqlite(正文)threadId
Claude~\.claude\projects\C--Users-ben22\<sessionId>.jsonlsessionId
DSHcheckout 的 .agents\notes\(proposed / implemented)笔记文件路径
归属就藏在路径里:谁干的,去谁的目录找原文。你手里已有 ~\.codex\external_agent_session_imports.json(source_path + sha256 + imported_thread_id + connector_names),可当归属索引用。

参考 · Codex 数据 & 排查踩坑

找 Codex 会话时(尤其下「某 agent 未参与」结论前)务必多数据源交叉,别一次 grep 定论。

Codex 数据到底在哪(Windows)

~\.codex\
├── session_index.jsonl       ← 会话索引(在根目录,不是 sessions\)
├── state_5.sqlite            ← threads 表:标题 / updated_at / tokens_used / cwd / model
└── thread_history_1.sqlite   ← thread_items(正文)、thread_turns(状态/报错)

踩坑清单(实战验证)

  1. 续聊会换 thread_id:Codex 继续旧会话时,新消息会挂到新的 thread_id 上。按 thread_items.created_at_ms 全表倒序查最新,别用固定 thread_id 硬查。
  2. 时间戳单位不一致:thread_turns.started_at / completed_at 是「秒」,thread_items.created_at_ms 是「毫秒」,混用会算出错日期。
  3. 编码坑:jsonl / sqlite 里的中文是 UTF-8,Windows PowerShell 5.1 的 Select-String 默认按 ANSI 读会漏匹配;用 -Encoding UTF8 或直接用 Python。
  4. 关键词带同义/相邻词:别只按项目名(LED / 屏 / 露点),还要带摄像头、相机、选型、型号(CB1 / JM-B-WF001)、协议(RTSP / ONVIF / MQTT)。
  5. 下「未参与」前交叉验证:session_index.jsonl + threads 表 + thread_items + thread_spawn_edges 都过一遍。

人怎么接力

接力只发生在「人 → agent」,从不在 agent 之间直接发生。

  1. 让 A 汇报:粘贴「进展汇报提示词」+ 指定项目,A 返回一份带归属的进展说明。
  2. 人决定:看完说明,决定下一步让谁、干什么。
  3. 把说明转给 B:把 A 的「进展说明」整段作为上下文粘贴给 B,再下达具体指令(如「从 todo ③ 继续」「先修这个报错」)。
  4. B 也先汇报:B 动手前先说一句它准备怎么做,人确认后再让它干(可选,加强人控)。
核心闭环:agent 汇报 → 人决策 → 人把汇报转给下一个 agent → 下一个 agent 再汇报。归属随「进展说明」一路传递,永不丢。

给 AI 的说明

如果你是一个 AI agent,被要求「找某个项目」或「接某个项目」:你的任务永远是汇报,不是直接接力。用上面的提示词跑一遍,把「进展说明」交给人,等他的下一步指令。所有数据都在本机文件系统里,Cursor 的 SQLite 用 file:...?mode=ro&immutable=1 只读打开即可,无需登录、无需联网。
  • 规范 / 组件 / 部署 → /design、/module、/deploy
  • 项目手交卡 → /project/(低成本交接,先读卡)
  • 本页就是交接汇报总入口;旧地址 /read-cursor/ 会自动跳到这里