Documentation

Arden Python SDK

Complete reference for the ardenpy SDK — secure your AI agents with runtime policy enforcement.

Introduction

The Arden Python SDK provides runtime security for AI agents by enforcing policies on every tool call. This document covers every public function, class, parameter, return value, exception, and behavioral detail.

How Arden Works

Every tool call protected by Arden is evaluated against your configured policies before execution. The policy engine can allow, block, or require human approval for each action.

Installation

bash
pip install ardenpy

Requires Python 3.8 or later.

How It Works

Every tool call protected by Arden follows this sequence:

  1. Your code calls the wrapped function (e.g. safe_refund(150.0, customer_id="cus_abc")).
  2. The SDK sends the tool name and all arguments to the Arden policy engine.
  3. The policy engine evaluates the call against the rules you configured in the dashboard for this agent.
  4. One of three decisions is returned:
    • allow — the SDK immediately executes the original function and returns its result.
    • block — the SDK raises PolicyDeniedError without executing the function.
    • requires_approval — a human must approve or deny the call on the Arden dashboard before anything executes.

Important: The original function is never executed unless the policy explicitly allows it or a human approves it.

Configuration

Configure the SDK once at application startup, before any calls to guard_tool().

configure()

python
ardenpy.configure(
    api_key: str | None = None,
    api_url: str | None = None,
    environment: str | None = None,
    timeout: float | None = None,
    poll_interval: float | None = None,
    max_poll_time: float | None = None,
    retry_attempts: int | None = None,
) -> ArdenConfig

Sets the global SDK configuration. Returns the resulting ArdenConfig instance.

Parameters

ParameterTypeDefaultDescription
api_keystrARDEN_API_KEY env varYour agent's API key. Keys beginning with arden_test_ automatically set environment="test".
api_urlstrAuto-set from environmentBase URL for the Arden API. Override only if self-hosting.
environmentstr"live"Either "test" or "live". Auto-detected from the API key prefix when possible.
timeoutfloat30.0Seconds before an individual HTTP request to the Arden API times out.
poll_intervalfloat2.0Seconds between status checks when polling for approval in wait or async modes.
max_poll_timefloat300.0Maximum total seconds to wait for a human decision before raising ApprovalTimeoutError.
retry_attemptsint3Number of times to retry a failed HTTP request before raising ArdenError.

Returns

ArdenConfig

Raises

ValueErrorif api_key is not provided and ARDEN_API_KEY is not set, or if any parameter value is invalid.

Example

python
import ardenpy as arden

arden.configure(
    api_key="arden_live_3e6159f645814adfa86b01f8c368d503",
    timeout=60.0,
    max_poll_time=600.0,
)

Notes

  • configure() must be called before any guard_tool() call.
  • Calling configure() a second time overwrites the previous configuration globally.
  • The api_key can also be set via the ARDEN_API_KEY environment variable.

guard_tool()

python
ardenpy.guard_tool(
    tool_name: str,
    func: Callable,
    approval_mode: str = "wait",
    on_approval: Callable[[WebhookEvent], None] | None = None,
    on_denial: Callable[[WebhookEvent], None] | None = None,
) -> Callable

Wraps func with Arden policy enforcement. Returns a new callable with the same signature as func. The original function is not modified.

Parameters

ParameterTypeDefaultDescription
tool_namestrThe name used to look up this tool's policy in the dashboard.
funcCallableThe function to protect. Must be a plain Python callable.
approval_modestr"wait"How the SDK behaves when a policy decision of requires_approval is returned. One of "wait", "async", or "webhook".
on_approvalCallableNoneRequired when approval_mode is "async" or "webhook". Called when a human approves the action.
on_denialCallableNoneRequired when approval_mode is "async" or "webhook". Called when a human denies the action.

Returns

A callable with the same signature as func.

Raises

ArdenErrorSDK is not configured, or API communication failed.
PolicyDeniedErrorPolicy decision is block, or a human denied the action (wait mode only).
ApprovalTimeoutErrorNo human decision within max_poll_time (wait mode only).

Example

python
import ardenpy as arden

arden.configure(api_key="arden_live_...")

def issue_refund(amount: float, customer_id: str) -> dict:
    # real implementation
    return {"refund_id": "re_123", "amount": amount}

safe_refund = arden.guard_tool("stripe.issue_refund", issue_refund)

# Later, in your agent or request handler:
result = safe_refund(150.0, customer_id="cus_abc")

Approval Modes

When a policy decision of requires_approval is returned, the SDK's behavior depends on the approval_mode you set on guard_tool().

Wait Mode

python
approval_mode="wait"   # default

Behavior: Blocks the calling thread. Polls the Arden API every poll_interval seconds until a human approves or denies the action on the dashboard, or until max_poll_time seconds have passed.

  • If approved: executes func and returns its result.
  • If denied: raises PolicyDeniedError.
  • If max_poll_time is exceeded: raises ApprovalTimeoutError.

When to use: Scripts, CLI tools, synchronous web request handlers, or any context where blocking the current thread is acceptable.

Async Mode

python
approval_mode="async",
on_approval=...,
on_denial=...,

Behavior: Returns a PendingApproval object immediately. A daemon background thread begins polling for the approval decision. When a human acts on the dashboard, the thread calls either on_approval or on_denial.

When to use: Long-running services (agents, workers) where you cannot block the main thread but also don't have an HTTP server to receive webhooks.

Webhook Mode

python
approval_mode="webhook",
on_approval=...,
on_denial=...,

Behavior: Returns a PendingApproval object immediately. No background thread is started. Instead, when a human acts on the Arden dashboard, the Arden backend makes an HTTP POST to the webhook URL you configured for this agent in the dashboard.

When to use: Production services with a publicly reachable HTTP endpoint, or any scenario where you want push-based delivery without long-lived polling threads.

Exceptions

All exceptions inherit from ArdenError, which itself inherits from Exception.

ArdenError

python
class ArdenError(Exception): ...

Base class for all Arden SDK exceptions. Catch this to handle any Arden-related error in one place.

PolicyDeniedError

python
class PolicyDeniedError(ArdenError):
    tool_name: str

Raised when a tool call is blocked, either automatically by policy (block decision) or because a human denied it on the dashboard (wait mode).

ApprovalTimeoutError

python
class ApprovalTimeoutError(ArdenError):
    action_id: str
    timeout: float

Raised in wait mode when no human decision is received within max_poll_time seconds.

Error Handling Patterns

Pattern 1: Handle all decisions at the call site (wait mode)

python
def process_customer_request(amount: float, customer_id: str):
    try:
        result = safe_refund(amount, customer_id=customer_id)
        return {"ok": True, "refund": result}

    except arden.PolicyDeniedError:
        return {"ok": False, "reason": "refund_not_allowed"}

    except arden.ApprovalTimeoutError as e:
        return {"ok": False, "reason": "approval_timeout", "action_id": e.action_id}

    except arden.ArdenError as e:
        logger.error(f"Arden API error: {e}")
        return {"ok": False, "reason": "policy_check_failed"}

Pattern 2: Deferred handling (async/webhook mode)

python
# Tool is wrapped once at startup
safe_refund = arden.guard_tool(
    "stripe.issue_refund",
    issue_refund,
    approval_mode="webhook",
    on_approval=handle_refund_approved,
    on_denial=handle_refund_denied,
)

# At call time, only check for immediate blocks
def process_customer_request(amount: float, customer_id: str):
    try:
        result = safe_refund(amount, customer_id=customer_id)
    except arden.PolicyDeniedError:
        return {"ok": False, "reason": "refund_not_allowed"}

    if isinstance(result, arden.PendingApproval):
        return {"ok": True, "status": "pending", "action_id": result.action_id}

    return {"ok": True, "refund": result}

Environments

Arden has two isolated environments. Each has its own API endpoint, API keys, agents, policies, and actions.

EnvironmentAPI URLKey prefix
Testhttps://api-test.arden.sharden_test_
Livehttps://api.arden.sharden_live_

Recommended Setup

python
import os
import ardenpy as arden

# Use test environment in development, live in production.
# The key prefix determines the environment automatically.
arden.configure(api_key=os.environ["ARDEN_API_KEY"])

Set ARDEN_API_KEY=arden_test_... in development and ARDEN_API_KEY=arden_live_... in production. No code changes needed.

For the dashboard, API key management, and policy configuration, see app.arden.sh.
For support, contact team@arden.sh.