Skip to content
// 0x
Go back
0x1A // 工具设计

为 AI Agent 设计跨运行时会话追踪协议 — track-agent-sessions 的构建过程

为什么需要会话追踪

用 AI Agent 一段时间后,你会遇到一个问题:换了运行环境,Agent 不知道上次聊到哪里。

更具体地说:

需要一层薄薄的抽象,让 Agent 在任何环境下都能回答一个问题:这个项目上次的会话状态是什么?

答案就是 track-agent-sessions

设计:一个确定性的会话索引

核心文件是 .agent-sessions/session-history.json,存放在被追踪的项目根目录下:

{
  "sessions": [
    {
      "id": "20260804-1641-codex",
      "runtime": "codex",
      "native_session_id": "019fcbef-8dcd-7f33-a174-12d...",
      "started": "2026-08-04T16:41:42Z",
      "ended": null,
      "status": "active",
      "focus": "登记验证"
    }
  ],
  "latest_session": "20260804-1641-codex",
  "history_limit": 20
}

每条记录包含运行时标识、原生会话 ID、状态和时间戳。latest_session 指向最近登记的会话,Agent 不需要遍历全表就知道当前焦点在哪里。

生命周期管理

四个核心操作:

开始 → track-agent-sessions start --status active
验证 → track-agent-sessions report
结束 → track-agent-sessions end --native-id <id>
恢复 → track-agent-sessions start  (检测到残留 active → 标记 interrupted + 新开 active)

中断恢复的逻辑:如果索引中已有 active 记录但原生 session ID 不同,说明上次会话未正常结束。此时不覆盖旧记录,而是将其标记为 interrupted,再新建一条 active 记录。两条记录都保留,等人工确认。

有界索引:默认保留最近 20 条记录。超出时移除最旧的终态记录(ended / interrupted),不删除 active 记录,不删除 Agent 原生 transcript。

消费者项目如何接入

Skill 的安装方式是向目标项目注入一段 AGENTS.md 指令:

## Agent session tracking

On the first user instruction of every new agent session:
1. Register this session: track-agent-sessions start --status active
2. Report: current session ID + full history

When user explicitly requests to end:
1. End this session: track-agent-sessions end --native-id <id>

Agent 读取这段指令后自主调用脚本,无需人工每次操作。

消费者项目不直接修改 Skill 源码。源码和消费者副本完全隔离:src/track-agent-sessions/ 是唯一源码,消费者下的 .agents/skills/track-agent-sessions/ 是安装副本。修复必须先在源码完成、跑通测试、再重新安装。

安装验证协议

Skill 需要在不同运行时下行为一致,设计了一套验证协议:

1. 登记验证  → Agent 登记会话,报告 ID + 状态 + 文件路径
2. 结束验证  → Agent 结束同一会话,确认状态变为 ended
3. 跨环境验证 → 在另一个运行环境下重复,确认索引兼容
4. 消费者验证 → 在独立子项目中安装,确认不影响已安装副本

每次验证时 Agent 只报告结果,不修改源代码。如果验证失败,回到源码修改、跑测试、重新安装。

关键设计取舍

为什么不用数据库? 文件系统是 Agent 最自然的操作对象。JSON 文件可读、可 grep、可版本控制(.gitignore),没有额外依赖。

为什么项目级而非全局? 同一 Skill 可以安装在不同项目里,每个项目有独立的会话记录。项目级隔离比全局单例更干净。

为什么限制 20 条? Agent 只需要最近的历史来判断当前状态。完整 transcript 由各运行时自行管理。20 条是”够用且不膨胀”的平衡点。

为什么区分 interrupted 和 ended? 异常中断和正常结束在语义上完全不同。标记为 interrupted 的记录提醒用户:这里可能需要人工确认。

从 Problem 到 Skill

这个 Skill 的诞生路径本身就是 Praxis 工作流的一个实例:

问题: Agent 会话记录缺少原生 ID
    → 调查:Codex 和 opencode 各自有原生 ID 格式
    → 方案:以 runtime + 原生 ID 为唯一标识,JSON 文件做索引
    → 实现:track-agent-sessions skill
    → 验证:Codex 和 opencode 各跑 3 轮安装验收
    → 认知:机器事实源与人类投影分离

一个问题 → 一个可复用 Skill → 一条可复用的认知模型。


Share this post on:

Previous Post
一个需求从聊天到上线 — AI Agent 驱动 Calendly 预约功能的全过程
Next Post
把个人经验编译为 AI Agent 可复用资产 — Praxis 知识库的架构思路