Telemetry & Span Instrumentation¶
AgentPool uses Logfire (backed by OpenTelemetry). All code in the critical execution path (RunLoop, Turn, delegation, protocol entry points) MUST be instrumented. Uninstrumented code produces orphan traces.
Rules¶
-
@logfire.instrumentfor method-level spans. Format string params extract from args: -
with logfire.span(...)for spans that must stay open acrossawaitboundaries (e.g., delegation): -
Never
asyncio.create_task()without an active span.create_task()copiescontextvars— if a span is active, the child task inherits it as parent. If not, child spans are orphaned. Use@logfire.instrumenton the calling method, or wrap inwith logfire.span(...). -
ACP cross-process: populate
_meta.traceparent(W3C trace context) when acting as ACP client; extract when acting as ACP agent. See ACP _meta Propagation RFD.
Span Naming¶
protocol.{name}.{method}, orchestration.{component}.{method}, turn.{agent_type}, delegation.subagent, capability.{name}.{method}, lifecycle.{component}.{method}, graph.{component}.{method}
Required Span Attributes¶
session_id, parent_session_id, agent_name, turn_id, run_id
Do NOT Instrument¶
MemoryJournal / MemorySnapshotStore, pure data transforms, test helpers, logging calls.
Critical create_task() Call Sites That MUST Have a Span¶
| Call site | File | How |
|---|---|---|
_consume_run() |
session_controller.py |
@logfire.instrument on _start_run_handle() |
event_bus.publish() |
run.py |
@logfire.instrument on calling method |
_interrupt() |
run.py |
@logfire.instrument on cancel() |
| Background tasks | subagent_tools.py |
with logfire.span(...) in task body |
_execute_parallel() |
base_team.py |
@logfire.instrument on _execute_parallel() |