Quick start
Custodyn sits between your AI agent and the outside world. Every action your agent attempts — sending an email, executing code, writing to a database — passes through Custodyn first. You set the rules. Custodyn enforces them.
You can be up and running in under 5 minutes.
custodyn.check() before executing. That's it.const { Custodyn } = require('custodyn'); const custodyn = new Custodyn({ agentId: 'agt_your_agent_id', apiKey: process.env.CUSTODYN_API_KEY, serverUrl: 'https://custodyn.app' }); // Before your agent executes any action: const result = await custodyn.check( 'send_email', // action name 'send', // category: read|write|execute|send|delete|pay|auth 'smtp.gmail.com' // target ); if (result.allowed) { // proceed with the action } else { // action was blocked or pending approval console.log(result.reason); }
from custodyn import Custodyn import os custodyn = Custodyn( agent_id='agt_your_agent_id', api_key=os.environ['CUSTODYN_API_KEY'], server_url='https://custodyn.app' ) # Before your agent executes any action: result = custodyn.check( 'send_email', # action name 'send', # category 'smtp.gmail.com' # target ) if result['allowed']: # proceed pass
Installation
The Custodyn SDK is open-source (MIT licensed) and available on npm and PyPI.
JavaScript / Node.js
npm install custodyn
yarn add custodyn
Python
pip install custodyn
requests library — it falls back to urllib automatically.Requirements
| Runtime | Minimum version | Notes |
|---|---|---|
| Node.js | 16+ | ESM and CommonJS both supported |
| Python | 3.8+ | requests optional but recommended |
| Browser | — | SDK is server-side only |
Authentication
Every API request must include your API key in the X-API-Key header. Never expose your API key in client-side code.
Getting your API key
as_live_Using environment variables
CUSTODYN_API_KEY=as_live_your_key_here CUSTODYN_AGENT_ID=agt_your_agent_id
Key rotation
You can rotate your API key at any time from Settings → API Keys. The old key is immediately invalidated. Update your environment variables before rotating.
Core concepts
Action categories
| Category | Default risk | Examples |
|---|---|---|
read | Low | Read file, query database, list repos |
write | Medium | Create file, update record, push code |
execute | Medium | Run script, call API, spawn process |
send | High | Send email, post Slack message, send SMS |
auth | High | Login, OAuth flow, token exchange |
delete | High | Delete file, drop table, remove record |
pay | Critical | Charge card, wire transfer, refund |
JavaScript SDK
The JS SDK works in Node.js with any AI framework — LangChain, OpenAI Assistants, custom agents, etc.
Initialisation
const { Custodyn } = require('custodyn'); const custodyn = new Custodyn({ agentId: process.env.CUSTODYN_AGENT_ID, // required apiKey: process.env.CUSTODYN_API_KEY, // required serverUrl: 'https://custodyn.app', // required in production strictMode: true, // default: true failClosed: true, // block if server unreachable });
Configuration options
| Option | Type | Required | Description |
|---|---|---|---|
agentId | string | Required | Your agent's ID from the dashboard |
apiKey | string | Required | Your company API key starting with as_live_ |
serverUrl | string | Required | Set to https://custodyn.app in production |
strictMode | boolean | Optional | Default true. Block actions when server policy says block. |
failClosed | boolean | Optional | Default true. Block actions if server is unreachable. |
custodyn.check()
The main method. Call this before every agent action.
const result = await custodyn.check( 'action_name', // string — descriptive name of the action 'category', // string — one of: read|write|execute|send|delete|pay|auth 'target', // string — what the action is acting on { // object — optional parameters amount: 500, currency: 'USD' } ); // result.allowed — boolean // result.outcome — 'allowed' | 'blocked' | 'pending_approval' // result.reason — string (if blocked) // result.actionId — string (for tracking approvals)
Handling approvals
const custodyn = new Custodyn({ agentId: process.env.CUSTODYN_AGENT_ID, apiKey: process.env.CUSTODYN_API_KEY, serverUrl: 'https://custodyn.app', onApprovalRequired: async (action) => { console.log(`Waiting for approval: ${action.action}`); // Notify your team, pause the agent, etc. }, onActionBlocked: (action) => { console.log(`Blocked: ${action.action} — ${action.reason}`); } });
Python SDK
Works with CrewAI, AutoGen, LangChain, and any Python-based agent framework.
from custodyn import Custodyn, PRESETS import os custodyn = Custodyn( agent_id=os.environ['CUSTODYN_AGENT_ID'], api_key=os.environ['CUSTODYN_API_KEY'], server_url='https://custodyn.app', fail_closed=True, ) # Check before any action result = custodyn.check( 'delete_user_record', 'delete', 'your-db-host/users' ) if not result['allowed']: raise PermissionError(result['reason'])
Using presets
Presets are pre-built policy bundles for common use cases.
from custodyn import Custodyn, PRESETS # Available: PRESETS['strict'], PRESETS['balanced'], PRESETS['permissive'] custodyn = Custodyn( agent_id='agt_your_agent_id', api_key='as_live_your_key', policies=PRESETS['balanced'] )
Framework plugins
Native plugins for popular AI frameworks. All plugins are included in the main SDK — no separate install needed.
OpenClaw
from custodyn import CustodynPlugin plugin = CustodynPlugin( agent_id='agt_your_agent_id', api_key=os.environ['CUSTODYN_API_KEY'], server_url='https://custodyn.app' ) # Returns: {'block': True, 'blockReason': '...'} or {'block': False} result = plugin.check(action, category, target)
CrewAI
from custodyn import register_custodyn # Call before your CrewAI crew runs register_custodyn( agent_id='agt_your_agent_id', api_key=os.environ['CUSTODYN_API_KEY'], server_url='https://custodyn.app' )
AutoGen
from custodyn import CustodynInterventionHandler handler = CustodynInterventionHandler( agent_id='agt_your_agent_id', api_key=os.environ['CUSTODYN_API_KEY'], server_url='https://custodyn.app' ) # Pass to your AutoGen agent as an intervention handler
Agents
An agent is any AI system you register with Custodyn. Each agent gets a unique ID that ties all its actions, logs, and policies together.
Registering an agent
agt_. Use this in your SDK config.Agent status
| Status | Meaning |
|---|---|
| Active | Agent is running and actions are being checked |
| Paused | Agent is manually paused — all actions blocked |
| Inactive | No actions in the last 7 days |
Trust score
Each agent has a trust score (0–100) based on its history — how many actions were blocked, approved, or flagged. A score below 50 triggers a warning. Scores update automatically as the agent operates.
Policies
Policies are rules that define what your agents can and cannot do. Every action an agent attempts is evaluated against your active policies before it executes. The first matching policy wins — evaluation stops there.
How evaluation works
When an agent calls custodyn.check(), Custodyn evaluates policies in this order:
Policy actions
| Action | What happens | Use when |
|---|---|---|
| Block | Action is rejected immediately. Agent receives a PermissionError. No override possible. | Actions that should never happen — deleting production data, paying without human sign-off, etc. |
| Require approval | Action is paused. Agent waits. A human approves or denies from the dashboard, Slack, or Teams. | High-risk actions that need a second pair of eyes before executing. |
| Allow | Action is explicitly permitted — skips all further policy checks. | Whitelisting specific trusted targets within a broader block rule. |
Action categories
Every policy targets one action category. Categories determine the default risk level and which actions match the policy.
| Category | Default risk | Covers |
|---|---|---|
read | Low | Reading files, querying databases, listing resources |
write | Medium | Creating or updating files, records, repositories |
execute | Medium | Running scripts, calling APIs, spawning processes |
send | High | Sending emails, Slack messages, SMS, webhooks |
auth | High | Login attempts, OAuth flows, token exchanges |
delete | High | Deleting files, dropping tables, removing records |
pay | Critical | Charging cards, wire transfers, refunds |
Target matching
Policies can match on the target of an action — the URL, hostname, file path, or service name. You can block or allow specific targets within a category.
production will match postgres://production-db/users, s3://prod-production-bucket, and https://api.production.myapp.com.Compound conditions
Standard policies match on category and target. Compound conditions let you add fine-grained rules based on action parameters — triggering a policy only when specific values are present.
| Condition | Example | Matches when |
|---|---|---|
parameter.amount gt "1000" | Approve large payments | Payment amount exceeds $1,000 |
target contains "production" | Block prod deletes | Target URL contains the word "production" |
risk_level eq "critical" | Approve critical actions | Action risk score is critical |
parameter.count gt "100" | Limit bulk ops | Bulk operation affects more than 100 records |
Setting up multiple policies
Most teams use a layered policy approach — broad global rules with specific agent-level exceptions. Here is an example setup for a finance team:
# Global policies (apply to all agents) 1. Block | category: delete | target: production → Block all prod deletes 2. Block | category: pay | amount gt 10000 → Block payments over $10k 3. Approve | category: pay | (any) → Approve all other payments 4. Approve | category: send | (any) → Approve all emails # Agent-specific: billing-agent (trusted, less restricted) 5. Allow | category: pay | target: stripe.com → Allow Stripe payments directly 6. Allow | category: send | target: @mycompany → Allow internal emails directly # Evaluation order for billing-agent sending to stripe.com: # Policy 5 matches first (agent-specific) → ALLOWED, stops here # Policies 3 and 4 never reached for this agent
Policy groups
Group multiple policies together and assign the whole group to an agent in one click. Useful when several agents share the same risk profile.
Velocity limits
Velocity limits cap how many times an action can run within a time window — independent of block/allow rules. Use these to prevent runaway agents.
| Example | Config |
|---|---|
| Max 10 emails per hour | Category: send | Limit: 10 | Window: 1 hour |
| Max 5 payments per day | Category: pay | Limit: 5 | Window: 24 hours |
| Max 100 API calls per hour | Category: execute | Limit: 100 | Window: 1 hour |
When a velocity limit is hit, the action is blocked with reason velocity_limit_exceeded and logged. The agent receives a PermissionError.
Escalations
Escalations define what happens when an approval is not acted on within a time window. Configure escalation chains under Policies → Escalations.
| Option | Behaviour |
|---|---|
| Auto-deny after timeout | If no one approves within N minutes, the action is automatically denied |
| Auto-approve after timeout | If no one denies within N minutes, the action proceeds automatically |
| Escalate to another approver | After N minutes, notify a secondary approver |
Compliance mapping
The Compliance tab maps your active policies to common compliance frameworks and shows a coverage score. Custodyn checks which controls your policies satisfy for SOC2, HIPAA, GDPR, and PCI-DSS and highlights gaps.
Dry run mode
Test a policy before enforcing it. In dry run mode, actions are evaluated against the policy but never actually blocked — you see what would have been blocked in the audit logs with outcome dry_run_blocked.
Quick presets
Custodyn ships with six ready-to-apply policy presets for common scenarios:
| Preset | What it does |
|---|---|
| Approve all payments | Every pay action requires human approval before executing |
| Block production deletes | Any delete targeting a "production" resource is permanently blocked |
| Approve bulk emails | All send actions require approval |
| Approve large payments | Only payments over $1,000 require approval (compound condition) |
| Block script execution | No agent can run scripts or execute code automatically |
| Approve auth changes | All authentication actions require human sign-off |
Policy conflicts
When two policies could match the same action, a conflict exists. Go to Policies → Conflicts tab to see all detected conflicts. Custodyn shows which policy wins (the one with higher priority or more specific target) and lets you resolve conflicts by adjusting priority or scope.
Tips for effective policies
pay and delete before deploying agents to production.Audit logs
Every action your agents attempt is logged — whether it was allowed, blocked, or sent for approval. Logs cannot be modified after creation.
Log fields
| Field | Description |
|---|---|
action | Name of the action attempted |
category | Action category (read, write, execute, etc.) |
target | What the action was targeting |
outcome | allowed / blocked / pending_approval / approved / denied |
risk_level | low / medium / high / critical |
timestamp | ISO 8601 UTC timestamp |
hash | SHA-256 integrity hash of the log entry |
Exporting logs
Go to Audit Logs → Export. Available formats: CSV, JSON, SOC2-compatible JSON. Exports include all fields including integrity hashes.
Approvals
When a policy requires approval, the action is paused and added to the approval queue. The agent waits until a human approves or denies it.
Approving or denying
Team members
You can invite teammates to your Custodyn account. Each member gets a role that controls what they can see and do.
Roles
| Role | Permissions |
|---|---|
| Owner | Full access — billing, settings, team management, all agents and policies |
| Admin | Manage agents, policies, approvals. Cannot change billing or remove owner. |
| Operator | View agents and logs, approve/deny actions. Cannot create or delete policies. |
| Viewer | Read-only access to dashboard, logs, and agents. |
Inviting a member
Settings
API Keys
Your API key authenticates all SDK and API requests. Go to Settings → API Keys to view or rotate your key. Treat it like a password — never commit it to version control.
Webhooks
Configure a webhook URL to receive real-time event notifications. Go to Settings → Webhooks, enter your endpoint URL, and copy the webhook secret to verify payloads.
Billing
View your current plan, usage, and upgrade options under Settings → Billing. All plans include a 14-day free trial. No credit card required to start.
Notification preferences
Configure where approval notifications are sent — email, Slack, or Microsoft Teams. Go to Settings → Notifications and enter your webhook URL.
Gateway API
Base URL: https://custodyn.app. All requests require X-API-Key header.
Check an action
The core endpoint. Call this before every agent action.
{
"agent_id": "agt_your_agent_id",
"action": "send_email",
"category": "send",
"target": "smtp.gmail.com",
"parameters": { "to": "user@example.com" },
"session_id": "uuid-v4"
}{
"allowed": true,
"outcome": "allowed",
"action_id": "act_abc123",
"risk": "high"
}{
"allowed": false,
"outcome": "blocked",
"reason": "Policy: no delete on production targets",
"action_id": "act_def456"
}{
"allowed": false,
"outcome": "pending_approval",
"action_id": "act_ghi789",
"message": "Waiting for human approval"
}Poll approval status
Poll this endpoint to check if a pending approval has been resolved.
Agents API
Manage agents programmatically via the REST API. All requests require X-API-Key header.
Register an agent
{ "name": "billing-agent", "description": "Handles payment actions" }{ "agent_id": "agt_abc123", "name": "billing-agent", "status": "active" }List agents
Update agent status
{ "status": "paused" } // or "active"Policies API
List policies
Create a policy
{
"name": "Block production deletes",
"category": "delete",
"action": "block",
"blockedTargets": ["prod-database", "s3://prod"],
"active": true
}Update a policy
Delete a policy
Toggle a policy on/off
Logs & export API
Get audit logs
| Query param | Description |
|---|---|
limit | Number of results (default 50, max 500) |
outcome | Filter by outcome: allowed, blocked, pending_approval |
agent_id | Filter by specific agent |
category | Filter by action category |
since | ISO 8601 timestamp — return logs after this time |
Export audit log (CSV)
Returns a CSV file with all audit log entries including integrity hashes.
Export SOC2 report
Returns a structured JSON report suitable for SOC2 evidence packages.
Verify log integrity
Verifies the SHA-256 hash chain on your audit logs. Returns a pass/fail with any tampered entries flagged.
Webhooks
Custodyn can notify your systems when key events happen — approvals, blocks, agent status changes.
Setting up a webhook
Webhook events
| Event | Triggered when |
|---|---|
action.blocked | An agent action was blocked by a policy |
action.approval_required | An action is waiting for human approval |
action.approved | A pending action was approved |
action.denied | A pending action was denied |
agent.paused | An agent was paused (manually or via kill switch) |
Verifying webhook signatures
const crypto = require('crypto'); function verifyWebhook(payload, signature, secret) { const expected = crypto .createHmac('sha256', secret) .update(payload) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(expected), Buffer.from(signature) ); }
SOC2 audit export
Custodyn can generate a SOC2-compatible audit report from your agent activity logs. The export includes all actions, outcomes, timestamps, integrity hashes, and a control mapping.
Exporting via dashboard
Go to Audit Logs → Export → SOC2 Report. The report downloads as a structured JSON file.
Exporting via API
HIPAA-ready controls
Custodyn implements the technical safeguards required to support HIPAA compliance in AI agent workflows.
Technical controls in place
| Control | Implementation |
|---|---|
| Access control | Role-based access (Owner, Admin, Operator, Viewer). API keys scoped per agent. |
| Audit logging | All agent actions logged with timestamp, outcome, and integrity hash. |
| Tamper evidence | SHA-256 hash on every log entry. Logs are append-only. |
| Human approval gates | High-risk actions require human approval before execution. |
| Encryption in transit | All API traffic over TLS 1.3. |
Check HIPAA status via API
Returns a checklist of which HIPAA-ready controls are active for your account.
Troubleshooting
Emails not arriving (verification or reset)
If verification or password reset emails are not arriving, check your spam folder first. If still missing, wait 2 minutes and use the Resend verification email link on the login page. Contact support@custodyn.app if the issue persists.
Actions always blocked even with no policies
Check that failClosed is not set to true while your server URL is misconfigured. In production always use serverUrl: 'https://custodyn.app'. If testing locally with a self-hosted instance, point to your local server URL instead.
Agent ID not found
The agent must be registered in the dashboard before using it in the SDK. Go to Agents → Add Agent, and copy the generated Agent ID.
SDK prints to console in production
The SDK logs initialization info to console. To suppress: set NODE_ENV=production or redirect stdout in your process manager.
Approval never resolves
The agent polls /action/{action_id} for approval status. Check that the approver has reviewed the action in the dashboard. Approvals do not expire by default.
FAQ
Does Custodyn add latency to my agent?
The gateway check takes under 5ms on average. For most AI agent workflows — where the agent itself takes seconds per step — this is negligible.
What happens if Custodyn goes down?
With failClosed: true (default), all actions are blocked when the server is unreachable — the safe choice. With failClosed: false, actions fall back to local policy evaluation.
Is the SDK open source?
Yes. The SDK (custodyn.js and custodyn.py) is MIT licensed and available on GitHub. The backend platform is proprietary.
Can I self-host Custodyn?
Not currently. The backend is a managed service. The SDK is open-source so you can inspect exactly what it sends to our servers.
How are API keys stored?
API keys are stored as SHA-256 hashes in our database — never in plaintext. Even in the unlikely event of a database breach, your keys cannot be recovered.
Can I use Custodyn with any AI framework?
Yes. The core SDK works with any framework — you just call custodyn.check() before each action. Native plugins are available for OpenClaw, CrewAI, and AutoGen.