tencentcloud-agentobs-sdk-openai-agent
Observability SDK for the OpenAI Agents SDK: automatically intercepts Agents SDK trace/span lifecycle callbacks, converts them into OTel spans conforming to the Tencent Cloud CLS GenAI Trace specification, and uploads directly to Tencent Cloud CLS.
- Zero intrusion: one
setup()call completes instrumentation — no changes to business code - Per-turn trace model: each
Runner.run()produces a complete trace withentry → agent → step → chat/toolhierarchy - Concurrency safe: parent-child relationships are derived from
span.parent_id— parallel tool calls andas_toolsub-agent nesting just work - Compliance ready: three content capture modes (
full/truncate/off) for strict data-residency requirements - Full metrics: token usage, TTFT (time to first token), finish_reason, tool error classification
Installation
pip install tencentcloud-agentobs-sdk-openai-agent
Runtime dependencies are installed automatically. The key ones:
openai-agents >= 0.2.0— the target SDK being instrumentedtencentcloud-cls-sdk-python >= 1.0.8— CLS upload client
Requires Python >= 3.9.
Quick Start
A single setup() handles all initialization:
import os
from tencentcloud_agentobs_sdk_openai_agent import setup, CLSConfig
# 1. Configure OpenAI (managed by Agents SDK, not this SDK)
os.environ["OPENAI_API_KEY"] = "sk-xxxx"
# 2. Enable CLS observability (must be called before running any agent)
# Option A: all from environment variables
setup()
# Option B: explicit CLSConfig (unset fields fall back to env vars)
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",
))
# 3. Use the OpenAI Agents SDK as usual
from agents import Agent, Runner
agent = Agent(
name="math_tutor",
instructions="You are a helpful math tutor.",
model="gpt-4o",
)
result = Runner.run_sync(agent, "What is 12 * 8?")
print(result.final_output)
setup() creates a TracerProvider, attaches the CLSCloudExporter, registers
instrumentation, and returns the provider (useful if you need to attach
additional processors).
The OpenAI API Key is managed by the Agents SDK, not by this SDK. This SDK only handles observability instrumentation and CLS upload — it never reads OpenAI credentials. Key, base_url, etc. are handled by the Agents SDK /
openaipackage, independent ofsetup().
CLSConfig.replace_existing_processors(defaultFalse) controls registration behavior:
False: append to the Agents SDK's existing trace processor list, coexisting with othersTrue: replace all existing processors (including OpenAI's default), keeping only this SDK
Configuration
Two sources, in descending priority:
CLSConfigexplicit values —CLSConfig(topic_id="xxx", ...)- Environment variables —
export CLS_ENDPOINT=...
Fields left as None in CLSConfig automatically fall back to the
corresponding environment variable, then to built-in defaults.
Environment Variable Example
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
Configuration Reference
Required (missing any one raises an error at init)
| Env Var | CLSConfig Field | Description |
|---|---|---|
CLS_ENDPOINT |
endpoint |
CLS endpoint (https:// is auto-prepended if missing) |
CLS_TOPIC_ID |
topic_id |
CLS log topic ID |
CLS_SECRET_ID |
secret_id |
Tencent Cloud access key ID |
CLS_SECRET_KEY |
secret_key |
Tencent Cloud access key secret |
Optional
| Env Var | CLSConfig Field | Default | Description |
|---|---|---|---|
CLS_AGENT_TYPE |
agent_type |
openai-agent |
Agent type, written to gen_ai.agent.type, and used as the resource service.name per spec |
CLS_PROVIDER_NAME |
provider_name |
inferred from model | LLM provider, written to gen_ai.provider.name. If unset, inferred from the model prefix (gpt→openai, etc.); set explicitly for Azure/compatible endpoints where inference is unreliable |
CLS_USER_ID |
user_id |
empty | End-user ID, written to gen_ai.user.id on every span for per-user filtering in CLS. Provided by the business layer; left empty if unset |
CLS_HOST_NAME |
host_name |
local hostname | Host name for resource attributes |
CLS_SOURCE |
source |
local IP | Log source identifier; falls back to hostname |
CLS_BATCH_SIZE |
batch_size |
32 |
Spans per upload batch |
CLS_DEBUG |
debug |
false |
Enable DEBUG-level logging with detailed upload info |
CLS_LOCAL_DUMP |
local_dump |
false |
Dump each batch as JSON Lines before upload (sidecar, failure doesn't affect upload) |
CLS_LOCAL_DUMP_FILE |
local_dump_file |
cls_spans.jsonl |
Local dump file path |
| — | replace_existing_processors |
False |
True replaces all existing processors; False appends |
Boolean variables accept 1 / true / yes (case-insensitive).
Content Capture
| Env Var | CLSConfig Field | Default | Description |
|---|---|---|---|
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT |
content_mode |
truncate |
Content capture mode — see below |
CLS_CONTENT_MAX_LENGTH |
content_max_length |
8192 |
Per-field truncation threshold (characters) |
CLS_CONTENT_TOTAL_MAX_LENGTH |
content_total_max_length |
1048576 |
Per-span total attribute size backstop (characters) |
SDK Logging
The SDK configures its own logger with a RotatingFileHandler (auto-rotates,
won't fill the disk). These are bootstrap settings, settable only via
environment variables:
| Env Var | Default | Description |
|---|---|---|
CLS_SDK_LOG_FILE |
cls_sdk.log |
SDK log file path |
CLS_SDK_LOG_LEVEL |
INFO |
Log level |
CLS_SDK_LOG_MAX_BYTES |
10485760 (10 MB) |
Max size per log file |
CLS_SDK_LOG_BACKUP_COUNT |
3 |
Number of rotated backup files |
Content Capture Modes
Controlled by OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT — determines
whether conversation content is recorded (input/output messages, tool
arguments and results):
| Mode | Behavior | Use Case |
|---|---|---|
full |
Record complete content, no truncation | Local debugging |
truncate (default) |
Record content, truncate oversized fields with markers | Production |
off |
No content at all — only token counts, latency, finish_reason | Strict compliance |
Compatibility: uses the standard OTel GenAI semconv variable name and accepts its legacy boolean values:
fullalso accepts:true/1/yes/all/span/span_onlyoffalso accepts:false/0/no/none/no_content
Truncation (truncate mode) is two-layered:
- Layer 1 (per-field): each text field is capped individually (default 8192
chars), JSON structure is preserved, overflow is clipped with a
...[truncated orig→new]marker. CLS queries can stillJSON_EXTRACTfields. - Layer 2 (total backstop): when message count is extreme, per-field truncation may not be enough (default 1 MB cap). This layer is a safety net and rarely triggers.
When truncation occurs, the span gets additional
{attribute}.truncated=true and {attribute}.original_size attributes,
so "originally short" and "was truncated" are distinguishable.
Span Hierarchy
Each Runner.run() produces one trace:
entry (SpanKind.SERVER — one root per turn)
└── agent (SpanKind.INTERNAL — the executing agent)
└── step (SpanKind.INTERNAL — synthesized ReAct round)
├── chat (SpanKind.CLIENT — one LLM call)
└── tool (SpanKind.CLIENT — one tool call)
└── agent [subagent] (triggered via as_tool)
- entry — root of this turn, carries
session_id/turn_id - agent — an Agent's execution span, aggregates token usage and call counts
- step — a ReAct round (LLM reasoning → optional tool call), synthesized by this SDK (the Agents SDK itself does not produce step spans)
- chat — one LLM API call: model, input/output messages, tokens, finish_reason, TTFT
- tool — one tool/function call: name, arguments, result, error classification
Parent-child relationships come solely from
span.parent_id. The SDK maintains no "currently active agent" global state, so parallel tool calls andas_toolnested sub-agents are correctly attributed without interference.
Key Metrics
| Attribute | Span | Description |
|---|---|---|
gen_ai.usage.input_tokens / output_tokens |
chat / agent | Token usage (per-call for chat; cumulative for agent) |
gen_ai.response.time_to_first_token_ms |
chat | TTFT — collected for both streaming and non-streaming |
gen_ai.response.finish_reasons |
chat | Normalized finish reason (stop / length / tool_calls / content_filter / error) |
gen_ai.response.model / gen_ai.request.model |
chat | Model name |
gen_ai.agent.message_count / tool_call_count |
agent | LLM / tool call counts for this agent |
gen_ai.tool.error.type / error.message |
tool | Error classification (timeout / rate_limit / auth_error / connection_error / not_found / validation_error …) |
Errors bubble up automatically: when a chat/tool span fails, parent step
and agent spans are also set to ERROR, ensuring agent-level searches in CLS
hit failed traces.
Local Debugging
Verify collected data without uploading to CLS — enable local dump via CLSConfig:
from tencentcloud_agentobs_sdk_openai_agent import setup, CLSConfig
setup(CLSConfig(local_dump=True, local_dump_file="cls_spans.jsonl", debug=True))
Or via environment variables:
export CLS_LOCAL_DUMP=true
export CLS_DEBUG=true
Each batch is appended as JSON Lines before upload. This is a sidecar capability — file write failures are logged but do not affect uploads.
Error Handling & Reliability
- Retry strategy:
5xx/ network errors return spans to the buffer for the next flush;4xx(400/401/403/404/413) are discarded (retrying won't help) - Backpressure protection: buffer exceeding 10,000 entries drops the oldest, preventing OOM
- Thread safety: all buffer operations are lock-protected
- Fallback close: on trace end or processor shutdown, all unclosed spans (e.g. cancelled tasks) are force-closed to prevent span leaks
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.2.tar.gz.
File metadata
- Download URL: tencentcloud_agentobs_sdk_openai_agent-0.0.2.tar.gz
- Upload date:
- Size: 54.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b74c21e0655ed74cdea11043561c2faec833891792ce73216d520092b7fcebbe
|
|
| MD5 |
8d5930e28565a1a588c5d6af0b4138e4
|
|
| BLAKE2b-256 |
ace1d7588eec285bfb3d7493cd798fa1b300c23416893963702043f6de782587
|
File details
Details for the file tencentcloud_agentobs_sdk_openai_agent-0.0.2-py3-none-any.whl.
File metadata
- Download URL: tencentcloud_agentobs_sdk_openai_agent-0.0.2-py3-none-any.whl
- Upload date:
- Size: 54.6 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 |
e7bbcf6ae1b143a68add8dcfa6267a07f430fe2741c9e2d1d6004a21cfa97f2c
|
|
| MD5 |
2f3a2af42c7fd00203dd952cbc7f2b25
|
|
| BLAKE2b-256 |
78114065cbcc8a4939d2d0aa78cd24f6db5f5146e22f648a1fe7ad6edcb679e1
|