Skip to content

3. 框架埋点(Instrumentation)


1. 埋点总览

框架在 Agent 执行链路的四个层级创建 Span,并在 Span 结束前 调用对应的 trace_*() 函数写入属性:

层级Span 名称创建位置属性写入函数gen_ai.operation.name
Runnerinvocationrunners.pytrace_runner() / trace_cancellation()run_runner / run_runner_cancelled
Agentagent_run [{name}]agents/_base_agent.pytrace_agent()run_agent
LLMcall_llmagents/core/_llm_processor.pytrace_call_llm()call_llm
Toolexecute_tool {name}agents/core/_tools_processor.pytrace_tool_call()execute_tool

Langfuse 映射层根据 gen_ai.operation.name 决定 Observation 类型(Trace 级 / Generation / Span)。


2. Span 创建方式差异

外层:start_span(不激活 context)

python
# runners.py
span = tracer.start_span("invocation")
try:
    # ... 执行 agent ...
    trace_runner(...)
finally:
    span.end()
python
# agents/_base_agent.py
span = tracer.start_span(f"agent_run [{self.name}]")
try:
    # ... agent 逻辑 ...
    trace_agent(...)
finally:
    span.end()

原因:async generator 在取消时可能跨上下文关闭,使用 start_as_current_span 会触发 OpenTelemetry context detach 错误。

内层:start_as_current_span(激活 context)

python
# agents/core/_llm_processor.py
with tracer.start_as_current_span('call_llm'):
    async for llm_response in self.model.generate_async(...):
        ...
    trace_call_llm(context, event_id, request, final_llm_response, ...)
python
# agents/core/_tools_processor.py
with tracer.start_as_current_span(f"execute_tool {tool.name}", attributes={...}):
    result = await tool.run_async(...)
    trace_tool_call(tool, args, function_response_event, ...)

3. trace_runner() — Runner 级 Trace 属性

调用时机Runner.run_async() 正常结束,在 finally 之前。

写入的关键属性(前缀 trpc.python.agent,可通过 set_trpc_agent_span_name() 修改):

属性含义
gen_ai.operation.namerun_runner
{prefix}.runner.app_name应用名
{prefix}.runner.name[trpc-agent]: {app}/{agent}
{prefix}.runner.user_id用户 ID
{prefix}.runner.session_id会话 ID
{prefix}.runner.input用户输入文本
{prefix}.runner.output最后一次非 streaming Event 的文本输出
{prefix}.state.begin / state.end执行前后 session state JSON

取消场景:捕获 RunCancelledException 时调用 trace_cancellation()gen_ai.operation.namerun_runner_cancelled,并写入 cancellation.reason 等。


4. trace_agent() — Agent 级 Span 属性

调用时机BaseAgent.run_async()finally 块。

属性含义
gen_ai.operation.namerun_agent
{prefix}.agent.nameAgent 名称
{prefix}.agent.input用户 content 文本
{prefix}.agent.output所有非 partial Event 拼接成的 action 字符串
{prefix}.state.begin / state.endAgent 执行前后 state

agent.output_build_action_string_from_events() 从 Event 流构建,包含文本、function call、function response 等。


5. trace_call_llm() — LLM Generation 属性

调用时机_llm_processor.py 中 LLM 流式/非流式调用完成后,只 trace 一次最终完整 response(避免 partial chunk 覆盖属性)。

属性含义
gen_ai.operation.namecall_llm
gen_ai.request.model模型名
gen_ai.usage.input_tokens / output_tokensToken 用量
{prefix}.llm_request序列化后的请求(contents + config,不含 bytes)
{prefix}.llm_responseLlmResponse JSON
{prefix}.instruction.name / .versionInstruction 版本(若使用 RemoteInstructionManager)
{prefix}.stream_function_calls.*流式 function call 聚合(可选)

6. trace_tool_call() — Tool Span 属性

调用时机:Tool 执行完毕,在 execute_tool Span 的 context 内。

属性含义
gen_ai.operation.nameexecute_tool
gen_ai.tool.name / .description / .call.idTool 元信息
{prefix}.tool_call_args调用参数 JSON
{prefix}.tool_response返回结果 JSON

并行 Tool:多个 Tool 并行执行时,合并为一个 execute_tool (merged) Span,调用 trace_merged_tool_calls()


7. 执行时序(单次对话)

Runner.run_async()

├─ start_span("invocation")

├─ Agent.run_async()
│   ├─ start_span("agent_run [weather_agent]")
│   │
│   ├─ LlmProcessor.process()
│   │   └─ with start_as_current_span("call_llm")
│   │       └─ trace_call_llm()          ← Generation 数据
│   │
│   ├─ ToolsProcessor.process()
│   │   └─ with start_as_current_span("execute_tool get_weather")
│   │       └─ trace_tool_call()         ← Tool Span 数据
│   │
│   └─ trace_agent()                     ← Agent Span 属性
│   └─ span.end()

├─ trace_runner()                          ← Trace 级 input/output
└─ span.end()

8. 自定义 Agent 埋点

对于 RemoteA2AAgent、ClaudeAgent 等非标准 LlmAgent,使用 CustomTraceReporter(见 7_custom_trace.md),在 Event 流上手动创建 call_llm / execute_tool Span。

LangGraph Agent 在 agents/utils/_langgraph.py 中有独立的 start_as_current_span + trace_call_llm 逻辑。


9. 用户自定义 Span

官方文档支持在 Tool 或 CustomAgent 中直接使用 OTel + Langfuse 属性:

python
from trpc_agent.telemetry import tracer
from opentelemetry import trace

def my_custom_trace() -> str:
    with tracer.start_as_current_span("my_custom_trace"):
        span = trace.get_current_span()
        span.set_attribute("langfuse.observation.input", "Hello Langfuse")
        span.set_attribute("langfuse.observation.output", "Hello User")
    return "Hello, Langfuse"

映射层对未知 gen_ai.operation.name_map_span_observation_attributes(),保留原始 attributes 并设 langfuse.observation.type=span