Metadata-Version: 2.4
Name: axiorank
Version: 0.7.2
Summary: Official Python SDK for AxioRank. Zero-Trust for AI agents: route every tool call through one governed control plane.
Project-URL: Homepage, https://axiorank.com
Project-URL: Documentation, https://app.axiorank.com/docs
Project-URL: Source, https://github.com/frostyhand/AxioRank
Project-URL: Issues, https://github.com/frostyhand/AxioRank/issues
Author: AxioRank
License: MIT
License-File: LICENSE
Keywords: agent,agent-security,ai,axiorank,firewall,gateway,guardrails,llm,mcp,security,zero-trust
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: httpx<1,>=0.27
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.40; extra == 'anthropic'
Provides-Extra: crewai
Requires-Dist: crewai>=0.100; extra == 'crewai'
Provides-Extra: dev
Requires-Dist: mypy>=1.8; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Provides-Extra: langchain
Requires-Dist: langchain-core>=0.3; extra == 'langchain'
Provides-Extra: litellm
Requires-Dist: litellm>=1.60; extra == 'litellm'
Provides-Extra: llamaindex
Requires-Dist: llama-index-core>=0.10; extra == 'llamaindex'
Provides-Extra: openai-agents
Requires-Dist: openai-agents>=0.1; extra == 'openai-agents'
Provides-Extra: pydantic-ai
Requires-Dist: pydantic-ai>=1.0; extra == 'pydantic-ai'
Provides-Extra: verify
Requires-Dist: cryptography>=42; extra == 'verify'
Description-Content-Type: text/markdown

# axiorank

Official Python SDK for [AxioRank](https://axiorank.com), the Zero-Trust
control plane for AI agents. Route your agent's tool calls through one governed
gateway so policies are enforced, risk is scored, and every call is audited.

Parity with the TypeScript [`@axiorank/sdk`](https://www.npmjs.com/package/@axiorank/sdk).

## Install

```bash
pip install axiorank
```

## Quickstart (sync)

```python
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

```python
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)

```python
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

```python
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.

```python
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

```bash
pip install "axiorank[langchain]"
```

```python
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:

```python
from axiorank.integrations.langchain import guard_tool

safe_tool = guard_tool(my_tool, axio, on_deny="return")
```

## LlamaIndex

```bash
pip install "axiorank[llamaindex]"
```

```python
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

```bash
pip install "axiorank[pydantic-ai]"
```

```python
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)

```bash
pip install "axiorank[openai-agents]"
```

```python
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")
```

## 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
