学习笔记 · Obsidian

SDK 追踪上下文与分布式链路

LangChainLangSmith

最稳妥的接入顺序是:优先原生框架集成,其次 Provider wrapper,再用 <code>traceable</code> 补业务节点;只有 SDK 不可用时才直接调用 REST。所有路径最终都必须维护同一个父子上下文、project 和 flush 生命周期。

一、接入层级

优先级方式适用场景主要风险
1LangChain/LangGraph/Deep Agents 原生 tracing已使用对应框架配置继承和版本差异
2Provider/框架 wrapperOpenAI、Anthropic 等直接 SDK多重 instrument 造成重复 trace
3<code>traceable</code> / <code>@traceable</code>自定义业务、tool、retrieverrun type 和 I/O 语义需自己保证
4<code>trace</code> / RunTree需要手动控制生命周期漏 patch、异常路径、层级错误
5REST APISDK 无法运行的语言/环境同步开销、批量协议、幂等和顺序

二、环境与程序化配置

常用变量:

  • <code>LANGSMITH_TRACING=true</code>:启用全局 tracing。
  • <code>LANGSMITH_API_KEY</code>:密钥。
  • <code>LANGSMITH_ENDPOINT</code>:区域或自托管 API;区域 URL 不要带尾斜杠。
  • <code>LANGSMITH_WORKSPACE_ID</code>:一个 key 关联多 workspace 时消歧。
  • <code>LANGSMITH_PROJECT</code>:默认 project。

无法设置环境变量时,创建显式 Client,并在 tracing context 或 tracer 中注入 client、project 和 enabled。不要把密钥硬编码到源码。

LangSmith 的 RunTree API 有一个容易忽略的特性:显式创建 RunTree 可绕过 <code>LANGSMITH_TRACING</code> 开关。它适合主动 tracing,不适合作为“全局关停”唯一控制点。

三、业务函数的自动追踪

<code>traceable</code> 会自动:

  • 建立 run、记录输入输出和异常。
  • 从当前异步/线程上下文取得父 run。
  • 将内部已 instrument 的 LLM、LangChain 或 tool 嵌套为子 run。
  • 支持 name、run type、tags、metadata、client 和 project。

Generator/async generator 只有在迭代完成、关闭或抛错后才能结束 run;调用函数但不消费生成器不会产生完整 trace。流式服务要覆盖客户端断连和取消路径。

读取当前 span:

  • 用 current run tree/span API 取得 ID、trace ID 或增加 metadata。
  • 读取可能返回空,代码必须允许 tracing 被禁用。
  • 不建议遍历整个 current RunTree 来推导所有子节点;异步子节点可能尚未提交。

四、嵌套与上下文传播

同进程内,traceable 和受支持 wrapper 通常自动继承上下文。跨服务必须:

  1. 从当前 run 生成 tracing headers。
  2. 随业务请求发送。
  3. 下游在 tracing context 中把 headers 设为 parent。
  4. 下游业务节点在该 context 内创建。

传播的是追踪身份,不是认证。下游仍需使用自己的 LangSmith 凭据;不要把上游 API key 放入 tracing headers。

异步队列要把父上下文写入消息 envelope,并定义过期策略。若队列任务可能在父 trace 保留窗口后执行,可改为新 trace,并用业务 correlation ID 关联,避免伪造一棵长期未闭合的树。

五、动态路由到 project 和 workspace

静态路由使用环境变量;动态路由使用 tracing context 或显式 client。

多目的地复制支持:

  • array 形式可表达多个 endpoint/workspace/API key。
  • primary 与 replica 使用确定性 run ID,便于对账。
  • replica 发送失败不影响 primary,也不应阻断业务。
  • Python 可用 OTel、LangSmith 或 hybrid 模式;文档当前说明 hybrid 只支持 Python。

文档中的 object 形式多 endpoint 示例使用了重复 JSON key;标准 JSON 无法保存两个同名 key。生产配置应使用数组形式,不要复制该 object 示例。

六、LangChain

设置环境变量后,Runnable 默认自动 tracing。重要行为:

  • Python 可用 <code>tracing_context</code> 选择性启停;JS/TS 可传 <code>LangChainTracer</code> callback。
  • tags 和 metadata 会从父 Runnable 继承给子 run;直接挂在某一模型实例上的配置只作用于该分支。
  • <code>run_name</code> 只重命名被调用的 Runnable,不自动改内部 LLM run 名。
  • 自定义 root <code>run_id</code> 会成为 trace ID,但当前不能直接给 LLM 对象指定该能力。
  • Python 用 <code>wait_for_all_tracers</code>;JS 用 <code>awaitAllCallbacks</code> 等待提交。
  • JS 非 serverless 可后台发送降低延迟;serverless 应关闭后台回调或显式等待。

LangChain JS 与 traceable 的互操作仍有边界:从 RunnableLambda 取到的 RunTree 不宜修改/遍历,极端并发下 execution order 可能相同,应依赖 start time 和真实层级。

七、LangGraph 与 Deep Agents

LangGraph:

  • 使用 LangChain 模型/工具时,只需原生 tracing 配置。
  • 使用裸 SDK 或自定义函数时,模型用 provider wrapper,工具用 traceable,才能正确嵌套。
  • <code>configurable.thread_id</code> 是图持久化/会话标识的重要来源,但仍应在最终 trace 中验证 thread metadata。

Deep Agents:

  • 基于 LangGraph,设置 LangSmith 环境变量即可自动 tracing;仅做自动 tracing 不要求单独安装 langsmith。
  • 需要选择性 tracing、查询或自定义 metadata 时再安装 SDK。
  • 子 Agent 产生的 run 使用 <code>lc_agent_name</code>,可在 Runs 视图或 SDK filter 中隔离。
  • 一次 invoke 通常包含规划 LLM、tool、子 Agent 和最终响应;不要拆成多个无关 trace。

Claude Agent SDK:

  • Python 使用 <code>configure_claude_agent_sdk</code>,JS/TS 使用 <code>wrapClaudeAgentSDK</code>。
  • 会自动捕获 query、模型交互、tool 与 MCP 操作。
  • 该页没有列出最低版本、脱敏和 flush 细节;生产采用前须以包 release/reference 补齐。

八、Human-in-the-loop 与后台任务

动态 interrupt/resume 适合生产人审:运行在明确节点暂停,收到批准/编辑/拒绝后以同一 checkpoint 恢复。

静态 breakpoint 更适合调试测试,不建议作为生产审批工作流,因为它与代码位置强绑定、状态语义较弱。

后台 run 必须在实际工作完成时结束,而不是在任务入队时结束。建议:

  • 入队节点记录 task ID。
  • worker 通过分布式父上下文创建子 run。
  • 取消、超时、重试和死信都写入明确状态。
  • 重试要有 attempt metadata,避免把多个尝试伪装成一个无错误 run。

九、直接 REST API

简单模式:

  • <code>POST /runs</code> 创建,<code>PATCH /runs/{id}</code> 结束。
  • 子 run 传 <code>parent_run_id</code>;服务端生成 trace ID 和 dotted order。
  • 简单但慢、限额更低,且同步调用会影响业务。

高吞吐模式:

  • <code>POST /runs/multipart</code> 批量 post/patch。
  • 调用方必须生成 UUIDv7、trace ID 和 dotted order。
  • multipart 每个 run 的主体、inputs、outputs、events 分 part。
  • 需要连接池、批次上限、退避重试、幂等 ID、超时和丢弃策略。

官方示例偏教学:直接 requests 调用没有完整超时、重试、响应检查、批量队列和熔断;<code>serialize_run</code> 还会原地移除 inputs/outputs/events。生产实现应优先复用 SDK batching,不能直接照搬。

十、提交与关停

异步 tracing 的底线:

  • CLI/短进程:finally 中等待所有 tracer。
  • serverless:关闭后台发送或调用 SDK 的 pending batches/flush。
  • worker:优雅关停先停止接单,再等待 tracing 队列,最后关闭 exporter。
  • 非关键 tracing 失败通常不应让用户请求失败,但必须有丢弃计数、队列水位和错误日志。