AI Agent Warden - Keep your AI agents in check with policy enforcement and human oversight
Project description
ardenpy
Policy enforcement and human approval for AI agent tool calls.
Arden sits between your agent and its tools. Every call is checked against policies you configure in the dashboard — automatically allowed, blocked, or held for a human to approve.
Install
pip install ardenpy
Quick start
1. Get your API key from app.arden.sh. You'll get two keys:
arden_test_...— development, hitsapi-test.arden.sharden_live_...— production, hitsapi.arden.sh
2. Configure once
import ardenpy as arden
arden.configure(api_key="arden_live_...")
3. Call your tools
For LangChain and CrewAI — that's it. Arden auto-patches the framework at configure-time, so every tool call is intercepted without any wrapping:
# LangChain — use tools normally, Arden intercepts everything
arden.configure(api_key="arden_live_...", tool_name_prefix="support")
agent = create_react_agent(llm, tools, prompt) # no wrapping needed
# Tool names in the dashboard: "support.search_web", "support.send_email", etc.
For custom agents with no framework, wrap functions explicitly:
def issue_refund(amount: float, customer_id: str) -> dict:
return {"refund_id": "re_123", "amount": amount}
safe_refund = arden.guard_tool("stripe.issue_refund", issue_refund)
result = safe_refund(150.0, customer_id="cus_abc")
# Arden checks policy first — allow, block, or wait for human approval
How it works
Every tool call goes through a policy check before executing:
| Policy decision | What happens |
|---|---|
allow |
Function executes immediately |
block |
PolicyDeniedError raised, function never runs |
requires_approval |
Pauses until a human approves or denies on the dashboard |
No policy configured? The call is allowed automatically and logged — you get a full audit trail from day one and can add policies incrementally.
Approval modes
When a tool requires approval, you choose how your code waits:
wait (default) — blocks until a human acts, then executes or raises PolicyDeniedError.
async — returns a PendingApproval immediately, background thread polls and calls your callback.
webhook — returns PendingApproval immediately, no polling. Arden POSTs to your endpoint when an admin decides.
# wait (default)
safe_refund = arden.guard_tool("stripe.issue_refund", issue_refund)
# async
safe_refund = arden.guard_tool("stripe.issue_refund", issue_refund,
approval_mode="async", on_approval=handle_approval, on_denial=handle_denial)
# webhook
safe_refund = arden.guard_tool("stripe.issue_refund", issue_refund,
approval_mode="webhook", on_approval=on_approval, on_denial=on_denial)
For webhook setup (FastAPI, Flask, Django examples) see the Library Reference.
Framework integrations
LangChain and CrewAI — zero wrapping required
Arden automatically patches LangChain and CrewAI's base tool class when configure() is called. Every tool instance — including ones created after configure — has its calls intercepted.
import ardenpy as arden
arden.configure(api_key="arden_live_...")
# All LangChain / CrewAI tool calls in this process are now intercepted.
# No protect_tools(), no guard_tool(), no boilerplate.
Tool names in the dashboard match each tool's .name attribute directly (e.g. "issue_refund"). The API key already scopes calls to your agent, so no prefix is needed.
Install the optional framework dependencies if you don't already have them:
pip install "ardenpy[langchain]" # LangChain
pip install "ardenpy[crewai]" # CrewAI
If you need per-tool approval mode overrides, protect_tools() is still available — see the Library Reference.
OpenAI Chat Completions
from ardenpy.integrations.openai import ArdenToolExecutor
executor = ArdenToolExecutor(tool_name_prefix="support")
executor.register("issue_refund", issue_refund_fn)
executor.register("send_email", send_email_fn)
# In your loop:
result = executor.run(tc.function.name, json.loads(tc.function.arguments))
OpenAI Agents SDK
from ardenpy.integrations.openai import protect_function_tools
safe_tools = protect_function_tools([issue_refund, search], tool_name_prefix="support")
agent = Agent(name="SupportBot", tools=safe_tools)
pip install "ardenpy[openai-agents]"
See examples/ for runnable code for every integration.
Error handling
try:
result = safe_refund(150.0, customer_id="cus_abc")
except arden.PolicyDeniedError:
# blocked by policy, or denied by a human
except arden.ApprovalTimeoutError:
# nobody approved within max_poll_time (wait mode)
except arden.ArdenError:
# API/configuration error
Links
- Library Reference — full API docs
- Examples — runnable code
- Dashboard
- PyPI
- Support
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 ardenpy-0.4.1.tar.gz.
File metadata
- Download URL: ardenpy-0.4.1.tar.gz
- Upload date:
- Size: 42.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9aae56bbaf883c8e7dc54bcfe6e439a66d01552808d8dcb2e706355344232da6
|
|
| MD5 |
2b351a46902daaa0b62bf2c029962a60
|
|
| BLAKE2b-256 |
6563c927087be7afbd88af2967cd03e877361fb980e957bd7f5bc12c8006ae0a
|
File details
Details for the file ardenpy-0.4.1-py3-none-any.whl.
File metadata
- Download URL: ardenpy-0.4.1-py3-none-any.whl
- Upload date:
- Size: 25.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8cf4e42e260498b15bbbe76bc01d68a14bb909c0a4482a273c1581316a750f32
|
|
| MD5 |
1035746b44bbaeda8aab295735a72ce6
|
|
| BLAKE2b-256 |
43346bfd69870e4e674b6d161ea973484c26c2f189265b088bfb19d5f0f391d4
|