Avenza Python SDK
Instrument AI agents in one line. Cost, value, and SLO tracking — automatically.
Install
pip install avenza
Quickstart (3 lines)
from avenza import Agent
agent = Agent(name='Invoice Bot', risk_tier='T2')
with agent.run() as run:
result = process_invoice(data)
run.success = result.is_valid
run.log_value('task_completed', quantity=1, unit_value_usd=1.50)
That's it. If you're using the official Anthropic, OpenAI, or Gemini client, token usage is captured automatically with zero additional code.
Setup wizard
avenza init
Interactive wizard that verifies your API key and writes a working starter script — not a docs page to interpret.
Diagnose
avenza doctor
Self-diagnose connection issues, missing instrumentation, and proxy configuration.
Auto-instrumentation
The SDK patches the official provider clients the moment it's imported:
import anthropic
from avenza import Agent
agent = Agent(name='Support Bot')
client = anthropic.Anthropic()
with agent.run() as run:
# Token usage captured automatically from this call
response = client.messages.create(model='claude-sonnet-4-6', ...)
run.success = True
Works across threads and async/await via Python's contextvars.
Manual token fallback
with agent.run() as run:
response = my_llm_client.call(...)
run.set_tokens(response.input_tokens, response.output_tokens)
run.success = True
LangChain
from avenza.integrations.langchain import AvenzaCallbackHandler
from langchain_anthropic import ChatAnthropic
handler = AvenzaCallbackHandler(agent_name='Support Classifier', risk_tier='T1')
llm = ChatAnthropic(model='claude-sonnet-4-6', callbacks=[handler])
response = llm.invoke('Classify this ticket: ...')
Testing
from avenza.testing import MockAgent
def test_my_agent():
agent = MockAgent(name='Invoice Bot')
with agent.run() as run:
run.success = True
run.log_value('task_completed', quantity=1, unit_value_usd=1.50)
assert agent.runs[-1].success is True
assert agent.runs[-1].value_events[0]['quantity'] == 1
Configuration
| Parameter | Default | Description |
|---|---|---|
name |
required | Agent display name |
risk_tier |
'T1' |
T1 (autonomous), T2 (approve-first), T3 (assist-only) |
api_key |
AVENZA_API_KEY env |
Bearer token from Settings → API Tokens |
model |
None | LLM model for cost lookup (auto-detected when using auto-instrumentation) |
auto_instrument |
True |
Patch provider clients automatically |
offline_buffer |
True |
Queue failed sends to disk and retry |
base_url |
https://app.avenza.app |
Override for self-hosted |
redact_fields |
None | Field names to scrub from outgoing payloads (see below) |
Redaction
If your agent handles sensitive data — patient names, SSNs, account numbers — in set_metadata() or escalate(reason=...), tell the SDK which field names to scrub before anything leaves your process:
agent = Agent(name="Intake Bot", redact_fields=["ssn", "patient_name", "email"])
with agent.run() as run:
run.set_metadata(patient_name="Jane Doe", ssn="123-45-6789", confidence=0.94)
# payload sent to Avenza has patient_name and ssn replaced with "[REDACTED]"
# confidence is untouched — only field names you list are affected
Matching is case-insensitive and recursive (checked inside meta and value_events, at any nesting depth). Redaction only affects the outgoing copy — run._metadata in your own process still has the real values, so your agent's own logic is unaffected.
Never blocks. Never raises.
Every network call is fire-and-forget on a background thread. Avenza being down, slow, or returning errors will never crash your agent or add latency to your agent's actual work. Failed sends are buffered to .avenza_buffer.jsonl and retried on next startup.
If a send fails and there's no offline buffer to catch it (offline_buffer=False, or the buffer write itself fails — e.g. read-only filesystem), the payload is genuinely lost rather than silently retried. That's tracked, not hidden:
if agent.dropped_count > 0:
logger.warning(f"Avenza lost {agent.dropped_count} governance record(s)")
dropped_count should stay 0 in normal operation. A nonzero value under sustained load is a signal to leave offline_buffer=True (the default) rather than disabling it.
Metadata
Release files for avenza 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| avenza-1.1.0.tar.gz | 23.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| avenza-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 47.2 kB
Release files / avenza-1.1.0.tar.gz
| Download URL | avenza-1.1.0.tar.gz |
|---|---|
| Size | 23.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4dc98cbd371bec259cc0fd922b4e4aa0c1f6934386fc3d2d51f899536617e3c5
|
|
BLAKE2b-256 checksum How to use checksums |
edee868f0d6088910c5f300781eaf613e56c4318cd936de54854d0d6c13f6353
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.6
|
Release files / avenza-1.1.0-py3-none-any.whl
| Download URL | avenza-1.1.0-py3-none-any.whl |
|---|---|
| Size | 23.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d740fa5b4fc5ca19437b0b726698d4ea76a68bafda95d52fec5256d6266736c0
|
|
BLAKE2b-256 checksum How to use checksums |
6f78d3422d250780eb513935ce818caca7fa4b13b0f2651ab02def1e05c4135e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.6
|
Security for avenza 1.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.