Documentation Index
Fetch the complete documentation index at: https://docs.tracectrl.ai/llms.txt
Use this file to discover all available pages before exploring further.
Overview
When your agents span multiple processes or services (e.g., Agent A calls Agent B via HTTP), you need to propagate the trace context so all spans appear in the same trace.
TraceCtrl provides two helpers that wrap OpenTelemetry’s W3C Trace Context propagators:
Injecting Context (Outgoing Requests)
On the calling side, inject the traceparent header into your outgoing request:
from tracectrl.context import inject_trace_headers
headers = inject_trace_headers()
# headers now contains {"traceparent": "00-abc123...-def456...-01"}
requests.post("http://agent-b/api", headers=headers, json=payload)
You can also inject into an existing headers dict — the function mutates and returns it:
headers = {"Content-Type": "application/json", "Authorization": "Bearer ..."}
inject_trace_headers(headers)
# traceparent is added to the existing dict
On the receiving side, extract the trace context from incoming headers:
from tracectrl.context import extract_trace_headers
# In your FastAPI/Flask/Django handler:
ctx = extract_trace_headers(dict(request.headers))
# All spans created after this point belong to the caller's trace
extract_trace_headers returns an OpenTelemetry Context object. You don’t normally need to use it directly — OpenTelemetry’s propagator activates the extracted context for you.
API Reference
Injects W3C traceparent (and optionally tracestate) into the given headers dict. If no dict is provided, creates and returns a new one.
Extracts the trace context from incoming headers. Returns the OpenTelemetry Context object.
Full Example: Two-Service Strands Agent
The Strands instrumentor is the canonical, PyPI-published path. Two services, two Agent instances, trace propagated across the HTTP boundary.
import tracectrl
from tracectrl import tag_agent
from tracectrl.instrumentation.strands import StrandsInstrumentor
from tracectrl.context import inject_trace_headers
from tracectrl.session import new_session, current_session_id
from strands import Agent
from strands.models import BedrockModel
import requests
tracectrl.configure(service_name="agent-a")
StrandsInstrumentor().instrument()
agent_a = Agent(
name="researcher",
model=BedrockModel(model_id="anthropic.claude-3-5-haiku-20241022-v1:0"),
system_prompt="You are a research agent.",
)
tag_agent(agent_a)
new_session()
# Call Agent B with trace context
headers = inject_trace_headers()
headers["X-TraceCtrl-Session"] = current_session_id()
response = requests.post(
"http://localhost:5001/process",
headers=headers,
json={"task": "summarise the latest LLM safety papers"},
)
import tracectrl
from tracectrl import tag_agent
from tracectrl.instrumentation.strands import StrandsInstrumentor
from tracectrl.context import extract_trace_headers
from tracectrl.session import set_session_id
from strands import Agent
from strands.models import BedrockModel
from fastapi import FastAPI, Request
tracectrl.configure(service_name="agent-b")
StrandsInstrumentor().instrument()
agent_b = Agent(
name="writer",
model=BedrockModel(model_id="anthropic.claude-3-5-haiku-20241022-v1:0"),
system_prompt="You are a writing agent.",
)
tag_agent(agent_b)
app = FastAPI()
@app.post("/process")
async def process(request: Request):
extract_trace_headers(dict(request.headers))
sid = request.headers.get("X-TraceCtrl-Session")
if sid:
set_session_id(sid)
body = await request.json()
return {"result": str(agent_b(body["task"]))}
This uses the standard W3C Trace Context specification (traceparent header). It works with any OpenTelemetry-compatible service, not just TraceCtrl agents.