Observed since 21 Oct, 09:01 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Your complete Agent Ecosystem
Observability and tracing for AI agents, LLM chains, and workflows. Trace every step of your AI pipeline — LLM calls, tool use, retrieval, guardrails — with zero boilerplate.
pip install agenx
With LangChain support:
pip install agenx[langchain]
All optional dependencies:
pip install agenx[all]
Requires Python 3.11+.
The fastest way to add tracing. Decorate your functions and agenx handles span creation, timing, and parent-child relationships automatically.
from agenx import Tracer, StdoutExporter
tracer = Tracer()
tracer.configure(exporters=[StdoutExporter()])
@tracer.llm(model="gpt-4", provider="openai", temperature=0.7)
def chat(prompt: str) -> str:
return call_openai(prompt)
@tracer.tool(tool_name="web_search")
def search(query: str) -> list:
return fetch_results(query)
@tracer.agent(tools=["search", "chat"])
def assistant(question: str) -> str:
docs = search(question)
return chat(f"Answer using: {docs}")
assistant("What is quantum computing?")
For manual control over span attributes and events:
from agenx import trace, SpanType
with trace.span("pipeline") as root:
root.step.input = {"user_id": 12}
with trace.span("search", type=SpanType.RETRIEVER) as r:
r.retriever.query = "reset password"
r.retriever.returned = 5
r.add_event("cache_hit", {"key": "search_abc"})
with trace.span("generate", type=SpanType.LLM) as llm:
llm.llm.model = "gpt-4o"
llm.llm.tokens_total = 843
root.step.output = {"answer": "Click forgot password on the login page"}
trace is a pre-configured Tracer instance with StdoutExporter enabled.
Each decorator creates a span with type-specific attributes:
| Decorator | Span type | Key attributes |
|---|---|---|
@tracer.step | STEP | input, output, metadata |
@tracer.llm | LLM | model, provider, temperature, tokens_*, prompt, output |
@tracer.agent | AGENT | tools, iterations, input, output |
@tracer.tool | TOOL | tool_name, input, output |
@tracer.retriever | RETRIEVER | query, top_k, returned, documents |
@tracer.guard | GUARD | guard_name, passed, reason |
All decorators accept:
name — Custom span name (defaults to function name)capture_args — Record function arguments (default: True)capture_result — Record return value (default: True)# Disable capture for sensitive operations
@tracer.step(capture_args=False, capture_result=False)
def handle_credentials(api_key: str) -> dict:
...
Type-specific options:
@tracer.llm(model="claude-sonnet-4-6", provider="anthropic", temperature=0.3)
@tracer.agent(tools=["search", "calculator"])
@tracer.tool(tool_name="math_calculator")
@tracer.retriever(top_k=10)
@tracer.guard(guard_name="content_safety_filter")
All decorators work with both sync and async functions:
@tracer.llm(model="claude-sonnet-4-6", provider="anthropic")
async def generate(prompt: str) -> str:
return await async_llm_call(prompt)
Async context managers are also supported:
async with tracer.aspan("async_pipeline") as span:
span.step.input = {"query": "hello"}
Built-in colored terminal output with hierarchy and timing:
from agenx import StdoutExporter
exporter = StdoutExporter(
indent=True, # Show parent-child hierarchy
show_ids=True, # Display trace/span IDs
min_duration_ms=0.0, # Filter by minimum duration
)
Any callable that accepts a Span works as an exporter:
def my_exporter(span):
print(f"{span.name} took {span.to_dict().get('duration_ms', 0):.1f}ms")
tracer = Tracer()
tracer.configure(exporters=[StdoutExporter(), my_exporter])
Spans nest automatically via context. No manual ID passing needed:
@tracer.agent(name="qa_agent")
def qa_pipeline(question: str) -> str:
docs = retrieve(question) # child span
answer = generate(question, docs) # child span
return answer
@tracer.retriever(top_k=5)
def retrieve(query: str) -> list:
...
@tracer.llm(model="gpt-4")
def generate(query: str, context: list) -> str:
...
Calling qa_pipeline produces a trace tree:
qa_agent
├── retrieve
└── generate
Auto-instrument LangChain and LangGraph with a single call:
from agenx import instrument
instrument("langchain")
This patches chains, LLM calls, agents, and tools. To instrument all detected frameworks:
from agenx import instrument_all
instrument_all()
To remove instrumentation:
from agenx import uninstrument, uninstrument_all
uninstrument("langchain")
# or
uninstrument_all()
Record point-in-time events within a span:
with trace.span("search", type=SpanType.RETRIEVER) as r:
r.add_event("cache_hit", {"key": "search_abc"})
r.add_event("reranking_complete", {"top_k": 5})
agenx| Name | Description |
|---|---|
trace | Pre-configured Tracer with StdoutExporter |
Tracer | Core tracer class |
StdoutExporter | Terminal exporter |
SpanType | Enum: ROOT, STEP, LLM, RETRIEVER, TOOL, GUARD, AGENT |
instrument(name) | Enable instrumentation for a framework |
uninstrument(name) | Disable instrumentation |
instrument_all() | Auto-detect and instrument all available frameworks |
uninstrument_all() | Disable all instrumentation |
MIT
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.1.4 | 8 Apr 2026 | 11 |
This describes our collected data; it is not a security assessment.
Observed since 21 Oct, 09:01 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:c12b9f8685d5d1ecbd7875369a62b86fe5e1bd33db09c7bebaad2f6f3f236570