学习笔记 · Obsidian
Run 写入、批量、附件与幂等
Run 是 LangSmith tracing 的基本记录;Trace 由共享 trace_id 的树形 Run 组成,顶层 Run 的 id 应与 trace_id 对齐。写入接口的成功状态是 202 Accepted,表示已接受进入异步 ingest 链路,不等于已可查、已聚合或已持久化所有大字段。
四个写入端点
| 能力 | 方法与路径 | 契约 |
|---|---|---|
| 创建单个 Run | POST /api/v1/runs | JSON runs.Run,202 |
| 更新 Run | PATCH /api/v1/runs/{run_id} | 只传变更字段;未知字段被忽略,202 |
| JSON 批量 | POST /api/v1/runs/batch | post 和/或 patch 数组,202 |
| Multipart 批量 | POST /api/v1/runs/multipart | Run、Feedback、大字段和二进制附件同批 ingest,202 |
它们均接受 API Key、Tenant 上下文或 Bearer 认证。客户端必须从已验证的 workspace 上下文决定 session_id/项目,不能相信浏览器自报的 tenant/project ID。
Run 数据模型
runs.Run 覆盖:
- 标识与树关系:
id、trace_id、parent_run_id、dotted_order; - 归属:
session_id或session_name; - 执行:
name、run_type、start_time、end_time、status、error; - 载荷:
inputs、outputs、events、extra、serialized; - 关联:
reference_example_id、tags、输入/输出附件映射。
run_type 枚为 tool|chain|llm|retriever|embedding|prompt|parser。OpenAPI 对该 ingest schema 没有声明 required 字段,不代表生产端可以不建立不变式:应在 SDK/网关层要求 UUID、项目归属、开始时间及正确的父子链,否则可能得到孤儿 Run、错树或难以补写的费用数据。
JSON batch 和 multipart 的选择
JSON batch 是一个对象,post 和 patch 均为 Run 数组。官方建议数百个 Run 优先批量;但输入/输出很大或带附件时,multipart 更稳定。
Multipart 的 part name 是协议的一部分:
post.<run_id>/patch.<run_id>:Run JSON;post|patch.<run_id>.<field>:将inputs|outputs|events|error|extra|serialized大字段移出主 JSON;feedback.<run_id>:Feedback JSON,必须带trace_id与session_id;attachment.<run_id>.<filename>:与 Run 绑定的二进制文件。
每个 part 都必须有 Content-Type,且有 Content-Length header 或 length 参数。不允许 part 级 Content-Encoding;可在整个请求上使用 gzip 或 zstd。对 part name、run_id 和 filename 做白名单/长度校验,不应把 filename 当存储路径;附件还需内容类型、大小、扫毒、保留期和下载授权。
幂等、顺序与重试
客户端应在首次发送前生成稳定 run_id/trace_id,网络超时后使用同一 ID 重试,不要每次生成新 ID。409 通常是冲突信号,应先查已有 Run;429 和短暂 5xx/网络错误可带 jitter 有界退避;400/403/413/422 需修正请求、授权或拆分载荷,不应盲目重试。
202 后若立即读不到,应以短时有界轮询处理最终一致;父 Run 创建和子 Run 补写要保持 ID/树关系不变。PATCH 声明“未知字段被忽略”,所以调用方必须在本地做 schema 严格校验,否则拼写错误会以“成功但未更新”的形式潜伏。