本文面向在自有网络或私有化环境中接入 Agent 运营分析的 Python 用户,覆盖安装、初始化、Trace 与 Span 上报、常用框架集成、多模态、失败留存、验收和故障排查。
本文提供的示例基于bytedance.tea_era 1.1.0+tob.1,支持 Python 3.9 及以上版本。
在正式开始接入之前,您需要获取以下参数信息。
https://gator.volces.com。trace_id 请使用 32 位小写十六进制字符串。Python SDK 只保留一个初始化入口 Config(...),您必须显式提供服务根地址和鉴权信息。
业务线程只负责结束 Span 并非阻塞入队,实际网络请求由 Dispatcher worker 执行。Native、OpenAI、LangChain、LangGraph 和 OTel 最终共用同一投递链路,因此队列、批量、重试、统计、多模态和失败留存语义一致。
统一通过 SDK-only 离线包安装。该包只包含 Agent 运营分析 SDK 自身,不包含任何第三方依赖 wheel;您应在自己的可信制品源和安全治理流程中准备第三方依赖,再把依赖 wheelhouse 与 SDK-only 包一起传入离线环境。
说明
离线附件:本节附件 era-python-sdk-1.1.0+tob.1-sdk-only.zip 适用于 Linux、macOS、Windows 和 Python 3.9 及以上版本。
SDK 包 | License | Notice |
|---|---|---|
内容 | SDK 交付方 | 客户方 |
|---|---|---|
ERA SDK wheel | 提供并校验 | 在目标环境使用 |
直接依赖范围 | 提供 | 根据实际能力选择 profile |
第三方wheel与传递依赖 | 不包含 | 从客户可信源下载、锁定并保存 |
平台和ABI兼容性 | SDK wheel 为 | 确保第三方 wheel 匹配 OS、CPU 和 Python 版本 |
第三方漏洞和许可证 | 不替客户选择版本 | 对最终锁定版本执行漏洞扫描和许可证审查 |
以下为 SDK wheel 元数据中的直接依赖范围。您还需让 pip 或依赖锁定工具解析传递依赖,并对最终完整依赖树进行测试和安全治理。
Profile | 直接依赖范围 | Python | 能力 |
|---|---|---|---|
|
| 3.9+ | Native、Dispatcher、多模态、DeadLetter |
| native + | 3.9+ | OpenAI 兼容模型接口 |
| native + | 3.9+ | OpenTelemetry |
| native + | 3.9+ | LangChain |
| native + | 3.9+ | LangGraph |
| native + OpenAI、LangChain Core、LangGraph上述范围 | 3.9+ | Fornax 兼容路径 |
| native + | 3.11+ | DeepAgents |
| native + OpenAI + OTel + LangChain + LangGraph | 3.9+ | 常用全集,不含 DeepAgents |
联网构建机应与生产离线环境使用相同 OS、CPU 架构和 Python 次版本。不要混用 cp39、cp311、cp312 wheel。
unzip era-python-sdk-1.1.0+tob.1-sdk-only.zip cd era-python-sdk-1.1.0+tob.1-sdk-only # 可改为 native/openai/otel/langchain/langgraph/fornax/deepagents PROFILE=all python -m pip download \ --only-binary=:all: \ --dest ./customer-wheelhouse \ --index-url https://CUSTOMER_PYPI/simple \ -r requirements/$PROFILE.txt
--only-binary=:all: 会在任一依赖没有目标平台 wheel 时失败,避免离线环境临时编译源码。若您使用 pip-tools、uv、Poetry 或内部治理平台,应基于相同 profile 生成完整锁定文件并保留 hash。
在干净的同构环境预验证:
python -m venv ./verify-env source ./verify-env/bin/activate python -m pip install --no-index \ --find-links ./customer-wheelhouse \ -r requirements/$PROFILE.txt python -m pip check
Windows 激活环境:
python -m venv .\verify-env .\verify-env\Scripts\Activate.ps1
python -m venv ./.venv source ./.venv/bin/activate python -m pip install --no-index \ --find-links ../customer-wheelhouse \ -r requirements/all.txt python -m pip check
仅使用 Native 时替换为 native.txt;其他能力使用对应 profile。DeepAgents 必须使用 Python 3.11 及以上。
推荐安装器先检查 profile 直接依赖和版本范围,再以 --no-deps 安装 SDK,最后执行版本检查和 pip check:
./install.sh --profile all
powershell -ExecutionPolicy Bypass -File .\install.ps1 --profile all
手动安装:
python -m pip install --no-deps \ ./bytedance_tea_era-1.1.0+tob.1-py3-none-any.whl python -m pip check python -c "from bytedance import tea_era as era; print(era.__version__)"
预期版本为 1.1.0+tob.1。
python -c "from bytedance import tea_era as era; print(era.__version__)" python -c "import openai; print('openai ok')" python -c "import opentelemetry.sdk; import bytedance.tea_era.otel; print('otel ok')" python -c "import langchain_core, langgraph; print('frameworks ok')"
随后使用测试 Workspace 和 32 位 hex trace_id运行本文最小可运行示例,确认 flush.ok=True、failed=0、pending=0、close.ok=True,并在产品页面核对 Span 数量和父子关系。
问题或报错 | 解决方案 |
|---|---|
缺少依赖 | 安装器会显示缺少的直接依赖和范围。回到联网构建机重新生成您的 wheelhouse,不要让离线机器连接公网补包。 |
No matching distribution found | 通常是 wheelhouse 与目标 OS、CPU 或 Python 次版本不匹配,或某依赖没有二进制wheel。不要使用 |
| 说明您选择的第三方版本或传递依赖不一致。SDK-only 安装器不会自动修改环境,应回到依赖锁定阶段解决。 |
安全扫描结果不同 | SDK-only 包不携带第三方依赖,最终漏洞结果取决于您的实际锁定版本。您应对完整环境生成 SBOM,并在每次升级后重新扫描。 |
from bytedance import tea_era as era client = era.Client(era.Config( workspace_id="CUSTOMER_WORKSPACE_ID", agent_id="CUSTOMER_AGENT_ID", base_url="https://CUSTOMER_ERA_HOST", api_token="CUSTOMER_API_TOKEN", auth_mode=era.AuthMode.BEARER, service_name="customer-agent-service", ))
参数 | 是否必填 | 说明 |
|---|---|---|
| 是 | Agent 运营分析中对应的空间 ID。 说明 进入 Agent 运营分析 > 空间管理 > 数据接入,在指定 Agent 内获取空间 ID(Workspace ID)、Agent ID 和 API Token。 |
| 是 | Agent 运营分析中对应的 Agent ID。 |
| 是 | HTTPS 服务根地址。不要填写完整 ingest path、query、fragment 或 userinfo。
|
| Bearer 模式必填 | SDK 发送 |
| 否 | 用于多服务检索和运行时标签。 |
推荐通过环境变量注入:
export ERA_WORKSPACE_ID=CUSTOMER_WORKSPACE_ID export ERA_AGENT_ID=CUSTOMER_AGENT_ID export ERA_BASE_URL=https://CUSTOMER_ERA_HOST export ERA_API_TOKEN=CUSTOMER_API_TOKEN export ERA_AUTH_MODE=bearer
from bytedance import tea_era as era client = era.Client(era.config_from_env())
私有 CA、代理和环境代理继承可分别使用 ERA_CA_BUNDLE、ERA_PROXY 和 ERA_TRUST_ENV。生产环境不要关闭 TLS 校验。若传入自定义 httpx.Client,TLS、代理和 Client 关闭责任归调用方,不能再同时配置 SDK 管理的 CA/代理参数。
字段 | 含义 | 建议 |
|---|---|---|
| 业务用户标识。 | 使用稳定、非敏感的内部用户 ID。 |
| 一段连续会话;同一会话可包含多个 Trace。 | 使用 conversation/session/ticket ID,同一会话保持不变。 |
| 一次完整请求或 Agent run。 | 使用 |
| Trace 内的一个操作步骤。 | 由 SDK 生成,不需要业务侧指定。 |
| 可选业务消息 ID。 | 若业务原始 ID 不是 32 位 hex,请放这里或自定义 tag,不要直接作为顶层 |
默认 require_trace_config=True。根 Trace 缺少 user_id 或 thread_id 时,SDK 会创建 NoOp Span 并拒绝上报。无会话概念的单次任务可以把 request ID 同时作为 thread_id。
import secrets from bytedance import tea_era as era client = era.Client(era.Config( workspace_id="CUSTOMER_WORKSPACE_ID", agent_id="CUSTOMER_AGENT_ID", base_url="https://CUSTOMER_ERA_HOST", api_token="CUSTOMER_API_TOKEN", )) trace_id = secrets.token_hex(16) trace = client.new_trace(era.TraceConfig( user_id="customer-user-123", thread_id="conversation-456", trace_id=trace_id, message_id="customer-message-789", tags={"biz_scene": "customer_service"}, )) root = trace.agent_span("agent_request").set_input({ "query": "帮我查询订单状态", }) tool = ( trace.tool_span("query_order", parent=root) .set_input({"order_id": "order-123"}) .set_output({"status": "shipped"}) .set_tag("tool_name", "query_order") .finish() ) root.set_output({ "answer": "订单已发货", "tool_span_id": tool.span_id, }).finish() result = client.flush(timeout=30) print(trace_id, result.ok, result.exported, result.failed) close_result = client.close(timeout=30) print(close_result.ok, close_result.closed)
常用 Span 类型包括 agent、prompt、model、tool、retriever、skill、embedding、chain、graph 和 custom。根 Span 推荐使用 agent,其 parent_id 为 0。
业务线程结束 Span 后仅执行冻结和非阻塞入队。Dispatcher 按 item 数和字节数限制队列,worker 批量发送;DNS、连接、代理、超时、连接重置、HTTP 408/429/5xx 可按预算重试,TLS、鉴权、其他4xx、序列化和非法响应等终态错误不重试。flush() 等待调用前 checkpoint 对应的网络投递与死信任务,并返回结构化结果。close() 停止接收新 Span、排空队列并关闭 SDK 自建资源;应在进程退出前调用。主统计始终满足:
accepted = exported + dropped + failed + pending
exported 表示接收端返回成功协议响应,不等同于 Trace 已完成异步落库和产品索引。正式验收还需使用 exact trace_id 到产品页面确认 Span 数量和父子关系。
snapshot = client.snapshot() health = client.health() diagnosis = client.diagnose(smoke=False) print(snapshot.conserved) print(health.status, health.reasons) print(diagnosis)
health() 是只读本地检查,不发网络请求。diagnose(smoke=True) 会额外发送一个无业务载荷的最小 Span,仅在明确需要网络诊断时使用。诊断结果不会输出 API Token、Authorization 或完整业务 payload。
ERA 的规范关键 span_type 支持以下几种:
span_type | 说明 |
|---|---|
| Root 表示 Trace 的开始节点,判断方式是 |
| Prompt 组装、模板渲染、变量填充。 |
| LLM / 多模态模型调用。Trace 中有模型调用时必须上报。 |
| 向量化(Embedding)调用。将文本、图片等输入转换为向量表示时必须上报。 |
| 当 model output 存在 tool call,或业务实际调用工具 / API 时必须上报。 |
| 一次 Agent 运行、子 Agent、任务编排节点。入口 Span 推荐使用 |
| RAG、知识库检索、搜索召回。 |
| 一次 Skill 调用,记录 Skill 的输入参数与最终产物(contents / result)。 |
| 命令行程序(短生命周期进程)执行 |
| 工作流 / 编排流程,把多个步骤(检索、模型、工具等子 Span)串联的"编排容器"节点 |
以下 tag key 在 ERA 中具有固定语义,推荐通过 SDK 提供的方法或约定字段写入,避免用不同类型重复上报:
参数 | 概念 | 规范要求 |
|---|---|---|
space_id | 每个 Span 节点都必须传入,ERA 业务空间标识 | 必须 |
agent_id | 每个 Span 节点都必须传入,ERA agent标识 | 必须 |
thread_id | 一次连续会话,例如:用户和Agent的多轮聊天。 | 必须 |
trace_id | 全局唯一,用于标识一次完整的一问一答。 | 必须 |
user_id | 每个 Span 节点都必须传入,如果用户自己没有在 Span 中上报 user_id,则需要额外传入,用于标识终端用户,如果业务上在TEA中有业务语意的用户id,那么上报时推荐这个值设置为业务语意的用户id,这样在与GUI事件关联时可以关联分析 | 必须 |
span_id | 操作单元 ID。在同一个 Trace 内唯一,用于标识一个具体的操作步骤(如一次模型调用、一次工具调用等)。 | 必须 |
parent_id | 父操作单元 ID。指向当前 Span 的直接上游 Span。通过 | 必须 |
span_type | Span 类型。标识了该操作单元的性质 | 必须 |
span_name | Span 名称。更具体地描述 Span 的功能,例如 | 必须 |
start_time | 开始时间,单位:微秒(μs) | 必须 |
duration | 持续时长,单位:微秒(μs) | 必须 |
status_code | 状态码。标识 Span 的执行结果。通常 | 必须 |
error_type | 错误类型。当 |
|
error | 错误描述。当 | 条件必须 |
input/output | 输入与输出。以 JSON 字符串形式记录了 Span 的输入参数和返回结果。对于 | 必须 |
latency_first_resp | 流式调用模型时,从 Span | 条件必须 |
input_tokens | 输入token数 | 条件必须 |
output_tokens | 输出token数 | 条件必须 |
total_tokens | 总 token 数,通常等于 input_tokens + output_tokens。 | 条件必须 |
agent_version | agent版本号 | 可选 |
ds_agent_id | 子agent_id,主要用于era子agent分析场景 | 可选 |
一条 Trace 由 trace_id 串联,Span 之间通过 span_id / parent_id 表达父子关系。
字段 | 类型 | 规范要求 | 说明 |
|---|---|---|---|
| string | 必须 | 单次请求链路 ID,支持业务自定义。如需要和TEA GUI事件联合分析,trace_id需要和TEA中的对话id保持一致 |
| string | 必须 | 当前 Span ID,由 SDK 生成或业务传入。 |
| string | 必须 | 根 Span 的 |
入口 Span 表示一次用户请求或一次 Agent 运行的入口。推荐使用 span_type = "agent",并设置 parent_id = "0"。
一条 Trace 必须且只能有一个 Root Span;若继承了上游 span_id,当前 Span 不再是 Root Span
下面是入口Span常用的tag定义,您应该组合系统保留tag一起使用。
Key | Desc | 规范要求 |
|---|---|---|
| 父 Span ID,root span的parent_id推荐为0 | 必须 |
| 可以自定义 | 必须 |
| 可以自定义 | 必须 |
| Trace 开始时间 | 必须 |
| Trace 端到端执行耗时 | 条件必须 |
| 本次 Trace 的最终执行状态,0和200为成功,其他为失败 | 必须 |
| 本次请求或 Agent 运行的输入,推荐格式如下 | 条件必须 |
| 本次请求或 Agent 运行的最终输出,推荐格式如下 | 条件必须 |
| 错误类型。当 | 条件必须 |
| 人类可读的错误描述信息,用于排障定位。 | 条件必须 |
| 从 Trace 开始到首次向用户返回有效响应的耗时 | 推荐 |
Key | Desc | Example |
|---|---|---|
| 本次请求或 Agent 运行的输入内容,按顺序排列。 |
|
Key | Desc | Example |
|---|---|---|
| 本次请求或 Agent 运行最终返回给用户的输出内容。 |
|
content
Content 通用约束
Content 是 Root / Agent / Skill / Chain 等边界 Span 复用的多模态内容结构。Model Span 可继续使用 Message 协议,并由适配层映射为 Content;Retriever、Tool、CLI 等已有专用输入输出结构时不强制使用 Content。
媒体与文件优先使用 url 或 reference_id,;鉴权参数、密钥和 PII 必须脱敏。单项截断使用 truncated,整体结果不完整使用 output.partial;已有 arguments / result 等正式字段时,不应在 json Content 中重复上报。
Discriminated Union 规则Content 是以 content_type 为判别字段(discriminator)的 tagged union。校验规则如下:
# | 规则 | 说明 |
|---|---|---|
1 | 判别字段必填 | 每个 Content 项必须包含 |
2 | 载荷字段一一对应 |
|
3 | 互斥 | 同一 Content 项中禁止出现多个载荷字段(如同时有 |
4 | 资源定位二选一 | 媒体类型(image/file/audio/video)的载荷对象中, |
5 | 截断标记 | 任何载荷若经过截断/摘要处理,必须设置 |
通用媒体字段(适用于 image / file / audio / video)
以下字段在所有媒体类型的载荷对象中通用:
字段 | 类型 | 规范要求 | 说明 |
|---|---|---|---|
|
| 条件必须 | 资源的可访问 URL(HTTP/HTTPS)。与 |
|
| 条件必须 | 资源的平台内部引用 ID(如文件系统 ID、OSS key)。与 |
|
| 推荐 | 资源原始文件名 |
|
| 推荐 | MIME 类型(如 |
|
| 条件必须 | 是否经过截断/摘要处理。为 |
Key | Desc | Example |
|---|---|---|
| 当前 Content 项的数据类型,决定该项使用哪个载荷字段。每个 Content 必须且只能包含一种与 content_type 对应的载荷字段。
|
|
| 纯文本内容。 |
|
| 图片内容。
|
|
| 文件内容。
|
|
| 音频内容。 |
|
| 视频内容。 |
|
| 结构化 JSON 内容。 |
|
Prompt Span 表示 Prompt 模板渲染、变量填充或上下文组装。
常用span定义:
Key | Desc | 规范要求 |
|---|---|---|
| prompt | 必须 |
| 可以自定义 | 必须 |
| prompt平台,如fornax、langsmith | 推荐 |
| prompt唯一的key | 推荐 |
| Prompt版本号 | 推荐 |
Key | Desc | Example |
|---|---|---|
| Prompt 模板内容(字符串),可含 {{变量}} 占位符,由 arguments 填充。 |
|
| Prompt 模板中的参数。 |
argument
Key | Desc |
|---|---|
| 参数名 |
| 参数值。 |
| 参数来源(自由字符串,用于标注取值出处)。常见取值:user_input(用户输入)、user_profile(用户画像)、system(系统)、tool(工具返回)等。 |
渲染后的 Prompt 内容:
{ "prompt": "你是一个客服助手,请根据知识库回答用户问题。当前用户等级:vip,用户问题:帮我查订单 order_123 的物流状态" }
Model Span 表示一次模型调用。
常用span定义:
Key | Desc | 规范要求 |
|---|---|---|
| model | 必须 |
| 可以自定义 | 必须 |
| 模型名称 | 推荐 |
| 模型所在的推理平台 / 供应商,例如:火山方舟、OpenAI、内部推理网关等。 | 推荐 |
| 输入token数 | 条件必须 |
| 输出token数 | 条件必须 |
| 本次调用消耗的总 token 数,等于 | 条件必须 |
| 推理消耗token数 | 推荐 |
| 输入中命中 KV Cache(缓存)的 token 数,该部分通常计费更低。 | 推荐 |
| 首包耗时,单位:微秒(μs) | 推荐 |
| 调用参数 | 推荐 |
| 输入。 | 条件必须 |
| 输出。 | 条件必须 |
Key | Desc |
|---|---|
| 回复随机性。 |
| 模型回答的最大 token 数量。 |
| 停止词表。 |
| 核采样(nucleus sampling)阈值,只在累计概率达到 top_p 的候选集中采样,取值范围 0~1。 |
| 模型生成的候选回复数量,对应 |
| 采样时只保留概率最高的 k 个候选 token。 |
| 存在惩罚:对已出现过的 token 施加惩罚,值越大越鼓励模型谈论新话题,取值范围一般为 -2~2。 |
| 频率惩罚:按 token 出现频率施加惩罚,值越大越抑制重复内容,取值范围一般为 -2~2。 |
| 推理强度档位,控制模型思考深度,常见取值 |
Key | Desc | Example |
|---|---|---|
| 消息内容。 |
|
| 可调用的 Tool 列表。 |
|
| 用于控制模型是否可以或必须调用工具,以及调用哪个工具 |
|
tool
tool注册表,用于提供给Model的Input中,作为可以被调用的tool的列表。
Key | Desc |
|---|---|
| tool类型。 |
| function 描述。 |
tool.function
Key | Desc |
|---|---|
| 函数名,不应为空。 |
| Function 描述。 |
| 参数说明。 |
tool_choice
Key | Desc |
|---|---|
| Tool 调用方式。 |
| Function 描述。Type 为 function 时使用。 |
Key | Desc | Example |
|---|---|---|
| 消息对应的角色,不应为空。
|
|
| 消息内容。 |
|
| 模型可观测的推理内容或摘要(可选)。与最终回复 |
|
| 多模态的消息内容。 |
|
| 消息名,可为空。 | - |
| Tool 调用列表,用于 |
|
| Tool Call ID,用于标识某一次需要进行/已经执行的tool call。 | - |
Message 条件约束——字段必填性与互斥规则随 role 变化,上报时须满足以下条件:
条件 | 必填字段 | 说明 |
|---|---|---|
|
| 必须关联触发该工具执行的 Model output 中对应的 |
|
| 三字段缺一不可;下游 Tool Span 依赖 |
| - | 允许并存。若两者均有值,消费端以 |
仅有 | - | 适用于纯文本消息(最常见场景);无需填 |
仅有 | - | 适用于多模态或结构化消息; |
message.parts[*]
Key | Desc |
|---|---|
| 内容类型。
|
| 文本内容。 |
| 图片内容。 |
| 文件内容。 |
| 音频内容。 |
| 视频内容。 |
| 用于校验 Text 块 / 多模态块 / tool_call 完整性的签名标识。类型: string。部分模型(如 Gemini 3)会返回。 |
message.parts[*].image_url
Key | Desc |
|---|---|
| 图片名 |
| 图片文件地址或 base64 编码的图片信息。 |
| 控制如何处理图片
|
message.parts[*].file_url
Key | Desc |
|---|---|
| 附件名 |
| 附件文件地址或 base64 编码的文件信息。 |
| 暂时无用 |
| 后缀名 |
message.parts[*].audio_url
Key | Desc |
|---|---|
| 音频名 |
| 音频文件地址或 base64 编码的音频信息。 |
message.parts[*].video_url
Key | Desc |
|---|---|
| 视频名 |
| 视频文件地址或 base64 编码的视频信息。 |
message.tool_calls[*]
模型指示要调用的tool和调用信息。
Key | Desc |
|---|---|
| Tool 的 ID。 |
| Call 类型。 |
| 调用的 Function 对象,不应为空。 |
| 用于校验 tool_call 完整性的签名标识。类型: string。部分模型(如 Gemini 3)会返回。 |
message.tool_calls[*].function
Key | Desc |
|---|---|
| 被调用的 Function 名,不应为空。 |
| 调用参数,不应为空。 |
Key | Desc | Example |
|---|---|---|
| Choice 列表。 |
|
| responseAPI场景中,用于标识本地请求的id | resp_cdbwb423432cwd3cdxxxx |
choice
Key | Desc |
|---|---|
| 停止原因。
|
| Choice 序号。 |
| 输出内容。 |
当模型决定调用工具时,finish_reason 为 tool_calls,message 内携带 tool_calls:
{ "id": "resp_cdbwb423432cwd3cdxxxx", "choices": [ { "index": 0, "finish_reason": "tool_calls", "message": { "role": "assistant", "content": "", "tool_calls": [ { "id": "call_001", "type": "function", "function": { "name": "get_weather", "arguments": "{\"city\":\"北京\"}" } } ] } } ] }
Embedding Span 表示一次向量化(Embedding)调用,将文本、图片等输入转换为稠密向量表示。常见场景包括:RAG 索引构建时的文档切片向量化、检索时的 query 向量化、语义相似度计算等。
Key | Desc | 规范要求 |
|---|---|---|
|
| 必须 |
| Embedding 操作名,推荐 | 必须 |
| Embedding 模型名称,例如 | 推荐 |
| 模型所在的推理平台 / 供应商,例如:火山方舟、OpenAI、内部推理网关等。 | 推荐 |
| 输入 token 数 | 条件必须 |
| 本次调用消耗的总 token 数 | 条件必须 |
| 输出向量维度,例如 | 推荐 |
| 输入。符合下面 input 定义的 JSON object。协议层为原生 JSON value,仅在传输层按需序列化。 | 条件必须 |
| 输出。符合下面 output 定义的 JSON object。协议层为原生 JSON value,仅在传输层按需序列化。 | 条件必须 |
Embedding 输入:待向量化的内容列表及编码参数。
Key | Desc | 规范要求 |
|---|---|---|
| 待向量化的文本列表,类型 | 条件必须(文本场景) |
| 待向量化的图片 URL 列表,类型 | 条件必须(多模态场景) |
| 本次调用生效的参数,类型 | 推荐 |
{ "texts": [ "如何查询订单物流状态", "退货流程是什么" ], "call_options": { "encoding_format": "float", "dimensions": 1536 } }
Key | Desc |
|---|---|
| 向量编码格式,如 |
| 输出向量维度(部分模型支持动态维度)。类型: |
| 输入类型标识,如 |
Embedding 输出:向量化结果及用量信息。
Key | Desc | 规范要求 |
|---|---|---|
| 向量列表,每个元素包含 | 条件必须 |
| 本次返回的向量数量,类型 | 推荐 |
| token 用量汇总,类型 | 推荐 |
{ "embeddings": [ { "index": 0, "vector_dim": 1536, "vector_preview": [0.0123, -0.0456, 0.0789, "..."] }, { "index": 1, "vector_dim": 1536, "vector_preview": [0.0321, 0.0654, -0.0987, "..."] } ], "count": 2, "usage": { "input_tokens": 24, "total_tokens": 24 } }
注意
output 中 embeddings[*].vector 完整向量通常较大(数千浮点数),实际上报时推荐只记录维度 (vector_dim) 和前几位预览 (vector_preview),避免 Span 体积膨胀。如需完整向量,建议以外部存储引用方式记录。
Tool Span 表示一次工具调用。
Key | Desc | 规范要求 |
|---|---|---|
| tool | 必须 |
| tool的name | 必须 |
| 对应上次Model output返回的tool_call的tool_call_id | 推荐 |
工具入参,通常是模型在 tool_calls.arguments 里给出的参数(JSON object;协议层为原生对象,仅传输层按需序列化为 string):
{ "tool_call_id": "call_001", "name": "get_weather", "arguments": { "city": "北京" } }
工具执行成功的返回:
{ "tool_call_id": "call_001", "city": "北京", "weather": "晴", "temperature": "18~26℃", "humidity": "45%", "updated_at": "2026-07-13T14:00:00+08:00" }
工具执行失败时,推荐在 output 中记录错误信息,并将 Span 的 status_code 置为非 0,同时上报 error_type 和 error
Skill Span 表示一次 Skill(独立能力单元)的调用与执行,Skill 内部产生的模型调用、工具调用应通过子 Span 独立记录,不在 Skill Span 中重复上报。
Key | Desc | 规范要求 |
|---|---|---|
|
| 必须 |
| Skill 名称 | 必须 |
| Skill id | 推荐 |
| Skill 版本,存在版本信息时推荐上报 | 推荐 |
| Skill 来源,枚举: | 推荐 |
| 本次 Skill 被激活的直接原因,枚举: | 推荐 |
| 操作类型,推荐 | 推荐 |
skill.trigger 记录导致本次 Skill 被激活的直接原因(而非来源或执行方式)。多个因素并存时记录最直接的决定来源,例如用户点名后由模型执行,应记 user 而非 model。四个枚举含义如下:
枚举值 | 含义 | 典型场景 | 示例 |
|---|---|---|---|
| 用户明确指定使用某个 Skill | 用户通过命令、名称或 UI 手动选择 Skill | 用户输入「使用 code-review skill 审查代码」 |
| Agent Runtime 根据预定义的确定性规则匹配并激活 Skill | 根据文件类型、任务类型、关键词或路由配置自动匹配,不经过模型决策 | 检测到输入是 PDF,规则自动激活 pdf-processing |
| 模型根据当前任务和 Skill 描述,自主判断需要使用该 Skill | 模型读取可用 Skill 的名称和描述后进行选择 | 模型判断当前任务是代码审查,选择 code-review |
| 平台或 Agent 配置默认、强制激活 Skill | Skill 是内置能力、全局默认能力,或由安全和合规策略强制启用 | 所有请求都自动启用 data-redaction,模型和用户都不能关闭 |
Skill 的边界输入:父节点实际交给 Skill 的任务、材料与执行参数。
Key | Desc | 规范要求 |
|---|---|---|
| 传给 Skill 的任务内容和输入材料,类型 | 推荐 |
| Skill 本次实际生效的结构化参数,类型 | 可选 |
约束:contents 与 arguments 至少存在其一,否则 input 语义不完整。arguments 中的敏感值(密钥、token、PII 等)应脱敏或以引用/哈希代替明文。
{ "contents": [ { "content_type": "text", "text": "请检查这段代码中的安全问题" }, { "content_type": "file", "file": { "url": "https://example.com/main.go", "name": "main.go", "suffix": "go" } } ], "arguments": { "scope": "security", "severity_threshold": "medium" } }
Skill 的边界产出:最终返回给父节点的内容与结构化结果。
Key | Desc | 规范要求 |
|---|---|---|
| Skill 返回的最终内容或产物,类型 | 推荐 |
| Skill 返回的结构化结果,类型 | 可选 |
| 一句话结果摘要,类型 | 可选 |
| 输出是否不完整,类型 | 可选 |
{ "summary": "发现 3 个安全问题,其中 1 个高风险", "contents": [ { "content_type": "text", "text": "发现 3 个安全问题,其中 1 个为高风险问题。" }, { "content_type": "file", "file": { "url": "https://example.com/code-review-report.md", "name": "code-review-report.md", "suffix": "md" } } ], "result": { "issue_count": 3, "high": 1, "medium": 2, "low": 0 }, "partial": false }
Agent Span 表示一次 Agent 运行、子 Agent 调用或任务编排节点。
推荐:
Key | Desc | 规范要求 |
|---|---|---|
|
| 必须 |
| Agent 操作名,推荐 | 必须 |
Agent 输入:本次 Agent 运行的初始请求。规范约束顶层结构(推荐 contents + arguments),不约束业务字段;Agent 内部的模型、工具、子 Agent 调用应下沉到子 Span,不在此重复。
Key | Desc | 规范要求 |
|---|---|---|
| 本次 Agent 运行的初始请求内容,类型 | 推荐 |
| 本次运行实际生效的结构化参数,类型 | 可选 |
{ "contents": [ { "content_type": "text", "text": "北京今天天气怎么样?" } ], "arguments": { "session_id": "sess_8823", "user_level": "vip" } }
Agent 输出:本次 Agent 运行最终返回给上游的结果。summary 供 trace 列表预览,partial 在结果不完整时置 true。
Key | Desc | 规范要求 |
|---|---|---|
| 返回给上游的最终内容或产物,类型 | 推荐 |
| 结构化结果,类型 | 可选 |
| 一句话结果摘要,类型 | 可选 |
| 输出是否不完整,类型 | 可选 |
{ "summary": "已回复北京天气", "contents": [ { "content_type": "text", "text": "北京今天晴,气温 18~26℃。" } ], "result": { "tool_calls_count": 1, "steps": 2 }, "partial": false }
Retriever Span 表示检索、召回或 RAG 上下文构造。
推荐:
Key | Desc | 规范要求 |
|---|---|---|
|
| 必须 |
| 检索操作名,推荐 | 必须 |
| 检索来源类型(如 | 推荐 |
| 检索方式,例如 | 推荐 |
| 应用侧使用的数据源稳定标识 | 推荐 |
| 检索的集合 / 索引名 | 推荐 |
检索请求:检索参数为 JSON object(协议层为原生对象,仅传输层按需序列化为 string)。至少包含 query;top_k、min_score、filter 等参数与 call_options 保持一致,可选补充。
Key | Desc | 规范要求 |
|---|---|---|
| 实际用于检索的查询文本,类型 | 必须 |
| 本次检索生效的调用参数,类型 | 推荐 |
{ "query": "如何查询订单物流状态", "call_options": { "top_k": 3, "min_score": 0.5, "filter": { "op": "must", "field": "lang", "conds": ["zh"] } } }
Key | Desc |
|---|---|
| 检索结果数量。 |
| Score 下限。 |
| VikingDB 的 DSL。 |
{ "top_k": 3, "min_score": 0.5, "filter": { "op": "must", "field": "lang", "conds": ["zh"] }, "search_params": { "dense_weight": 0.7 } }
Key | Desc | Example |
|---|---|---|
| 召回的文档列表。 |
|
| 本次实际返回的文档数量,类型 |
Key | Desc |
|---|---|
| doc id。 |
| 索引名。 |
| 文档内容。 |
| 得分。 |
| 文档扩展信息,类型 |
CLI Span 表示一次命令行程序(短生命周期进程)的执行,用于观测命令调用、参数、耗时、退出码与错误。字段对齐 OpenTelemetry CLI 语义约定(process.*),process.exit.code 非 0 判定为失败。
Key | Desc | 规范要求 |
|---|---|---|
|
| 必须 |
| 命令名,推荐取可执行文件名 | 必须 |
| 可执行文件名 | 推荐 |
| 可执行文件全路径,如 | 可选 |
| 命令参数数组(含命令本身);含敏感值时须脱敏或不采集 | 推荐 |
CLI 输入:本次执行的命令、参数与运行环境,结构化为 JSON object(协议层为原生对象,仅传输层按需序列化为 string)。至少包含 command;args、cwd、关键环境变量等可选补充,敏感值须脱敏。
Key | Desc | 规范要求 |
|---|---|---|
| 可执行文件名或命令,类型 | 推荐 |
| 参数列表,类型 | 推荐 |
| 执行时的工作目录,类型 | 可选 |
| 本次生效的关键环境变量,类型 | 可选 |
{ "command": "git", "args": ["clone", "https://example.com/repo.git", "--depth", "1"], "cwd": "/workspace", "env": { "GIT_TERMINAL_PROMPT": "0" } }
CLI 输出:进程退出码与标准输出/错误摘要,结构化为 JSON object(协议层为原生对象,仅传输层按需序列化为 string)。exit_code 为核心判定字段;stdout / stderr 推荐截断保留摘要,避免超大日志。失败时 exit_code 非 0,并将 Span 的 status_code 置为非 0、记录 error.type。
Key | Desc | 规范要求 |
|---|---|---|
| 进程退出码,类型 | 必须 |
| 标准输出摘要,类型 | 可选 |
| 标准错误摘要,类型 | 可选 |
执行成功:
{ "exit_code": 0, "stdout": "Cloning into 'repo'...\nReceiving objects: 100% (128/128), done." }
chain Span chain Span 表示一次工作流/编排流程的执行,是把多个步骤(检索、模型调用、工具调用等子 Span)串联起来的"编排容器"节点。
Key | Desc | 规范要求 |
|---|---|---|
|
| 必须 |
| 工作流逻辑名(如 | 必须 |
chain 输入:本次流程的初始请求内容与生效参数,结构化为 JSON object(协议层为原生对象,仅传输层按需序列化为 string)。与 Agent/Skill 统一使用 Content[],不使用 Message[]——Chain 是通用工作流编排,不绑定聊天协议语义。
Key | Desc | 规范要求 |
|---|---|---|
| 本次流程的初始请求内容,类型 | 推荐 |
| 本次流程实际生效的结构化参数,类型 | 可选 |
Workflow 输出:流程的最终产物与执行状态,结构化为 JSON object(协议层为原生对象,仅传输层按需序列化为 string)。不复制子 Span 输出;失败、取消、超时或结果被截断时置 partial=true,并将 Span 的 status_code 置为非 0、记录 error.type。与 Agent/Skill 统一使用 Content[]。
Key | Desc | 规范要求 |
|---|---|---|
| 返回给上游的最终内容或产物,类型 | 推荐 |
| 结构化结果,类型 | 可选 |
| 一句话结果摘要,类型 | 可选 |
Trace Envelope 继承规则space_id、agent_id、thread_id、user_id 为每个 Span 必填的上下文字段。上报时有两种合法方式:
下方示例采用方式 1(Envelope 继承),仅在 Trace 顶层声明一次。
拓扑:customer_qa_agent(Agent Root)→ chat gpt-4.1-mini(Model)。Root 只记录边界输入、最终输出和整条链路耗时,不复制 Model Span 的 token。
{ "space_id": "era_space_001", "agent_id": "agent_customer_qa", "thread_id": "thread_8823", "user_id": "user_10086", "trace_id": "9f3b5d7a1c2e4f608192a3b4c5d6xxxx", "spans": [ { "span_id": "1000000000000001", "parent_id": "0", "span_type": "agent", "span_name": "customer_qa_agent", "start_time": 1784217600000000, "duration": 620000, "status_code": 0, "input": { "contents": [ { "content_type": "text", "text": "退款多久到账?" } ] }, "output": { "contents": [ { "content_type": "text", "text": "退款通常在 1~3 个工作日内到账。" } ], "partial": false } }, { "span_id": "2000000000000001", "parent_id": "1000000000000001", "span_type": "model", "span_name": "demoname", "start_time": 1784217600050000, "duration": 540000, "status_code": 0, "model_name": "demoname", "model_platform": "openai", "input_tokens": 42, "output_tokens": 18, "total_tokens": 60, "latency_first_resp": 160000, "call_options": { "temperature": 0.2, "max_tokens": 256 }, "input": { "messages": [ { "role": "user", "content": "退款多久到账?" } ] }, "output": { "choices": [ { "index": 0, "finish_reason": "stop", "message": { "role": "assistant", "content": "退款通常在 1~3 个工作日内到账。" } } ] } } ] }
拓扑:Agent Root 下包含 Retriever、第一次 Model、Tool 和第二次 Model。第一次 Model 通过 finish_reason=tool_calls 产生工具请求;tool_call_id 在 Model 输出、Tool Span 和第二次 Model 输入中保持一致。
order_support_agent [agent, parent_id=0] |
|---|
{ "space_id": "era_space_001", "agent_id": "agent_order_support", "thread_id": "thread_9901", "user_id": "user_20088", "trace_id": "af4c6e8b2d3f507192a4b6c8d0e2xxxx", "spans": [ { "span_id": "a000000000000001", "parent_id": "0", "span_type": "agent", "span_name": "order_support_agent", "start_time": 1784218200000000, "duration": 1150000, "status_code": 0, "input": { "contents": [ { "content_type": "text", "text": "订单 A1024 到哪里了?" } ] }, "output": { "contents": [ { "content_type": "text", "text": "订单 A1024 已发出,预计明天送达。" } ], "partial": false } }, { "span_id": "b000000000000001", "parent_id": "a000000000000001", "span_type": "retriever", "span_name": "search_order_faq", "start_time": 1784218200030000, "duration": 120000, "status_code": 0, "retriever_provider": "knowledge_base", "collection": "order_faq", "input": { "query": "订单物流状态查询", "call_options": { "top_k": 2 } }, "output": { "documents": [ { "id": "faq_1024", "index": "order_faq", "content": "可通过订单编号查询最新物流状态。", "score": 0.92 } ], "returned_count": 1 } }, { "span_id": "c000000000000001", "parent_id": "a000000000000001", "span_type": "model", "span_name": "demoname", "start_time": 1784218200160000, "duration": 280000, "status_code": 0, "model_name": "demoname", "model_platform": "openai", "input_tokens": 68, "output_tokens": 14, "total_tokens": 82, "input": { "messages": [ { "role": "user", "content": "订单 A1024 到哪里了?" } ] }, "output": { "choices": [ { "index": 0, "finish_reason": "tool_calls", "message": { "role": "assistant", "tool_calls": [ { "id": "call_order_01", "type": "function", "function": { "name": "get_order_status", "arguments": "{\"order_id\":\"A1024\"}" } } ] } } ] } }, { "span_id": "d000000000000001", "parent_id": "a000000000000001", "span_type": "tool", "span_name": "get_order_status", "start_time": 1784218200450000, "duration": 180000, "status_code": 0, "tool_call_id": "call_order_01", "input": { "arguments": { "order_id": "A1024" } }, "output": { "result": { "status": "shipped", "eta": "2026-07-17" } } }, { "span_id": "e000000000000001", "parent_id": "a000000000000001", "span_type": "model", "span_name": "chat answer_order_query", "start_time": 1784218200640000, "duration": 470000, "status_code": 0, "model_name": "demoname", "model_platform": "openai", "input_tokens": 86, "output_tokens": 22, "total_tokens": 108, "latency_first_resp": 150000, "input": { "messages": [ { "role": "user", "content": "订单 A1024 到哪里了?" }, { "role": "tool", "tool_call_id": "call_order_01", "content": "{\"status\":\"shipped\",\"eta\":\"2026-07-17\"}" } ] }, "output": { "choices": [ { "index": 0, "finish_reason": "stop", "message": { "role": "assistant", "content": "订单 A1024 已发出,预计明天送达。" } } ] } } ] }
拓扑:Agent Root 激活 code-review Skill;Skill 内部通过 CLI Span 执行 git diff 获取材料,再由 Model Span 完成安全审查。Skill Span 只记录父节点传入的任务和最终返回结果,不复制 CLI stdout 或 Model choices。
coding_assistant [agent, parent_id=0] |
|---|
{ "space_id": "era_space_001", "agent_id": "agent_coding_assistant", "thread_id": "thread_7702", "user_id": "user_30099", "trace_id": "c17e39a25b6d4f708192a4c6e8b0xxxx", "spans": [ { "span_id": "f000000000000001", "parent_id": "0", "span_type": "agent", "span_name": "coding_assistant", "start_time": 1784218800000000, "duration": 1280000, "status_code": 0, "input": { "contents": [ { "content_type": "text", "text": "检查最近一次提交中的安全问题" } ] }, "output": { "contents": [ { "content_type": "text", "text": "发现 1 个高风险问题:日志中可能泄露访问令牌。" } ], "partial": false } }, { "span_id": "f100000000000001", "parent_id": "f000000000000001", "span_type": "skill", "span_name": "code-review", "start_time": 1784218800030000, "duration": 1190000, "status_code": 0, "skill.name": "code-review", "skill.version": "1.3.0", "skill.source": "local", "skill.trigger": "user", "skill.operation": "invoke", "input": { "contents": [ { "content_type": "text", "text": "检查最近一次提交中的安全问题" } ], "arguments": { "scope": "security", "severity_threshold": "medium" } }, "output": { "summary": "发现 1 个高风险问题", "contents": [ { "content_type": "text", "text": "日志语句可能输出明文访问令牌。" } ], "result": { "issue_count": 1, "high": 1, "medium": 0, "low": 0 }, "partial": false } }, { "span_id": "f200000000000001", "parent_id": "f100000000000001", "span_type": "cli", "span_name": "git", "start_time": 1784218800060000, "duration": 140000, "status_code": 0, "process.executable.name": "git", "process.executable.path": "/usr/bin/git", "process.command_args": [ "git", "diff", "--unified=0", "HEAD~1", "HEAD" ], "input": { "command": "git", "args": [ "diff", "--unified=0", "HEAD~1", "HEAD" ], "cwd": "/workspace/order-service" }, "output": { "exit_code": 0, "stdout": "@@ auth.go @@\n+logger.Info(\"token=%s\", accessToken)" } }, { "span_id": "f300000000000001", "parent_id": "f100000000000001", "span_type": "model", "span_name": "chat review_security_diff", "start_time": 1784218800210000, "duration": 920000, "status_code": 0, "model_name": "demoname", "model_platform": "openai", "input_tokens": 176, "output_tokens": 44, "total_tokens": 220, "latency_first_resp": 270000, "input": { "messages": [ { "role": "user", "content": "检查下面的代码差异是否存在安全问题。" }, { "role": "user", "content": "@@ auth.go @@\n+logger.Info(\"token=%s\", accessToken)" } ] }, "output": { "choices": [ { "index": 0, "finish_reason": "stop", "message": { "role": "assistant", "content": "存在高风险:访问令牌可能被写入日志,应移除或脱敏。" } } ] } } ] }
场景 | 入口 | 退出前操作 |
|---|---|---|
Native 手动控制父子关系 |
|
|
普通函数、协程和 stream |
|
|
OpenAI 或兼容接口 |
|
|
LangChain |
| 包装器结束时 flush;进程结束时 close |
LangGraph |
| 包装器结束时 flush;进程结束时 close |
已有 OpenTelemetry |
|
|
import secrets from openai import OpenAI from bytedance import tea_era as era client = era.Client(era.config_from_env()) model_client = client.wrap_openai(OpenAI( api_key="MODEL_API_KEY", base_url="https://MODEL_API_HOST/v1", )) with client.trace_context(era.TraceConfig( user_id="customer-user-123", thread_id="conversation-456", trace_id=secrets.token_hex(16), )): response = model_client.chat.completions.create( model="MODEL_ENDPOINT_OR_NAME", messages=[{"role": "user", "content": "你好"}], ) client.flush(timeout=30) client.close(timeout=30)
Wrapper 是实例代理,不修改全局 OpenAI 模块或原始 client。SDK 会采集模型名、输入输出、token、错误和流式生命周期;模型 API Key 应只交给模型 client,不应放入 Agent 运营分析 tags 或 payload。
默认关闭。Data URI 作为 Model Span input 的普通 payload 随 ingest 上报,不额外调用媒体上传接口。适合小尺寸内容或客户明确允许内联传输的场景。
config = era.Config( workspace_id="CUSTOMER_WORKSPACE_ID", agent_id="CUSTOMER_AGENT_ID", base_url="https://CUSTOMER_ERA_HOST", api_token="CUSTOMER_API_TOKEN", media_config=era.MediaConfig(enabled=False), )
显式开启。SDK 识别标准图片、视频、音频和文件节点,先调用 /v1/loop/files/upload;只有服务端返回 ready 且 size/SHA-256 校验通过后,才删除 Data URI、写入服务端权威 reference_id 和 attachment,并调用 /v1/loop/traces/ingest。
config = era.Config( workspace_id="CUSTOMER_WORKSPACE_ID", agent_id="CUSTOMER_AGENT_ID", base_url="https://CUSTOMER_ERA_HOST", api_token="CUSTOMER_API_TOKEN", media_config=era.MediaConfig( enabled=True, upload_concurrency=2, upload_timeout=120, max_upload_bytes=100 * 1024 * 1024, deduplicate=True, ), )
兼容配置 multimodal_attachment_upload_enabled=True 也会开启共享媒体上传。外部 HTTP(S) URL 保持原样,SDK 不会主动下载。可通过 client.media_stats() 查看 uploaded_files、uploaded_bytes、deduplicated_files 和 failed_uploads。
policy = era.CapturePolicy( redacted_keys={"authorization", "password", "token"}, redacted_paths={"customer.cards.*.number"}, redacted_key_patterns={r"credential$"}, max_payload_bytes=768 * 1024, semantic_projection=True, ) client = era.Client(era.Config( workspace_id="CUSTOMER_WORKSPACE_ID", agent_id="CUSTOMER_AGENT_ID", base_url="https://CUSTOMER_ERA_HOST", api_token="CUSTOMER_API_TOKEN", capture_policy=policy, ))
SDK 默认按常见敏感字段名和值模式脱敏,但您仍需根据自己的数据分类补充规则。不要依赖 SDK 替代业务侧最小化采集。开启完整 State 调试或超大文本上报会扩大数据范围,只建议在经过安全评审后短期启用。
trace_id 发送一条最小 Agent Trace。flush.ok=True、failed=0、pending=0,且 Snapshot 守恒。close(),确认 close.ok=True 和 closed=True。trace_id 查询。parent_id、类型、输入输出、错误和模型字段。多模态开启时还应确认媒体上传发生在 ingest 之前,最终 Model Span 中已移除 Data URI,并能看到 reference/attachment。关闭时应确认没有媒体上传请求。
问题或报错 | 解决方案 |
|---|---|
初始化失败 | 检查 |
TLS 失败 | 检查域名证书、SNI、完整证书链、私有 CA 和代理。不要使用 |
| 先确认使用的是 32 位小写 hex |
短进程退出后丢数据 | 退出前调用 |
队列压力或丢弃 | 检查 |
HTTP 错误 | 401/403 通常是 Agent token、Workspace/Agent 映射或权限问题;429/5xx 会按策略重试;其他 4xx 通常不会重试。不要在日志中打印完整响应正文或 Authorization。 |
client = era.Client(era.Config( workspace_id="CUSTOMER_WORKSPACE_ID", agent_id="CUSTOMER_AGENT_ID", base_url="https://CUSTOMER_ERA_HOST", api_token="CUSTOMER_API_TOKEN", dead_letter_config=era.DeadLetterConfig( directory="./era-dead-letter", max_file_bytes=512 * 1024 * 1024, queue_length=1024, ), ))
目录为空时死信完全关闭,不创建线程或文件。启用后,每个 Client/进程写独立的 era-failed-spans-PID-INSTANCE.ndjson。网络重试耗尽、不可重试终态、队列溢出和已创建 Span 的序列化失败可以留存;采样过滤、SDK disabled 和创建前身份校验拒绝不会留存。
死信写入是独立有界队列,不阻塞业务线程。落盘成功不代表远端上报成功,原 Span 仍计为 failed 或 dropped。SDK不提供重放、轮转、压缩、加密、自动清理或目录总量限制;您需要自行配置磁盘配额、告警、保留周期和处置流程。即使 SDK 会移除鉴权信息和媒体字节,文件仍可能包含业务 input/output,应按敏感数据管理。
SDK 不承诺 exactly-once,不提供默认磁盘 spool、自动重放、多目标原子双写或内置告警平台。Idempotency-Key 和稳定 Trace/Span ID 用于降低模糊重试风险,但您仍应按至少一次投递语义设计业务监控。死信文件只用于留存和审计,不能视为远端成功。
当 SDK 返回成功但产品页面最终不可见时,请保留 SDK 版本、发生时间、Workspace ID、Agent ID、exact trace_id、Snapshot/FlushResult、request ID/logid(若有)及脱敏后的网络错误类型,再联系火山引擎技术支持团队。不要提供 API Token、Authorization、完整业务 payload 或媒体字节。