适用版本:ChengOS v0.1.0+ | 最后核对:2026-08-12 | 来源:
crates/cheng-core/src/domain/execution_archive.rs、crates/cheng-core/src/domain/archive_policy.rs、crates/cheng-nodes/src/nodes/builtin/tools/get_trace.rs、crates/cheng-api/src/rest/handlers/execution/mod.rs
一次执行有三种彼此独立的视图,而本页最重要的一点就是:它们从不混为一谈。
| 视图 | 消费者 | 生命周期 |
|---|---|---|
| 执行归档 | 授权的服务端查询、支持、审计 | 可配置的持久保留 |
| 模型上下文投影 | 下一次 LLM 回合 | 受历史编织预算约束 |
| 界面轨迹投影 | Web 界面与 CLI | 默认是瞬时的 |
把它们当成一样东西,系统最终要么把载荷泄进模型上下文,要么在界面缓存过期时丢掉审计记录。
界面轨迹投影
执行进行时,编辑器与 CLI 依据 WebSocket 事件流渲染它——EXECUTION_START、EXECUTION_PROGRESS、NODE_COMPLETE、NODE_FAILED、流式与工具事件,以及终态的 EXECUTION_COMPLETE / EXECUTION_FAILED / EXECUTION_CANCELLED。见 WebSocket API。
这个投影是瞬时的。为了重连恢复,另有一份有界快照:
GET /executions/:id/trace-snapshot
归属校验刻意跑在存储查找之前,这样响应就无法泄露「别的用户是否存在快照」。运行中途重连的客户端会取这份快照并合并进来,而不是留下空白——见编辑器内嵌对话。
执行日志
GET /executions/:id/logs?offset=&limit=
分页的结构化日志,级别为 DEBUG / INFO / WARN / ERROR。这是针对某一次运行的「按顺序发生了什么」视图。
持久执行归档
归档是一次已完成智能体回合的、带版本的结构化记录:循环运行期间可追加,一旦提交即不可变。
有三条规则支配它:
- 持久化的助手消息始终是权威的公开答案。 归档从不替代它。
ArchiveRef是不透明的。 它绝不编码路径、租户名、文件名或可预测的回合序号。- 原生工具调用的重建只读结构化步骤。 渲染出来的轨迹文本绝不会被反解析成协议消息。
归档是权威的细节来源;紧凑的历史摘要是它的一个投影,反过来则不成立。
引用
ArchiveRef 是 32 位小写十六进制、无连字符的 UUIDv4。从不可信输入解析时会拒绝其他一切形状,正因如此,路径穿越在存储适配器里是结构上不可能的,而不是适配器需要用字符串检查去防守的东西。目录分片使用从该 ID 自身派生的两级前缀(ab/cd),因此目录规模有界,且没有任何调用方可控的数据抵达文件系统。
步骤
每个归档步骤都携带序号、来源的智能体循环迭代、助手动作、工具结果和时间戳。
replay_blocked 是其中微妙的字段:当捕获本身存在歧义时——供应商的调用 ID 重复,或一次调用出现了第二个结果——该步骤仍然会被归档,因为它是审计者必须看到的真实历史;但它绝不会被重放,因为「哪个结果属于哪次调用」没有真实答案。重放校验会完整检查一一配对规则,而不是抽样检查。
查询模式
归档可以按三种宽度读取:
| 模式 | 返回 |
|---|---|
summary(默认) |
计数、工具名、状态、终态——不含参数,不含载荷 |
tool_calls |
逐步的工具名、调用 ID、状态,以及策略允许的参数——不含结果载荷 |
detail |
策略允许的一切,包含有界的结果载荷 |
无法识别的模式字符串会回落到 summary,而不是悄悄放宽暴露面。
调用方选择的是模式,而不是响应大小。 渲染出的投影在服务端被限制在 24000 字符以内,因此模型无法索要无界的转储。
策略:保留与脱敏
归档策略会被盖章到每一份归档上,因此策略变更之后,旧对象依然可解释。
保留级别:
| 级别 | 实际 TTL |
|---|---|
ephemeral |
基准 TTL,且不超过 1 小时 |
standard(默认) |
基准 TTL |
extended |
基准 TTL × 12 |
ephemeral 刻意封顶在基准以下:它的存在是为了支撑瞬时的界面恢复窗口,而不是充当第二个持久存储。级别是持久元数据,由清理任务从目录中读取,而不是从当前配置重新推导——因此调低默认 TTL 不会追溯性地缩短、调高也不会追溯性地延长一份已写入归档所声明的寿命。
脱敏模式:
| 模式 | 归档什么 |
|---|---|
strict |
只有结构化元数据——名称、状态、大小。不存任何载荷字节 |
balanced(默认) |
有界载荷,并对明显敏感的参数键做遮蔽 |
diagnostic |
按配置上限存载荷、不做键遮蔽——仅限短保留期的诊断环境 |
脱敏发生在生产者边界:落盘的归档已经是脱敏后的。因此后来的策略变更绝不可能把先前写入的数据变得更暴露。当脱敏判定的含义发生变化时,策略版本会递增,于是旧归档保留其原本的解释。
工作区级的轨迹保留可单独配置,并对已完成和失败的执行分别设置天数——失败通常值得比成功活得更久。
在工作流内部读取轨迹
tools/get_trace 让 ReAct 智能体按需读取上一回合的记录。模型先在回合元数据里看到一份紧凑摘要;需要细节时才调用这个工具。
[agent/react].tools ──▶ [agent/get_execution_trace]
两条彼此独立的查找路径:
| 输入 | 来源 |
|---|---|
trace_key({session_id}:{turn}) |
旧的进程内会话存储——无限期保留 |
archive_ref |
持久归档,带鉴权与基于策略的裁剪 |
旧会话只有 trace_key;新会话写入 archive_ref;迁移期间二者可能并存,且不会移除或重新解释任何旧键。二选一提供即可。
问「你用了哪些工具」要用 mode: tool_calls——summary 没有调用细节,而 detail 会花掉你多半并不需要的上下文。
重放与重跑
GET /executions/:id/containers/:cid/iterations 列出循环迭代轨迹
POST /executions/:id/containers/:cid/iterations/:idx/rerun 重跑某一次迭代
循环迭代可以逐次追踪、逐次重跑,因此调试一个 100 项的批处理不必把 100 项全部重来。见子流程与批量子流程。
重试失败的执行会产生新的执行 id,而不是改动旧记录:失败的那次运行原样留存,作为证据。
其余接口
GET /executions 列表
GET /executions/active 正在运行的
GET /executions/history 历史
GET /executions/:id 单次执行
GET /executions/archives/:ref 读取归档
POST /executions/:id/cancel|pause|resume|approve

暂无评论内容