Skip to main content

llm-agent-trace

PyPI version Python 3.9+ License: MIT

Zero-dependency LLM call tracer. Patch once — every provider is captured automatically.

┌─ research_agent · #a3f2b1  1149 tokens  $0.0022  3.4s
│
│  ├─ summarize  312→87 tok  $0.0004  1.2s
│  │  └─► openai · api.openai.com/v1/chat/completions  gpt-4o  312→87 tok  $0.0004  1.2s  ✓
│  │
│  └─ verify  540→210 tok  $0.0018  2.1s
│     └─► anthropic · api.anthropic.com/v1/messages  claude-sonnet-4-6  540→210 tok  $0.0018  2.1s  ✓
│
│  2 call(s)  ·  852→297 tokens  ·  $0.0022  ·  3.4s
└────────────────────────────────────────

Why

Every LLM observability tool is either a paid SaaS, a massive framework dependency, or tied to a specific provider. llm-agent-trace is none of those — it's a small library you drop in and forget about.

  • Zero runtime dependencies — stdlib only
  • Provider-agnostic — works with OpenAI, Anthropic, Mistral, Groq, Gemini, Cohere, Ollama, LM Studio, Azure OpenAI, and anything that speaks HTTP
  • Works with LangChain, LiteLLM, and any other framework — intercepts at the HTTP layer, not the SDK layer
  • Sync + async — both are captured

Install

pip install llm-agent-trace

Quickstart

import llm_agent_trace

# One line at the top of your script
llm_agent_trace.patch()

# Wrap your agent run in a session
with llm_agent_trace.session("my_agent"):
    response = openai.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": "Hello"}]
    )
# Trace is printed to stderr automatically when the session ends

Works identically with LiteLLM, LangChain, Anthropic SDK, or any HTTP-based LLM client — no changes to your existing code.

Adding structure with spans

Without spans you get a flat list of calls. Spans let you group calls into named steps:

import llm_agent_trace

llm_agent_trace.patch()

@llm_agent_trace.span("summarize")
def summarize(text):
    return llm.invoke(f"Summarize: {text}")

@llm_agent_trace.span("verify")
def verify(summary):
    return llm.invoke(f"Is this accurate? {summary}")

with llm_agent_trace.session("research_agent"):
    summary = summarize(long_document)
    verdict = verify(summary)

Spans also work as context managers:

with llm_agent_trace.session("agent"):
    with llm_agent_trace.span("step_1"):
        result = llm.invoke(...)
    with llm_agent_trace.span("step_2"):
        result = llm.invoke(...)

Save trace as JSON

with llm_agent_trace.session("my_agent", output="trace.json"):
    ...
{
  "session_id": "a3f2b1",
  "name": "my_agent",
  "duration_ms": 3400,
  "total_calls": 2,
  "total_tokens_in": 852,
  "total_tokens_out": 297,
  "total_cost_usd": 0.0022,
  "spans": [...],
  "orphan_calls": [...]
}

Disable terminal output

with llm_agent_trace.session("my_agent", print_trace=False, output="trace.json"):
    ...

Custom cost table

llm_agent_trace.patch(cost_table={
    "my-fine-tuned-model": (0.005, 0.015),  # per 1k tokens: in, out
})

Introspection

import llm_agent_trace

sess = llm_agent_trace.current_session()   # active Session or None
sp   = llm_agent_trace.current_span()      # active Span or None

Supported providers (auto-detected)

Provider Endpoint pattern
OpenAI api.openai.com/v1/chat/completions
Anthropic api.anthropic.com/v1/messages
Azure OpenAI *.openai.azure.com/*/chat/completions
Mistral api.mistral.ai/v1/chat/completions
Groq api.groq.com/openai/v1/chat/completions
Gemini generativelanguage.googleapis.com/*/generateContent
Cohere api.cohere.com/v1/chat
Together AI api.together.xyz/v1/chat/completions
Perplexity api.perplexity.ai/chat/completions
OpenRouter openrouter.ai/api/v1/chat/completions
Ollama / LM Studio localhost:*/api/chat

Any provider not listed but using HTTP/REST is captured as unknown.

Limitations (v1)

  • Streaming responses are logged as a single event when the stream closes; per-chunk tracing is not yet supported.
  • gRPC-based providers are not supported (rare in practice — all major providers use HTTP).
  • Monkey-patching works best when patch() is called before your LLM library imports. If you import from litellm import completion before calling patch(), that specific reference won't be intercepted — use litellm.completion(...) instead.

Contributing

Issues and PRs welcome. Please open an issue before starting work on a large change.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

llm_agent_trace-0.2.0.tar.gz (16.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

llm_agent_trace-0.2.0-py3-none-any.whl (13.3 kB view details)

Uploaded Python 3

File details

Details for the file llm_agent_trace-0.2.0.tar.gz.

File metadata

  • Download URL: llm_agent_trace-0.2.0.tar.gz
  • Upload date:
  • Size: 16.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for llm_agent_trace-0.2.0.tar.gz
Algorithm Hash digest
SHA256 8fe6660e41e8645debb0528397f653ae81f7ad69fcf696de0d3eefeb772a96b8
MD5 6e7918300b563d3735605254e3aaf978
BLAKE2b-256 a24ae8a6a5195fce3d24d1bc9a0455149f544206db8ffc8c9016cc76ae84bc0d

See more details on using hashes here.

File details

Details for the file llm_agent_trace-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for llm_agent_trace-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fbd6cd5b38cfe4b91b2cacd126cce4f593def74ee3bfff6bf875b4a4f1b9652d
MD5 e3bc879862e39fe0ed00569c5a83908e
BLAKE2b-256 6f74ec7e2deebafcb85e5ceb6bc55b5ad67e0683942e58a67935575a580103d7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page