tencentcloud-agentobs-sdk-openai-agent
面向 OpenAI Agents SDK 的可观测性 SDK:自动拦截 Agents SDK 的 trace/span 生命周期回调,转换为符合腾讯云 CLS GenAI Trace 规范的 OTel span,并直接上传到 腾讯云 CLS。
- 零侵入:一行
instrument()完成埋点,无需改动业务代码 - per-turn trace 模型:每次
Runner.run()生成一条完整链路,层级为entry → agent → step → chat/tool - 并发安全:父子关系读
span.parent_id,天然支持并行工具调用与as_tool子 agent 嵌套 - 合规可控:三档内容捕获策略(
full/truncate/off),支持强合规场景下完全不记录对话内容 - 完整指标:token 用量、TTFT(首 token 延迟)、finish_reason、工具错误分类
安装
pip install tencentcloud-agentobs-sdk-openai-agent
运行时依赖会一并安装,其中关键的两项:
openai-agents >= 0.2.0—— 被埋点的目标 SDKtencentcloud-cls-sdk-python >= 1.0.8—— CLS 上传客户端
要求 Python >= 3.9。
快速开始
一行 setup() 完成全部初始化:
import os
from tencentcloud_agentobs_sdk_openai_agent import setup, CLSConfig
# ── 1. 配置 OpenAI(由 Agents SDK 使用,不属于本 SDK 的配置)──
# 最简方式:设置环境变量,openai 包会自动读取
os.environ["OPENAI_API_KEY"] = "sk-xxxx"
# 如需自定义 base_url(网关/代理/兼容接口/Azure)、organization、超时等,
# 改用自定义客户端交给 Agents SDK:
# from openai import AsyncOpenAI
# from agents import set_default_openai_client
# set_default_openai_client(AsyncOpenAI(
# api_key="sk-xxxx",
# base_url="https://your-gateway/v1",
# organization="org-xxxx", # 可选
# timeout=30, # 可选
# ))
# ── 2. 启用 CLS 可观测性(必须在跑 agent 之前调用)──
# 方式一:全部走环境变量(先 export CLS_ENDPOINT / CLS_TOPIC_ID / CLS_SECRET_ID / CLS_SECRET_KEY)
setup()
# 方式二:用 CLSConfig 显式提供配置(未提供的字段仍回落到环境变量)
setup(CLSConfig(
endpoint="ap-guangzhou.cls.tencentcloudapi.com",
topic_id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
secret_id="your_secret_id",
secret_key="your_secret_key",
service_name="my-agent-app",
))
# ── 3. 之后照常使用 OpenAI Agents SDK 即可 ──
from agents import Agent, Runner
agent = Agent(
name="math_tutor",
instructions="You are a helpful math tutor.",
model="gpt-4o", # 指定模型;不写则用 Agents SDK 默认模型
)
result = Runner.run_sync(agent, "What is 12 * 8?")
print(result.final_output)
setup() 封装了创建 TracerProvider、挂载 CLSCloudExporter、注册埋点等全部步骤,并返回所用的 TracerProvider(需要继续挂载其他 processor 时可用)。
OpenAI API Key 由 OpenAI Agents SDK 管理,不属于本 SDK 的配置。 本 SDK 只负责可观测性埋点与 CLS 上传,从不读取 OpenAI 密钥;调用 LLM 所需的 key、base_url 等都交给 Agents SDK /
openai包处理,与setup()相互独立。具体可配置项与函数签名以 OpenAI Agents SDK 官方文档 为准。
CLSConfig.replace_existing_processors(默认False)控制埋点注册方式:
False:追加到 Agents SDK 已有的 trace processor 列表,与其他 processor 共存True:替换所有已有 processor(含 OpenAI 默认的),只保留本 SDK
配置
配置来源共两种,优先级从高到低:
CLSConfig显式传值 ——CLSConfig(topic_id="xxx", ...)- 系统环境变量 ——
export CLS_ENDPOINT=...
构造 CLSConfig 时,未显式提供(保持 None)的字段会自动回落到对应环境变量,再回落到内置默认值。因此 CLSConfig() 等价于「全部走环境变量」,而 CLSConfig(topic_id="xxx") 表示「topic_id 用显式值,其余走环境变量」。
环境变量示例
export CLS_ENDPOINT=ap-guangzhou.cls.tencentcloudapi.com
export CLS_TOPIC_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
export CLS_SECRET_ID=your_secret_id
export CLS_SECRET_KEY=your_secret_key
export CLS_SERVICE_NAME=my-agent-app
配置项清单
必填(缺一即在初始化时抛错)
| 环境变量 | CLSConfig 字段 | 说明 |
|---|---|---|
CLS_ENDPOINT |
endpoint |
CLS 接入地址(无 https:// 前缀时自动补全) |
CLS_TOPIC_ID |
topic_id |
CLS 日志主题 ID |
CLS_SECRET_ID |
secret_id |
腾讯云访问密钥 ID |
CLS_SECRET_KEY |
secret_key |
腾讯云访问密钥 Key |
可选
| 环境变量 | CLSConfig 字段 | 默认值 | 说明 |
|---|---|---|---|
CLS_SERVICE_NAME |
service_name |
openai-agents-app |
服务名,写入 span 的 service.name / gen_ai.agent.type,用于在 CLS 按应用维度筛选 |
CLS_HOST_NAME |
host_name |
本机 hostname | 主机名,写入 resource 属性 |
CLS_SOURCE |
source |
本机 IP | 日志来源标识;取不到 IP 时回落到 hostname |
CLS_BATCH_SIZE |
batch_size |
32 |
buffer 攒够多少条 span 触发一次上传 |
CLS_DEBUG |
debug |
false |
开启后日志级别降为 DEBUG,打印详细上传过程 |
CLS_LOCAL_DUMP |
local_dump |
false |
开启后每批 span 上传前先以 JSON Lines 追加落盘(旁路,失败不影响上传) |
CLS_LOCAL_DUMP_FILE |
local_dump_file |
cls_spans.jsonl |
本地落盘文件路径 |
| — | replace_existing_processors |
False |
埋点注册方式:True 替换所有已有 processor,False 追加 |
布尔类变量(CLS_DEBUG / CLS_LOCAL_DUMP)接受 1 / true / yes(大小写不敏感)为真。
内容捕获相关
| 环境变量 | CLSConfig 字段 | 默认值 | 说明 |
|---|---|---|---|
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT |
content_mode |
truncate |
内容捕获档位,见下节 |
CLS_CONTENT_MAX_LENGTH |
content_max_length |
8192 |
单个文本字段的截断阈值(字符数) |
CLS_CONTENT_TOTAL_MAX_LENGTH |
content_total_max_length |
1048576 |
单个 span 属性的总量兜底阈值(字符数) |
日志相关
SDK 会为自身 logger 配置文件输出,无需额外配置即可看到链路日志(使用 RotatingFileHandler 自动轮转,不会写满磁盘)。这几项属于 SDK 自身 logging 的引导配置,只能通过环境变量设置,不在 CLSConfig 中。
| 环境变量 | 默认值 | 说明 |
|---|---|---|
CLS_SDK_LOG_FILE |
cls_sdk.log |
SDK 日志文件路径 |
CLS_SDK_LOG_LEVEL |
INFO |
日志级别 |
CLS_SDK_LOG_MAX_BYTES |
10485760(10 MB) |
单个日志文件大小上限 |
CLS_SDK_LOG_BACKUP_COUNT |
3 |
日志轮转保留的备份数 |
内容捕获档位
通过 OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT 控制是否记录对话内容(input/output messages、工具入参与结果),三档语义:
| 档位 | 行为 | 适用场景 |
|---|---|---|
full |
完整记录对话内容,不截断 | 本地开发调试 |
truncate(默认) |
记录内容,但对超长字段截断并打标记 | 生产环境 |
off |
完全不记录对话内容,仅保留 token 数、耗时、finish_reason 等指标 | 强合规场景 |
取值兼容性:沿用 OTel GenAI semconv 的标准变量名,并兼容其历史布尔取值,便于已配置过其他 GenAI 埋点的用户无缝切换:
full档也接受:true/1/yes/all/span/span_onlyoff档也接受:false/0/no/none/no_content
截断机制(truncate 档)为两层设计:
- 第一层(逐字段截断):对每个文本字段单独限长(默认 8192 字符),JSON 结构完整保留,超长部分剪短并追加
...[truncated 原长->新长]标记,CLS 查询端仍可用JSON_EXTRACT提取字段。 - 第二层(总量兜底):消息条数极多时,逐字段截断后总量仍可能超标(默认 1 MB),此层为最后防线,正常不触发。
发生截断时,对应 span 会额外写入 {属性名}.truncated=true 与 {属性名}.original_size 两个属性,便于区分「原文本就短」与「内容被截断了」。
Span 层级结构
每次 Runner.run() 生成一条 trace,层级如下:
entry (SpanKind.SERVER,每轮一个根)
└── agent (SpanKind.INTERNAL,当前执行的 agent)
└── step (SpanKind.INTERNAL,合成的 ReAct 轮次)
├── chat (SpanKind.CLIENT,一次 LLM 调用)
└── tool (SpanKind.CLIENT,一次工具调用)
└── agent [subagent] (通过 as_tool 触发的子 agent)
各层级说明:
- entry —— 本轮对话的根节点,携带
session_id/turn_id - agent —— 一个 Agent 的执行区间,汇总该 agent 的 token 用量、LLM 调用次数、工具调用次数
- step —— 一个 ReAct 轮次(LLM 推理 →(可选)工具调用),由本 SDK 合成(Agents SDK 本身不产生 step span)
- chat —— 一次 LLM API 调用,记录 model、input/output messages、token 用量、finish_reason、TTFT
- tool —— 一次工具/函数调用,记录工具名、入参、结果、错误分类
父子关系的唯一来源是
span.parent_id,SDK 不维护「当前活跃 agent」这类全局状态,因此并行工具调用、as_tool嵌套子 agent 都能正确归位,互不干扰。
采集的关键指标
| 属性 | 所在 span | 说明 |
|---|---|---|
gen_ai.usage.input_tokens / output_tokens |
chat / agent | token 用量(chat 单次;agent 为累计) |
gen_ai.response.time_to_first_token_ms |
chat | TTFT,首 token 延迟(流式与非流式均采集) |
gen_ai.response.finish_reasons |
chat | 归一化后的 finish_reason(stop / length / tool_calls / content_filter / error) |
gen_ai.response.model / gen_ai.request.model |
chat | 模型名 |
gen_ai.agent.message_count / tool_call_count |
agent | 该 agent 的 LLM / 工具调用次数 |
gen_ai.tool.error.type / error.message |
tool | 工具错误分类(timeout / rate_limit / auth_error / connection_error / not_found / validation_error 等) |
错误会自动冒泡到父级 step 和 agent:chat/tool 失败时,上层 span 也会被置为 ERROR 状态,保证在 CLS 侧按 agent 维度检索时能命中失败链路。
本地调试
无需上传 CLS 即可核对采集内容,通过 CLSConfig 开启本地落盘:
from tencentcloud_agentobs_sdk_openai_agent import setup, CLSConfig
setup(CLSConfig(local_dump=True, local_dump_file="cls_spans.jsonl", debug=True))
或通过环境变量:
export CLS_LOCAL_DUMP=true
export CLS_DEBUG=true
每批 span 在上传前会以 JSON Lines(一行一条)追加写入本地文件,内容与实际上传 CLS 的完全一致。落盘是旁路能力,写文件失败只记日志,不影响上传主流程。
错误处理与可靠性
- 重试策略:
5xx/ 网络错误的 span 放回 buffer 等待下次 flush;4xx(400/401/403/404/413)直接丢弃(重试无意义) - 背压保护:buffer 超过 10,000 条时丢弃最旧的数据,防止 OOM
- 线程安全:所有 buffer 操作在锁保护下进行
- 兜底关闭:trace 结束或 processor shutdown 时,会兜底关闭所有未正常结束的 span(如 task 被 cancel 的情况),避免 span 泄漏
License
Apache-2.0
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tencentcloud_agentobs_sdk_openai_agent-0.0.1.tar.gz.
File metadata
- Download URL: tencentcloud_agentobs_sdk_openai_agent-0.0.1.tar.gz
- Upload date:
- Size: 52.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ba029f94fe1668dfc6c4259fc77f11dd5c2eccc54d863648c2ac7e4e2720161a
|
|
| MD5 |
e4dc6b60f1e547b3e9f54c605ac56214
|
|
| BLAKE2b-256 |
e56beaf1179a391ebfffdee9fc282e6dab201729098520c90dc30f9123461ec9
|
File details
Details for the file tencentcloud_agentobs_sdk_openai_agent-0.0.1-py3-none-any.whl.
File metadata
- Download URL: tencentcloud_agentobs_sdk_openai_agent-0.0.1-py3-none-any.whl
- Upload date:
- Size: 52.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e998bec6d42e7d7adb9e220fd39f54e1d4ea772ba9615f2c17641a7be5f0fbd5
|
|
| MD5 |
0522953aa347606c584ebea19dd580a3
|
|
| BLAKE2b-256 |
eb71cd50fdf26081ffc94f6916ec3bfa1c984f86bb1c765a1a73aa524c4535c5
|