Instrument any supported agent framework without modifying application code.
# Instrument a specific framework
agent-strace auto --framework langchain -- python my_agent.py
# Auto-detect all installed frameworks
agent-strace auto --detect -- python my_agent.py
# Via environment variable (no CLI wrapper needed)
AGENT_STRACE_AUTO_INSTRUMENT=langchain,litellm python my_agent.pyOr in code:
from agent_trace.integrations import instrument_langchain
instrument_langchain()| Framework | Install | What's traced |
|---|---|---|
| OpenAI Agents SDK | pip install agent-strace[openai-agents] |
Runner.run, FunctionTool calls |
| LangChain / LangGraph | pip install agent-strace[langchain] |
BaseTool._run, BaseChatModel._generate |
| CrewAI | pip install agent-strace[crewai] |
Crew.kickoff, Agent.execute_task, Task.execute_sync |
| LiteLLM | pip install agent-strace[litellm] |
litellm.completion |
| Anthropic SDK | pip install anthropic |
messages.create |
| OpenAI SDK | pip install openai |
chat.completions.create |
| AWS Strands | pip install agent-strace[strands] |
Agent.__call__, BaseTool.invoke |
Install all integrations at once:
pip install agent-strace[all-integrations]Each integration is an optional extra — the core package stays dependency-free. See ADR-0003.
Use setup-generated hooks when the agent CLI has its own lifecycle hook system.
| CLI | Setup | What's traced |
|---|---|---|
| Claude Code | agent-strace setup --cli claude |
Session start/end, user prompts, assistant responses, tool calls/results |
| OpenAI Codex | agent-strace setup --cli codex |
Session start, user prompts, assistant responses, PreToolUse/PostToolUse tools |
| Gemini CLI | agent-strace setup --cli gemini |
Session start/end, prompts, assistant responses, BeforeTool/AfterTool tools |
| Cursor | agent-strace setup --cli cursor |
Session start/end, prompts, shell execution, file edits, assistant responses when emitted by Cursor hooks |
| GitHub Copilot CLI | agent-strace setup --cli copilot |
Session starts, prompts, hook-visible tool calls/results, and stop payloads when emitted by Copilot hooks |
| GitHub Copilot Desktop | Wrap each local MCP server with agent-strace record -- ... |
MCP initialize/tool call/tool result traffic for wrapped servers only; full chat transcripts and non-MCP activity are not exposed |
All paths write the same event stream under .agent-traces/, so replay, timeline, explain, why, watch, export, and audit commands work the same way after capture.
For Copilot Desktop, use a shared absolute trace directory such as /Users/alice/.agent-strace/traces, configure agent-strace --trace-dir <dir> mcp as an optional trace-reader MCP server, and wrap each tool-providing MCP server with agent-strace --trace-dir <dir> record --name <label> -- <original-command> <args>. See setup.md for the full Local server field values and validation commands.
from agent_trace.integrations import instrument_openai_agents
instrument_openai_agents()
# Now use the SDK normally
from agents import Agent, Runner
agent = Agent(name="my-agent", instructions="...")
result = Runner.run_sync(agent, "Do the task")Traces: Runner.run, Runner.run_sync, Runner.run_streamed, all FunctionTool calls.
from agent_trace.integrations import instrument_langchain
instrument_langchain()
# Now use LangChain normally
from langchain_anthropic import ChatAnthropic
llm = ChatAnthropic(model="claude-3-5-sonnet-20241022")Traces: BaseTool._run, BaseChatModel._generate, BaseChatModel._stream.
LangGraph node-level tracing is included — each node execution appears as a separate tool_call span with the node name and input/output.
from agent_trace.integrations import instrument_crewai
instrument_crewai()
# Now use CrewAI normally
from crewai import Crew, Agent, Task
crew = Crew(agents=[...], tasks=[...])
result = crew.kickoff()Traces: Crew.kickoff (session start/end), Agent.execute_task (LLM request/response), Task.execute_sync (tool call/result).
from agent_trace.integrations import instrument_litellm
instrument_litellm()
import litellm
response = litellm.completion(model="gpt-4o", messages=[...])Traces: litellm.completion, litellm.acompletion.
from agent_trace.integrations import instrument_anthropic
instrument_anthropic()
import anthropic
client = anthropic.Anthropic()
message = client.messages.create(model="claude-3-5-sonnet-20241022", ...)Traces: messages.create, messages.stream.
from agent_trace.integrations import instrument_openai
instrument_openai()
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(model="gpt-4o", messages=[...])Traces: chat.completions.create, chat.completions.stream.
from agent_trace.integrations import instrument_strands
instrument_strands()
from strands import Agent
agent = Agent(tools=[...])
result = agent("Do the task")Traces: Agent.__call__, BaseTool.invoke.
When one agent calls another over HTTP, inject a traceparent header so both sessions share the same W3C trace ID. This links spans across agents in any OTLP backend (Jaeger, Tempo, Datadog, Honeycomb).
Injecting (outbound call):
from agent_trace.propagation import inject_traceparent
headers = inject_traceparent({}, session_id="abc123", event_id="evt456")
# headers now contains: {"traceparent": "00-<trace-id>-<span-id>-01"}
response = requests.post("https://other-agent/run", headers=headers, json={...})Extracting (inbound call):
from agent_trace.propagation import extract_traceparent
ctx = extract_traceparent(request.headers)
if ctx:
# ctx["trace_id"] — 32-hex W3C trace ID from upstream
# ctx["parent_id"] — span ID of the calling agent
# ctx["sampled"] — sampling flag
passPass trace_id from the extracted context into inject_traceparent on any further outbound calls to propagate the same trace ID through the full call chain.
The implementation follows W3C Trace Context Level 1. No third-party dependencies required.