Skip to main content

RFC-0001: Storyline Format

FieldValue
StatusAccepted
Formatstoryline
Date2026-07-30
ComponentpChronicle (persisting-pchronicle)
Implementscrates/persisting-pchronicle/src/formats/storyline.rs
RelatedRFC-0002 Events · RFC-0004 ACTF · RFC-0008 ATIF · RFC-0009 OpenAI Messages

摘要

Storyline 是 pChronicle 的枢纽 interchange:以 Harbor ATIF-v1.7 的 Trajectory / Step 折叠语义为基准,加上少量 hub 便利字段(短名 wire、性能顶栏、可选子会话外链)。

捕获侧:HTTP → events 流(可 记录events.lance,也可 触发 handler);handler 经 storyline 做格式转换与落盘。外围格式(agenticmd / openai_msg / atif / actf只与 storyline 互转

Storyline 不是事实源。Canonical 事实仍是 events.lance

events ──┐
agenticmd ┼──► storyline ──► …
openai_msg┤
atif ─────┘

设计原则

  1. ATIF-first:根对象 ≈ Trajectory,turns[]steps[];能 1:1 的字段保持同义。
  2. Hub-only:A→B MUST 经 storyline。
  3. 少叙事:不引入 Capture Call / 相位 / event 回链等运行时读模型;那些留在 events。
  4. Not SoT:回放与审计以 events 为准。

相对 ATIF 仅保留这些增量:

增量说明
短名 wire(src/msg/ts/…)JSON 更短;长名仅作字段概念说明
latency_ms / ttft_ms常从 metrics 提升到 turn 顶栏
tool_calls[].duration_ms常从 tool_call.extra 提升
agent.idATIF 仅有 nameid = name
session RequiredATIF session_id 在 v1.7 可为可选
可选 parent / childrenATIF subagent_trajectories 的外链表达(默认不内嵌整树)
Required schema_version当前只接受 storyline/v1;未知版本 fail closed
可选 origin记录来源格式、来源 schema 与文档身份,不冒充 Storyline 自身版本
unknown_fields仅保存 Storyline 不认识的源格式 key/value,按来源和 JSON Pointer 隔离
可选 /task/started_at/finished_at评测/预算、文档级时间;不升 schema_version
可选 turns[].envturns[].finished_at相对 /task/env 的运行时 delta 与 turn 结束时间
可选 /promptturns[].promptACTF system_prompt / user_content;文档基线 + turn 整段覆盖
可选 tool_calls[].kindtool_calls[].response工具事件类型与执行状态;result 仍是输出体

格式映射的权威边界

本 RFC 只定义 Storyline wire schema。外围格式到 Storyline 的字段映射由对应格式 RFC 负责,设计文档和实现说明不得另行维护一份竞争性映射表:

同源恢复使用 unknown_fields 保留 Storyline 不认识的源字段。跨外围格式转换只保证输出 目标格式能够表达的 Storyline 语义;不能由目标格式表达的外来 residual 使用受控 _storyline envelope 携带。


Wire schema

编码:UTF-8 JSON。根对象 MUST 包含 schema_version: "storyline/v1"sessionagentturns。所有拥有字段的对象都拒绝未声明 key;扩展只能进入显式 extra 或受限 unknown_fields

Wire 短名

JSON 序列化和解码都使用短名;长名仅用于说明字段概念,不作为兼容输入。

短名字段概念位置
runrun_idroot
trajectorytrajectory_idroot
sessionsession_id / story_idroot
childrenchild_session_ids / child_story_idsroot
verversionagent
modelmodel_nameagent / turn
toolstool_definitionsagent
psidparent_session_id / parent_story_idparent
scidspawn_call_idparent
ptidspawn_idparent
relrelationparent
tstimestampturn
srcsourceturn
msgmessageturn
reasonreasoning_contentturn
effortreasoning_effortturn
nllmllm_call_countturn
copiedis_copied_contextturn
tcidtool_call_idtool_calls[]
fnfunction_nametool_calls[]
argsargumentstool_calls[]

保持全名:agent / task / env / llm / result / response / prompt / started_at / finished_at / final_metrics / continued_trajectory_ref / tool_calls / observation / metrics / extra / meta / latency_ms / ttft_ms / duration_ms,以及 id / name / notes / kind / turns / parenttool_calls[].kindturns[].kind 同名不同槽。

根对象

WireTypeStatus
schema_versionstringRequired,固定 storyline/v1
originobjectOptional;来源格式、schema 与文档身份
sessionstringRequired;非空
agentobjectRequired
turnsarrayRequired
runstringOptional;run-scoped identity
trajectorystringOptional;非空
attempt_idstringOptional;源格式 attempt identity
notesstringOptional
taskobjectOptional;env / llm / result,至少一项非空
promptobjectOptional;{system, user} 文档基线;至少一个非空字符串
started_atstring | numberOptional;与 turn ts 同一时间编码
finished_atstring | numberOptional;与 turn ts 同一时间编码
final_metricsanyOptional
continued_trajectory_refstringOptional
extraanyOptional;Storyline 业务扩展
metaanyOptional;文档级元数据
unknown_fieldsobjectOptional;源格式 residual,见下
unknown_key_countsobjectOptional;必须与 unknown_fields 一致
childrenstring[]Optional;子 Storyline identity 外链
parentobjectOptional;父 Storyline 外链

origin

WireTypeStatus
formatstringRequired;非空
schema_versionstringOptional;非空
document_idstringOptional;非空

agent

WireTypeStatus
idstringRequired;非空
namestringOptional
verstringOptional
modelstringOptional
toolsanyOptional
extraanyOptional

parent(可选外链)

对应 ATIF 内嵌 subagent_trajectories 的轻量替代;不是必填叙事层。

WireTypeStatusDescription
psidstringRequiredsession
scidstringOptional父侧触发 id(若有)
ptidintegerOptional父侧 turn id
relstringOptional默认 "spawn"

完整子轨迹 SHOULD 作独立 storyline.json;导出单文件 ATIF 时转换器 MAY 再内嵌。

turns[]

WireTypeStatus
idintegerRequired;文档内唯一
srcstringRequired;非空
msganyRequired
tsstring | numberOptional;RFC3339 或可精确表示为纳秒的 Unix epoch 秒数
modelstringOptional
effortanyOptional
reasonstringOptional
tool_callsarrayOptional
observationanyOptional
metricsanyOptional
nllmintegerOptional
copiedbooleanOptional
extraanyOptional
kindstringOptional;省略时由 srctool_calls 推导;不读取 tool kind
latency_msintegerOptional
ttft_msintegerOptional
envobjectOptional;相对 /task/env 的浅合并 delta,不相对前一 turn
promptobjectOptional;相对文档 /prompt 的整段覆盖,不相对前一 turn
finished_atstring | numberOptional;turn 结束时间

task.envturns[].env 形状相同:name / endpoint / id / event_type / request_id 为可选字符串;state 为开放 JSON object。重建某 turn 的有效 env 时,先取 /task/env 再浅合并该 turn 的 envstate 也浅合并)。落盘保持未合并形态。

task.llm 目前只有可选正整数 ktask.result 承载通用评测:correct / final_answer / ground_truth / status / score / max_score / error / artifacts。ACTF 私货(task_correctcategoryattempts_triedsolved_atretry_countretry_counts)不是强类型 hub 字段;读写旧 Storyline JSON 时这些键进入 task.result extra(与 typed 字段同级 flatten),不得静默丢弃。RFC-0004 的 JSON Pointer 不变,ACTF 转换层从 extra 还原。空字符串、空 object、null 视为缺省。

promptturns[].prompt 形状相同:可选字符串 system / user。有效 prompt 取该 turn 的 /prompt,缺省则用文档 /prompt;turn 一旦出现 /prompt 就整段替换,缺省键视为空字符串,不从文档继承。copied == true 的 turn 不得写 prompt。文档 /prompt 不能是空对象。turn 上唯一允许的双空对象是显式 {"system":"","user":""},用来清空文档基线。

tool_calls[]

WireTypeStatus
tcidstringRequired;全文档唯一且非空
fnstringRequired;非空
argsanyRequired
resultanyOptional
duration_msintegerOptional
extraanyOptional
kindstringOptional;工具事件类型(≠ turn kind);空字符串视为缺省
responseobjectOptional;status 字符串与/或 exit_code 整数

unknown_fieldsunknown_key_counts

unknown_fields 只保存外围格式中无法映射到 Storyline 已知字段的值:

/unknown_fields/sources/{source}/source_document_id = string
/unknown_fields/sources/{source}/fields/{E(P)} = any

P 是源文档中的完整 RFC 6901 JSON Pointer;E(P) 是把整个 P 作为 fields 对象 key 后执行一次 RFC 6901 token 转义。unknown_key_counts 按 source 和规范化 pointer 记录出现次数,必须能由 unknown_fields 确定性重算。已知业务扩展写入 extra,文档级元数据写入 meta,不得混入 unknown_fields


校验(Normative)

MUST 拒绝:缺失或无法识别的 schema_version;空 session / 空 agent.id;重复的 turns[].id;全局重复或空的 tool_calls[].tcid;空 fn;既非 RFC3339 字符串、也非 可精确表示为纳秒的 Unix epoch 秒数的 ts;未声明的 拥有字段;不匹配的 unknown_key_counts

turns 数组顺序具有语义,MUST 原样保留;id 只用于身份和关联,不用于排序。 导出 ATIF 时 step_id = turns[].id;未知 extra 透传。


枢纽 API

into_storyline(format, input) → StorylineDocument
from_storyline(format, story) → serialized
convert(from, to, input) ≡ from_storyline(to, into_storyline(from, input))

events 为 Lance-only:字符串 convert API 对 ChronicleFormat::Events 报错;内存用 events_to_storyline / storyline_to_events


文件与探测

约定
文件名storyline.json / {session}.storyline.json
内容schema_version: "storyline/v1" + session + turns

实现:into_storyline / from_storyline / convert


History

DateNotes
2026-07-30初稿与迭代(hub、短名、去 calls[]、性能字段、session
2026-07-30收敛为 ATIF-first:去掉 Capture Call/Normal 过度叙事;continued_trajectory_ref 对齐 ATIF;parent.scid 可选
2026-08-20固定 storyline/v1,增加 origin 与统一 unknown fields;Lance v2 保留数组顺序、出现语义和原始 observation
2026-08-21Storyline schema 与外围格式映射分离;映射由各格式 RFC 独立负责
2026-08-22增加可选 /task、文档/turn 时间、turn env、tool kind/responseschema_version 仍为 storyline/v1
2026-08-22增加可选文档 /prompt 与 turn /prompt{system, user});msg 仍是助手正文
2026-08-23task.result 强类型只保留通用评测;ACTF 私货进 extra,旧 JSON 同级键不得静默丢弃