Python SDK for the Polaxis AI Agent Governance Platform
Project description
Polaxis SDK
Python SDK and MCP server for the Polaxis AI Agent Governance Platform.
Polaxis sits between your AI agent and its tools, evaluating every tool call against your policies in real time — blocking dangerous actions, enforcing spend limits, and routing ambiguous calls to a human approver — all in under 5ms.
What does Polaxis do?
Your AI agent
│
│ tool_call("delete_records", {"table": "users"})
▼
┌─────────────────────────────────────────┐
│ Polaxis Policy Engine │
│ • Evaluate against your policy rules │
│ • Check agent spend budget │
│ • Scan for prompt injection / PII │
│ • Route to human approver if needed │
└─────────────────────────────────────────┘
│
│ decision: "allow" | "block" | "escalate"
▼
Your tools (database, email, API…)
Three possible outcomes for every tool call:
| Decision | Meaning | What to do |
|---|---|---|
allow |
Call is within policy. Proceed. | Execute the tool |
block |
Call violates a rule or budget. | Abort — log the reason |
escalate |
Human sign-off required. | Wait for approval via Slack or dashboard |
Installation
pip install polaxis
With MCP server support:
pip install "polaxis[mcp]"
Requirements: Python 3.10+
Quick start
1. Get your API key — create a free account at polaxis.io, add an agent, and copy its API key.
2. Set the environment variable:
export POLAXIS_API_KEY=ag_prod_...
3. Evaluate every tool call before executing it:
import asyncio
from polaxis import Polaxis, PolicyBlockError
guard = Polaxis() # reads POLAXIS_API_KEY from env
async def send_invoice(customer_id: str, amount: float):
# ← Evaluate BEFORE touching any tool
result = await guard.evaluate(
tool_name="send_invoice",
tool_input={"customer_id": customer_id, "amount_usd": amount},
session_id="session-001",
)
# result.decision is "allow", "block", or "escalate"
if result.allowed:
your_invoice_api.send(customer_id, amount)
asyncio.run(send_invoice("cust_123", 499.00))
That's it. Every call is now governed, logged, and auditable from your Polaxis dashboard.
API reference
Polaxis(api_key, *, base_url, timeout, raise_on_block, raise_on_budget)
Main async client. Create one instance per agent and reuse it.
| Parameter | Type | Default | Description |
|---|---|---|---|
api_key |
str |
env POLAXIS_API_KEY |
Your agent API key |
base_url |
str |
https://api.polaxis.io |
Override for self-hosted |
timeout |
float |
10.0 |
HTTP request timeout (seconds) |
raise_on_block |
bool |
True |
Raise PolicyBlockError / FirewallBlockError instead of returning a blocked result |
raise_on_budget |
bool |
True |
Raise BudgetExceededError on budget violations |
await guard.evaluate(tool_name, tool_input, *, session_id, estimated_cost_usd)
Evaluate a proposed tool call. Call this before every tool execution.
result = await guard.evaluate(
tool_name="send_email",
tool_input={"to": "alice@example.com", "subject": "Hello"},
session_id="sess_abc", # optional — groups calls in audit logs
estimated_cost_usd=0.002, # optional — for budget tracking
)
Returns EvaluateResult.
Raises:
PolicyBlockError— blocked by a policy ruleFirewallBlockError— blocked by the Agent Firewall (prompt injection, PII, secrets)BudgetExceededError— agent's budget is exhaustedAuthenticationError— bad API keyAPIError— unexpected HTTP error
await guard.await_approval(approval_id, *, timeout_seconds, poll_interval)
Poll until a human approver acts on an escalated request.
result = await guard.evaluate("wire_transfer", {"amount": 50_000})
if result.pending_approval:
status = await guard.await_approval(
result.approval_id,
timeout_seconds=result.timeout_seconds,
)
if status.approved:
execute_transfer()
Raises:
ApprovalRejectedError— approver clicked RejectApprovalTimeoutError— no decision withintimeout_seconds
EvaluateResult
| Attribute | Type | Description |
|---|---|---|
decision |
str |
"allow" | "block" | "escalate" |
allowed |
bool |
Shorthand for decision == "allow" |
blocked |
bool |
Shorthand for decision == "block" |
pending_approval |
bool |
Shorthand for decision == "escalate" |
reason |
str | None |
Human-readable explanation |
policy_triggered |
str | None |
Policy name that matched |
rule_name |
str | None |
Specific rule that matched |
approval_id |
str | None |
For escalated calls — pass to await_approval() |
timeout_seconds |
int |
How long to wait for approval |
budget_remaining_usd |
float |
Remaining daily budget |
budget_warning |
bool |
Budget is below 20% |
threats |
list |
Detected firewall threats (non-blocking) |
PolaxisSync — synchronous usage
For scripts and non-async frameworks:
from polaxis import PolaxisSync
guard = PolaxisSync()
result = guard.evaluate("delete_records", {"table": "orders", "where": "status='test'"})
if result.blocked:
raise RuntimeError(f"Blocked: {result.reason}")
Error handling
All exceptions inherit from PolaxisError:
from polaxis import (
PolicyBlockError, # policy rule matched → block
FirewallBlockError, # firewall detected threat
BudgetExceededError, # daily/monthly budget hit
ApprovalRejectedError, # human said no
ApprovalTimeoutError, # no decision in time
AuthenticationError, # bad API key
APIError, # HTTP error
)
Pattern — handle without raising:
guard = Polaxis(raise_on_block=False, raise_on_budget=False)
result = await guard.evaluate("tool", input)
match result.decision:
case "allow":
run_tool()
case "block":
log.warning("Blocked: %s", result.reason)
case "escalate":
status = await guard.await_approval(result.approval_id)
Human-in-the-loop (HITL)
When a policy rule has action require_approval, Polaxis pauses the agent and sends an approval request to your configured Slack channel or dashboard.
result = await guard.evaluate("deploy_to_production", {"service": "api", "version": "v2.1.0"})
if result.pending_approval:
print(f"Waiting for approval (id: {result.approval_id})")
# This blocks (async) until approved, rejected, or timed out
status = await guard.await_approval(
result.approval_id,
timeout_seconds=600, # 10 minute window
)
if status.approved:
deploy()
# ApprovalRejectedError or ApprovalTimeoutError raised otherwise
Your team sees this in Slack:
🔔 Polaxis — Approval Required
Agent: deploy-bot | Policy: prod-deploy-policy
Tool: deploy_to_production
Input: {"service": "api", "version": "v2.1.0"}
[✓ Approve] [✗ Reject]
Framework integrations
OpenAI function calling
# See examples/openai_tools_example.py for the full pattern
async def execute_tool(tool_name: str, tool_input: dict) -> str:
result = await guard.evaluate(tool_name, tool_input)
if result.allowed:
return your_tool_implementations[tool_name](**tool_input)
return f"Blocked: {result.reason}"
LangChain
# See examples/langchain_example.py for a GovernedTool base class
class MyTool(GovernedTool):
name = "my_tool"
async def _run_governed(self, **kwargs):
# Only called when Polaxis says "allow"
return do_the_work(**kwargs)
MCP (Model Context Protocol)
Add the Polaxis governance proxy to your MCP client config:
{
"mcpServers": {
"polaxis-proxy": {
"command": "python",
"args": ["-m", "polaxis_mcp.server"],
"env": {
"POLAXIS_API_KEY": "ag_prod_..."
}
}
}
}
The server exposes a polaxis_evaluate tool your agent calls before any action. See examples/mcp_config.json for a full config example.
CrewAI / PydanticAI / AutoGen
The pattern is the same for any framework — evaluate before calling the tool, handle the three outcomes. See the examples/ directory.
Policy examples
Policies are configured in the Polaxis dashboard (JSON format). Here are common patterns:
Block large financial transactions:
{
"name": "finance-guard",
"rules": [
{
"trigger": { "tool": "charge_card", "condition": "amount_usd > 500" },
"action": "block",
"message": "Charges over $500 require manual processing."
}
]
}
Require approval for production deployments:
{
"name": "prod-deploy",
"rules": [
{
"trigger": { "tool": "deploy", "condition": "environment == 'production'" },
"action": "require_approval",
"message": "Production deploys require engineering lead sign-off."
}
]
}
Rate-limit a noisy tool:
{
"name": "api-rate-limit",
"rules": [
{
"trigger": { "tool": "call_external_api", "condition": "rate_per_hour > 100" },
"action": "block",
"message": "External API rate limit exceeded."
}
]
}
Examples
| File | What it shows |
|---|---|
examples/basic_usage.py |
Core evaluate + HITL pattern |
examples/openai_tools_example.py |
OpenAI function-calling agent loop |
examples/langchain_example.py |
LangChain GovernedTool base class |
examples/mcp_config.json |
MCP client config for the proxy server |
Self-hosted deployment
On Pro and Enterprise plans you can run the full Polaxis stack in your own infrastructure:
# Clone the platform
git clone https://github.com/polaxis-io/polaxis-sdk.git
# Full Docker Compose stack
docker compose up
Point the SDK at your instance:
guard = Polaxis(
api_key="ag_prod_...",
base_url="https://polaxis.your-company.com",
)
Contributing
Contributions are welcome! See CONTRIBUTING.md for:
- Development setup
- How to add a new framework integration
- Running tests
- PR checklist and design principles
Support
| Channel | Link |
|---|---|
| Documentation | docs.polaxis.io |
| Dashboard | polaxis.io |
| GitHub Issues | github.com/polaxis-io/polaxis-sdk/issues |
| sdk@polaxis.io |
License
MIT — see LICENSE.
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 polaxis-0.1.0.tar.gz.
File metadata
- Download URL: polaxis-0.1.0.tar.gz
- Upload date:
- Size: 20.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b14fdf18e7f03741e4f6e533f3eaafa57abdde07d5aa4d2b18005024273f4c10
|
|
| MD5 |
46f29131f99ea2b937a77d9fc07da1fd
|
|
| BLAKE2b-256 |
0dff26b8a3f671ae6581fb9b865c8e7dbd26c1bf71df0edb7b8f0d609ee2912c
|
File details
Details for the file polaxis-0.1.0-py3-none-any.whl.
File metadata
- Download URL: polaxis-0.1.0-py3-none-any.whl
- Upload date:
- Size: 15.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
590b696dd9d03618080684a686d19e73dbf5aead074b359448b0ff79e68cffc5
|
|
| MD5 |
b3177f731aa5d308bf146752125d80e9
|
|
| BLAKE2b-256 |
f51452f1fde2a75eb9b847c8f46817f2727fb5e119c6cc085d1d596d2b8e1cd2
|