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
Observability for multi-agent AI systems. Track what your agents decided, why they decided it, and how much it cost.
AgentWeave wraps your Python agent code with W3C PROV-O compatible OpenTelemetry spans. Three decorators. Full decision provenance. Works with any OTLP backend.
Trace waterfall in Grafana Tempo — a Gemini 2.5 Pro call with PROV-O span attributes (model, provider, agent ID, latency)
Multi-provider trace list — Gemini and Claude Sonnet calls from the same proxy, one unified view
Architecture
graph LR
subgraph Agents
A1[Claude Agent<br><small>Python / Node.js</small>]
A2[Gemini Agent<br><small>Python / Node.js</small>]
A3[Any Agent<br><small>OpenAI, etc.</small>]
end
subgraph AgentWeave Proxy :4000
P[Multi-Provider<br>Proxy]
end
subgraph Upstream LLMs
AN[api.anthropic.com]
GO[generativelanguage<br>.googleapis.com]
end
subgraph Observability
OT[OTLP Collector<br><small>Tempo / Jaeger / Langfuse</small>]
GR[Grafana<br>Dashboard]
end
A1 -- "ANTHROPIC_BASE_URL" --> P
A2 -- "GOOGLE_GENAI_BASE_URL" --> P
A3 -. "@trace_llm decorator" .-> OT
P -- "/v1/messages" --> AN
P -- "/v1beta/models/*" --> GO
P -- "OTel spans" --> OT
OT --> GR
How it works: Agents point their SDK base URL at the proxy. The proxy auto-detects the provider from the request path, forwards the call upstream, extracts token counts and metadata, and emits an OTel span — all transparently. For Python agents, you can also use the @trace_llm / @trace_tool / @trace_agent decorators directly.
Why
When an agent delegates to another agent, calls an LLM ten times searching for a photo, and finally deploys a result — none of that is visible today. You see the output. You don't see the chain.
AgentWeave makes the chain the first-class artifact:
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
Every span carries PROV-O provenance: what was consumed, what was generated, which agent made the call, which model ran it.
Install
pip install agentweave
Quickstart
from agentweave import AgentWeaveConfig, trace_agent, trace_llm, trace_tool
# One-time setup — point at any OTLP HTTP endpoint
AgentWeaveConfig.setup(
agent_id="my-agent-v1",
agent_model="claude-sonnet-4-6",
otel_endpoint="http://localhost:4318", # Grafana Tempo, Jaeger, etc.
)
# Wrap your LLM calls
@trace_llm(provider="anthropic", model="claude-sonnet-4-6",
captures_input=True, captures_output=True)
def call_claude(messages: list) -> ...:
return client.messages.create(...)
# Wrap your tool calls
@trace_tool(name="web_search", captures_input=True, captures_output=True)
def web_search(query: str) -> str:
...
# Wrap your agent turns
@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)
That's it. All three spans link to the same trace ID. Open Grafana Tempo (or any OTLP backend) and you see the waterfall.
Decorators
@trace_agent
Root span for an agent turn. Nests all downstream tool and LLM calls.
@trace_agent(name="nix", captures_input=True, captures_output=True)
def handle(message: str) -> str: ...
@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 the response (Anthropic, OpenAI, and Google Gemini conventions supported).
@trace_llm(provider="anthropic", model="claude-sonnet-4-6",
captures_input=True, captures_output=True)
def call_claude(messages: list) -> anthropic.Message: ...
@trace_llm(provider="google", model="gemini-2.5-pro",
captures_input=True, captures_output=True)
def call_gemini(contents: list) -> genai.GenerateContentResponse: ...
Captured automatically:
prov.llm.prompt_tokens/prov.llm.completion_tokens/prov.llm.total_tokensprov.llm.stop_reason(end_turn,tool_use,STOP, etc.)prov.llm.prompt_previewandprov.llm.response_preview(first 512 chars, whencaptures_input/output=True)
PROV-O Attributes
| Attribute | Description |
|---|---|
prov.activity |
Name of the activity (tool/agent/llm) |
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 |
LLM provider (anthropic, openai, google) |
prov.llm.model |
Model name |
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 |
Full schema: agentweave/schema.py
Proxy — multi-provider observability gateway
For agents you can't instrument with decorators (Node.js, Claude Code, OpenClaw), run the AgentWeave proxy — a transparent HTTP server that sits between your agents and their LLM providers.
The proxy auto-detects the provider from the request path:
| Path pattern | Provider | Upstream |
|---|---|---|
/v1/messages |
Anthropic | api.anthropic.com |
/v1beta/models/... |
Google Gemini | generativelanguage.googleapis.com |
/v1/models/... |
Google Gemini | generativelanguage.googleapis.com |
pip install "agentweave[proxy]"
agentweave proxy start --port 4000 --endpoint http://localhost:4318 --agent-id my-agent
Point your agents at the proxy:
# Anthropic agents
export ANTHROPIC_BASE_URL=http://localhost:4000
# Google Gemini agents
export GOOGLE_GENAI_BASE_URL=http://localhost:4000
One port, all providers. Every LLM call gets a span — no SDK changes, no framework lock-in.
Full setup guide: docs/proxy-setup.md
Backends
AgentWeave emits standard OTLP HTTP — works with any compatible backend:
| Backend | Setup |
|---|---|
| Grafana Tempo | otel_endpoint="http://tempo:4318" — recommended for self-hosted |
| Jaeger | otel_endpoint="http://jaeger:4318" |
| Langfuse v3 | otel_endpoint="https://cloud.langfuse.com/api/public/otel" + auth headers |
| Any OTel Collector | Point at the collector's OTLP HTTP receiver |
| Console (dev) | from agentweave import add_console_exporter; add_console_exporter() |
Development
git clone https://github.com/arniesaha/agentweave
cd agentweave
pip install -e ".[dev]"
pytest # 24 tests
python examples/simple_agent.py
python examples/nix_max_delegation.py
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.1.1.tar.gz.
File metadata
- Download URL: agentweave_sdk-0.1.1.tar.gz
- Upload date:
- Size: 844.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c9d8bbc5870feca85470a6ee91ae64a72b48824ed6be3920e3141b7562b5bcaa
|
|
| MD5 |
5bdf1502b0a537d5fd227b36103ede05
|
|
| BLAKE2b-256 |
e6895656677e15479634d4a114471f848435745c00a710cf7f2ad191a2f91e2c
|
Provenance
The following attestation bundles were made for agentweave_sdk-0.1.1.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.1.1.tar.gz -
Subject digest:
c9d8bbc5870feca85470a6ee91ae64a72b48824ed6be3920e3141b7562b5bcaa - Sigstore transparency entry: 1076775709
- Sigstore integration time:
-
Permalink:
arniesaha/agentweave@11bb0668c5ce5357093aa26810919cab2281d1e9 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/arniesaha
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@11bb0668c5ce5357093aa26810919cab2281d1e9 -
Trigger Event:
push
-
Statement type:
File details
Details for the file agentweave_sdk-0.1.1-py3-none-any.whl.
File metadata
- Download URL: agentweave_sdk-0.1.1-py3-none-any.whl
- Upload date:
- Size: 18.9 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 |
b183c3e85fc66d74a33661cf3077c5c447541e5151f2b53cda6fa42d47fec184
|
|
| MD5 |
91d4e64bee7678989b38913ff1b4fe21
|
|
| BLAKE2b-256 |
4e7aaa5fc3a17e4f5976204c79b20d68c97e1ed970b145a02b05c37bbc4d49f8
|
Provenance
The following attestation bundles were made for agentweave_sdk-0.1.1-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.1.1-py3-none-any.whl -
Subject digest:
b183c3e85fc66d74a33661cf3077c5c447541e5151f2b53cda6fa42d47fec184 - Sigstore transparency entry: 1076775716
- Sigstore integration time:
-
Permalink:
arniesaha/agentweave@11bb0668c5ce5357093aa26810919cab2281d1e9 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/arniesaha
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@11bb0668c5ce5357093aa26810919cab2281d1e9 -
Trigger Event:
push
-
Statement type: