Observability and mesh layer for multi-agent AI systems — track what your agents decided, why they decided it, and how they're connected.
Project description
AgentWeave
Agent runtime observability and provenance layer for multi-agent AI systems.
When agents delegate, loop, and fanout across tools and models, the final output tells you nothing. AgentWeave makes the decision chain the first-class artifact — every span carries W3C PROV-O provenance on OpenTelemetry: which agent acted, which model ran, what was consumed, what was generated, and how much it cost.
Three paths to instrumentation — decorators, auto-instrumentation, or zero-code proxy. Any OTLP backend.
agent.nix 94ms
├── llm.claude-sonnet-4-6 81ms ← prompt_tokens=847, completion_tokens=312
├── tool.image_search 52ms
├── llm.claude-sonnet-4-6 79ms ← prompt_tokens=847, completion_tokens=312
├── tool.image_search 51ms
├── llm.claude-sonnet-4-6 80ms ← found it
└── tool.deploy_portfolio 48ms
How it works
graph LR
subgraph Agents["Agents — proxy mode"]
A1["Anthropic Agent"]
A2["Gemini Agent"]
A3["OpenAI Agent"]
end
SDK["Any Agent — SDK decorators / auto_instrument()"]
subgraph Proxy["AgentWeave Proxy :4000"]
P["Multi-Provider Proxy"]
end
subgraph LLMs["Upstream LLMs"]
AN[api.anthropic.com]
GO[generativelanguage.googleapis.com]
OA[api.openai.com]
end
subgraph Observability
OT["OTLP Collector — Tempo / Jaeger / Langfuse"]
GR["AgentWeave Dashboard"]
end
A1 -- "ANTHROPIC_BASE_URL" --> P
A2 -- "GOOGLE_GENAI_BASE_URL" --> P
A3 -- "OPENAI_BASE_URL" --> P
SDK -- "OTel spans" --> OT
P -- "/v1/messages" --> AN
P -- "/v1beta/models/*" --> GO
P -- "/v1/chat/completions" --> OA
P -- "OTel spans" --> OT
OT --> GR
Three paths to instrumentation:
- Auto-instrumentation (
auto_instrument()) — one call patches Anthropic and OpenAI SDKs. No decorators needed. - Decorators (
@trace_agent,@trace_llm,@trace_tool) — wrap your functions directly in Python, TypeScript, or Go. Zero infrastructure needed. - Proxy — point any agent's base URL at AgentWeave. It auto-detects the provider, forwards upstream, extracts token counts, and emits OTel spans. No code changes.
Overview — LLM calls, cost over time, and p95 latency by model
Session Explorer — multi-level sub-agent hierarchy with parent→child edges
Install
| SDK | Language | Install |
|---|---|---|
| sdk/python | Python | pip install agentweave-sdk |
| sdk/js | TypeScript / JavaScript | npm install agentweave-sdk |
| sdk/go | Go | go get github.com/arniesaha/agentweave-go |
Quickstart (Python)
Option A — Auto-instrumentation (zero decorators)
from agentweave import auto_instrument
auto_instrument() # patches Anthropic + OpenAI SDKs automatically
# Every client.messages.create() and client.chat.completions.create()
# now emits OTel spans with token counts — no wrappers needed.
Option B — Decorators (explicit control)
from agentweave import AgentWeaveConfig, trace_agent, trace_llm, trace_tool
AgentWeaveConfig.setup(
agent_id="my-agent-v1",
agent_model="claude-sonnet-4-6",
otel_endpoint="http://localhost:4318",
)
@trace_llm(provider="anthropic", model="claude-sonnet-4-6",
captures_input=True, captures_output=True)
def call_claude(messages: list) -> ...:
return client.messages.create(...)
@trace_tool(name="web_search", captures_input=True, captures_output=True)
def web_search(query: str) -> str:
...
@trace_agent(name="my-agent")
async def handle(message: str) -> str:
response = call_claude(messages=[{"role": "user", "content": message}])
return web_search(response.content[0].text)
All three spans link to the same trace ID. Open any OTLP backend and you see the waterfall.
Framework Examples
| Framework | Example |
|---|---|
| LangGraph | examples/langgraph |
| CrewAI | examples/crewai |
| AutoGen | examples/autogen |
| OpenAI Agents SDK | examples/openai-agents-sdk |
Auto-Instrumentation
Patch LLM SDK client methods with a single call — no decorators needed.
from agentweave import auto_instrument, uninstrument
auto_instrument() # patch all detected SDKs
auto_instrument(providers=["anthropic"]) # selective
auto_instrument(captures_output=True) # include response preview
uninstrument() # restore originals
- Supports Anthropic (
Messages.create) and OpenAI (Completions.create), sync + async - Composes with explicit
@trace_llm— auto-instrumentation detects existing spans and skips to avoid double-tracing - Idempotent — calling
auto_instrument()twice is safe - Streaming support deferred to a follow-up
Decorators
@trace_agent
Root span for an agent turn. Nests all downstream tool and LLM calls.
@trace_agent(name="nix")
def handle(message: str) -> str: ...
Session grouping
Pass session_id to group all spans from a single user conversation together.
The value is attached as session.id on every span, making it a filterable
dimension in Grafana / Tempo.
@trace_agent(name="nix", session_id="conv-abc123")
def handle(message: str) -> str: ...
The proxy also accepts the X-AgentWeave-Session-Id header for zero-code
session tagging — see docs/session-grouping.md.
@trace_tool
Span for any tool call — file ops, API calls, shell commands, A2A delegation.
@trace_tool(name="delegate_to_max", captures_input=True, captures_output=True)
def delegate_to_max(task: str) -> dict: ...
@trace_llm
Span for LLM invocations. Auto-extracts token counts and stop reason from Anthropic, OpenAI, and Google Gemini response shapes.
@trace_llm(provider="anthropic", model="claude-sonnet-4-6", captures_output=True)
def call_claude(messages: list) -> anthropic.Message: ...
Captured automatically:
prov.llm.prompt_tokens/prov.llm.completion_tokens/prov.llm.total_tokensprov.llm.stop_reasonprov.llm.response_preview(first 512 chars, whencaptures_output=True)
Sub-agent Attribution
When agents delegate to sub-agents, use the sub-agent attribution parameters to link child sessions to their parent and distinguish agent roles in traces.
Python SDK
# Main agent — tags itself as the root session
@trace_agent(name="nix", session_id="sess-main-123", agent_type="main", turn_depth=1)
def main_agent(msg: str) -> str:
return delegate_to_sub(msg)
# Sub-agent — linked to parent session
@trace_agent(name="max", parent_session_id="sess-main-123",
agent_type="subagent", turn_depth=2)
def sub_agent(task: str) -> str:
return call_llm(task)
Environment variable auto-detection
Set AGENTWEAVE_PARENT_SESSION_ID and the SDK auto-populates prov.parent.session.id, defaults agent_type to "subagent", and turn_depth to 2:
export AGENTWEAVE_PARENT_SESSION_ID=sess-main-123
Proxy headers
When using the proxy, pass sub-agent context via HTTP headers:
| Header | Span attribute | Example |
|---|---|---|
X-AgentWeave-Parent-Session-Id |
prov.parent.session.id |
sess-main-123 |
X-AgentWeave-Agent-Type |
prov.agent.type |
subagent |
X-AgentWeave-Turn-Depth |
prov.session.turn |
2 |
TypeScript SDK
import { traceAgent } from 'agentweave-sdk';
const subAgent = traceAgent({
name: 'max',
parentSessionId: 'sess-main-123',
agentType: 'subagent',
turnDepth: 2,
})(async (task: string) => {
return callLlm(task);
});
New span attributes
| Attribute | Description |
|---|---|
prov.parent.session.id |
ID of the parent session that spawned this sub-agent |
prov.agent.type |
"main", "subagent", or "delegated" |
prov.session.turn |
Turn depth: 1 = main session, 2 = first-level sub-agent |
PROV-O Attributes
| Attribute | Description |
|---|---|
prov.activity.type |
tool_call, agent_turn, or llm_call |
prov.agent.id |
Agent identifier |
prov.agent.model |
Model name |
prov.used |
Serialized inputs consumed by the activity |
prov.wasGeneratedBy |
Output produced by the activity |
prov.wasAssociatedWith |
Agent responsible for the activity |
prov.llm.provider |
anthropic, openai, or google |
prov.llm.prompt_tokens |
Input token count |
prov.llm.completion_tokens |
Output token count |
prov.llm.total_tokens |
Total tokens |
prov.llm.stop_reason |
Why the model stopped |
prov.task.label |
Human-readable label for the task this agent is executing |
Full schema: sdk/python/agentweave/schema.py
Proxy — zero-code observability
For agents you can't instrument with decorators (Claude Code, Node.js, any runtime), run the AgentWeave proxy — a transparent HTTP server that sits between your agents and their LLM providers. Works with Claude Code out of the box — just set ANTHROPIC_BASE_URL in ~/.claude/settings.json (setup guide).
pip install "agentweave[proxy]"
agentweave proxy start --port 4000 --endpoint http://localhost:4318 --agent-id my-agent
# Point agents at the proxy — no code changes needed
export ANTHROPIC_BASE_URL=http://localhost:4000
export GOOGLE_GENAI_BASE_URL=http://localhost:4000
export OPENAI_BASE_URL=http://localhost:4000
One port, all providers. Every LLM call gets a span automatically.
Docker / k8s setup: see
deploy/docker/Dockerfile
Backends
AgentWeave emits standard OTLP HTTP — works with any compatible backend:
| Backend | Endpoint |
|---|---|
| Grafana Tempo | http://tempo:4318 — recommended for self-hosted |
| Jaeger | http://jaeger:4318 |
| Langfuse v3 | https://cloud.langfuse.com/api/public/otel |
| Console (dev) | from agentweave import add_console_exporter; add_console_exporter() |
Docs
| Topic | Doc |
|---|---|
| Claude Code proxy setup | docs/claude-code-proxy.md |
| Session grouping | docs/session-grouping.md |
| Proxy setup | docs/proxy-setup.md |
| Production hardening | docs/production-hardening.md |
| Provider compatibility | docs/compatibility.md |
| Deterministic trace IDs | docs/deterministic-trace-ids.md |
| Span linking design | docs/span-linking-design.md |
| Proxy benchmarks | docs/benchmarks.md |
| Versioning policy | docs/versioning.md |
Development
git clone https://github.com/arniesaha/agentweave && cd agentweave
pip install -e "./sdk/python[dev]"
pytest sdk/python # 237 Python tests
(cd sdk/js && npm ci && npx jest --verbose) # 10 TypeScript tests
(cd sdk/go && go test ./... -v) # 4 Go tests
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agentweave_sdk-0.3.0.tar.gz.
File metadata
- Download URL: agentweave_sdk-0.3.0.tar.gz
- Upload date:
- Size: 50.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6f0e26dd3fb4f8e9a5d388ff57aa08229bf45f71c9aa6c319e11f4990e58cc4
|
|
| MD5 |
34ae023e15804f4569f8918a549aee4a
|
|
| BLAKE2b-256 |
dc117d7f0bae50bc52737b14b36845220f4339960e97467a5468150d386535c0
|
Provenance
The following attestation bundles were made for agentweave_sdk-0.3.0.tar.gz:
Publisher:
publish.yml on arniesaha/agentweave
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agentweave_sdk-0.3.0.tar.gz -
Subject digest:
a6f0e26dd3fb4f8e9a5d388ff57aa08229bf45f71c9aa6c319e11f4990e58cc4 - Sigstore transparency entry: 1128232437
- Sigstore integration time:
-
Permalink:
arniesaha/agentweave@aa58978319f2ce7065629768c6973dacb60fb5c0 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/arniesaha
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@aa58978319f2ce7065629768c6973dacb60fb5c0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file agentweave_sdk-0.3.0-py3-none-any.whl.
File metadata
- Download URL: agentweave_sdk-0.3.0-py3-none-any.whl
- Upload date:
- Size: 33.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
168ba387ee41eb42daaa7ca9a2bbf374c1f9dad40cef8f91d6b813ae73f75537
|
|
| MD5 |
ed6e7b52a60317de57210894231ac3e6
|
|
| BLAKE2b-256 |
2b3dfdb9d237630b6dd8cd22acb979ce8dd70b84130db98b02f4a2c8e78195db
|
Provenance
The following attestation bundles were made for agentweave_sdk-0.3.0-py3-none-any.whl:
Publisher:
publish.yml on arniesaha/agentweave
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agentweave_sdk-0.3.0-py3-none-any.whl -
Subject digest:
168ba387ee41eb42daaa7ca9a2bbf374c1f9dad40cef8f91d6b813ae73f75537 - Sigstore transparency entry: 1128232486
- Sigstore integration time:
-
Permalink:
arniesaha/agentweave@aa58978319f2ce7065629768c6973dacb60fb5c0 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/arniesaha
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@aa58978319f2ce7065629768c6973dacb60fb5c0 -
Trigger Event:
push
-
Statement type: