Documentation
Getting started

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.

1
Create an account and get your API key
Sign up at custodyn.app/signup.html. After verifying your email, go to Settings → API Keys to copy your key.
2
Install the SDK
Install via npm or pip depending on your agent's language.
3
Register your agent in the dashboard
Go to Agents → Add Agent. Give it a name and copy the Agent ID.
4
Wrap your agent actions with Custodyn
Every action your agent takes should call custodyn.check() before executing. That's it.
JavaScript
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);
}
Python
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
Getting started

Installation

The Custodyn SDK is open-source (MIT licensed) and available on npm and PyPI.

JavaScript / Node.js

npm
npm install custodyn
yarn
yarn add custodyn

Python

pip
pip install custodyn
Python 3.8+ required. The SDK works with or without the requests library — it falls back to urllib automatically.

Requirements

RuntimeMinimum versionNotes
Node.js16+ESM and CommonJS both supported
Python3.8+requests optional but recommended
BrowserSDK is server-side only
Getting started

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

1
Log in to your dashboard
2
Go to Settings → API Keys
3
Copy your key — it starts with as_live_

Using environment variables

Never hardcode your API key. Always use environment variables or a secrets manager.
.env
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.

Getting started

Core concepts

Gateway
Every agent action passes through the Gateway for policy checking before execution. Sub-5ms latency.
Policies
Rules that define what your agents can and cannot do. Set per-agent or globally across all agents.
Approvals
High-risk actions pause and wait for human sign-off before executing. Configurable per policy.
Audit trail
Every action is logged with timestamp, outcome, and SHA-256 hash. Tamper-evident and exportable.
Kill switch
Pause all agents instantly with one click. Resume when ready. No code changes required.
Risk scoring
Actions are automatically scored low / medium / high / critical based on category and target.

Action categories

CategoryDefault riskExamples
readLowRead file, query database, list repos
writeMediumCreate file, update record, push code
executeMediumRun script, call API, spawn process
sendHighSend email, post Slack message, send SMS
authHighLogin, OAuth flow, token exchange
deleteHighDelete file, drop table, remove record
payCriticalCharge card, wire transfer, refund
SDK

JavaScript SDK

The JS SDK works in Node.js with any AI framework — LangChain, OpenAI Assistants, custom agents, etc.

Initialisation

JavaScript
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

OptionTypeRequiredDescription
agentIdstringRequiredYour agent's ID from the dashboard
apiKeystringRequiredYour company API key starting with as_live_
serverUrlstringRequiredSet to https://custodyn.app in production
strictModebooleanOptionalDefault true. Block actions when server policy says block.
failClosedbooleanOptionalDefault true. Block actions if server is unreachable.

custodyn.check()

The main method. Call this before every agent action.

JavaScript
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

JavaScript
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}`);
  }
});
SDK

Python SDK

Works with CrewAI, AutoGen, LangChain, and any Python-based agent framework.

Python
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.

Python
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']
)
SDK

Framework plugins

Native plugins for popular AI frameworks. All plugins are included in the main SDK — no separate install needed.

OpenClaw

Python
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

Python
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

Python
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
Dashboard

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

1
Go to Agents in the dashboard sidebar
2
Click Add Agent
Give it a descriptive name — e.g. "billing-agent" or "email-assistant"
3
Copy the Agent ID
It starts with agt_. Use this in your SDK config.

Agent status

StatusMeaning
ActiveAgent is running and actions are being checked
PausedAgent is manually paused — all actions blocked
InactiveNo 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.

Dashboard

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:

1
Agent-specific policies first
Policies assigned to that specific agent are checked first. These take priority over global policies.
2
Global policies next
Policies that apply to all agents are evaluated if no agent-specific policy matched.
3
First match wins
Evaluation stops at the first matching policy. The action is allowed, blocked, or sent for approval based on that policy.
4
No match = allow
If no policy matches the action, it is allowed by default. Use a strict preset to flip this to deny-by-default.

Policy actions

ActionWhat happensUse when
BlockAction 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 approvalAction 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.
AllowAction 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.

CategoryDefault riskCovers
readLowReading files, querying databases, listing resources
writeMediumCreating or updating files, records, repositories
executeMediumRunning scripts, calling APIs, spawning processes
sendHighSending emails, Slack messages, SMS, webhooks
authHighLogin attempts, OAuth flows, token exchanges
deleteHighDeleting files, dropping tables, removing records
payCriticalCharging 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.

Target matching is substring-based. A blocked target of 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.

ConditionExampleMatches when
parameter.amount gt "1000"Approve large paymentsPayment amount exceeds $1,000
target contains "production"Block prod deletesTarget URL contains the word "production"
risk_level eq "critical"Approve critical actionsAction risk score is critical
parameter.count gt "100"Limit bulk opsBulk operation affects more than 100 records
Multiple conditions on a single policy use AND logic — all conditions must match for the policy to fire. To create OR logic, create two separate policies with the same action.

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:

Example — Finance agent policy stack
# 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.

1
Go to Policies → Groups tab
2
Create a group and add policies to it
For example: "Finance group" with payment approval + delete block policies.
3
Assign the group to one or more agents
All policies in the group apply to those agents. Update the group once — all agents update automatically.

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.

ExampleConfig
Max 10 emails per hourCategory: send | Limit: 10 | Window: 1 hour
Max 5 payments per dayCategory: pay | Limit: 5 | Window: 24 hours
Max 100 API calls per hourCategory: 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.

OptionBehaviour
Auto-deny after timeoutIf no one approves within N minutes, the action is automatically denied
Auto-approve after timeoutIf no one denies within N minutes, the action proceeds automatically
Escalate to another approverAfter 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.

1
Go to Policies → select a policy → enable Dry Run
2
Run your agent normally
Actions are evaluated but not blocked. Check Audit Logs to see which actions would have been caught.
3
Disable dry run when ready to enforce
The policy switches to live enforcement immediately.

Quick presets

Custodyn ships with six ready-to-apply policy presets for common scenarios:

PresetWhat it does
Approve all paymentsEvery pay action requires human approval before executing
Block production deletesAny delete targeting a "production" resource is permanently blocked
Approve bulk emailsAll send actions require approval
Approve large paymentsOnly payments over $1,000 require approval (compound condition)
Block script executionNo agent can run scripts or execute code automatically
Approve auth changesAll authentication actions require human sign-off
Presets are starting points. After applying a preset, you can edit, combine, or extend it — they work exactly like custom policies once applied.

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

Start with presets, then refine. Apply a preset that matches your risk level, run your agent in dry run mode for a day, review the logs, then tighten or loosen specific rules.
Use agent-specific allow policies as exceptions. Set a global block on a category, then create allow policies for trusted agents that legitimately need access.
Combine velocity limits with approval policies. Require approval for the first payment of the day, then velocity-limit subsequent ones — gives flexibility without removing oversight.
No policies = allow everything. Without any policies, all agent actions are allowed. Always set at least a global block on pay and delete before deploying agents to production.
Dashboard

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

FieldDescription
actionName of the action attempted
categoryAction category (read, write, execute, etc.)
targetWhat the action was targeting
outcomeallowed / blocked / pending_approval / approved / denied
risk_levellow / medium / high / critical
timestampISO 8601 UTC timestamp
hashSHA-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.

Dashboard

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

1
Go to the Dashboard — pending approvals appear at the top
2
Review the action details — agent, target, risk level, parameters
3
Click Approve or Deny
The agent is notified immediately and either proceeds or halts.
Approvals also appear in the Command Center — the floating panel accessible from any dashboard page via the orange button in the bottom right.
Dashboard

Team members

You can invite teammates to your Custodyn account. Each member gets a role that controls what they can see and do.

Roles

RolePermissions
OwnerFull access — billing, settings, team management, all agents and policies
AdminManage agents, policies, approvals. Cannot change billing or remove owner.
OperatorView agents and logs, approve/deny actions. Cannot create or delete policies.
ViewerRead-only access to dashboard, logs, and agents.

Inviting a member

1
Go to Settings → Team
2
Enter their email and select a role
3
They receive an invite email
The link is valid for 48 hours. They must have a Custodyn account to accept.
Dashboard

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.

API reference

Gateway API

Base URL: https://custodyn.app. All requests require X-API-Key header.

Check an action

POST/gateway/check

The core endpoint. Call this before every agent action.

Request
{
  "agent_id":   "agt_your_agent_id",
  "action":     "send_email",
  "category":   "send",
  "target":     "smtp.gmail.com",
  "parameters": { "to": "user@example.com" },
  "session_id": "uuid-v4"
}
Response — allowed
{
  "allowed":   true,
  "outcome":   "allowed",
  "action_id": "act_abc123",
  "risk":      "high"
}
Response — blocked
{
  "allowed":   false,
  "outcome":   "blocked",
  "reason":    "Policy: no delete on production targets",
  "action_id": "act_def456"
}
Response — pending approval
{
  "allowed":   false,
  "outcome":   "pending_approval",
  "action_id": "act_ghi789",
  "message":   "Waiting for human approval"
}

Poll approval status

GET/action/{action_id}

Poll this endpoint to check if a pending approval has been resolved.

API reference

Agents API

Manage agents programmatically via the REST API. All requests require X-API-Key header.

Register an agent

POST/agents/register
Request
{ "name": "billing-agent", "description": "Handles payment actions" }
Response
{ "agent_id": "agt_abc123", "name": "billing-agent", "status": "active" }

List agents

GET/dashboard/agents

Update agent status

POST/agents/{agent_id}/status
Request
{ "status": "paused" }  // or "active"
API reference

Policies API

List policies

GET/policies

Create a policy

POST/policies
Request
{
  "name": "Block production deletes",
  "category": "delete",
  "action": "block",
  "blockedTargets": ["prod-database", "s3://prod"],
  "active": true
}

Update a policy

POST/policies/{policy_id}

Delete a policy

DELETE/policies/{policy_id}

Toggle a policy on/off

POST/policies/{policy_id}/toggle
API reference

Logs & export API

Get audit logs

GET/dashboard/logs
Query paramDescription
limitNumber of results (default 50, max 500)
outcomeFilter by outcome: allowed, blocked, pending_approval
agent_idFilter by specific agent
categoryFilter by action category
sinceISO 8601 timestamp — return logs after this time

Export audit log (CSV)

GET/export/audit-log

Returns a CSV file with all audit log entries including integrity hashes.

Export SOC2 report

GET/export/soc2-report

Returns a structured JSON report suitable for SOC2 evidence packages.

Verify log integrity

GET/audit/integrity

Verifies the SHA-256 hash chain on your audit logs. Returns a pass/fail with any tampered entries flagged.

API reference

Webhooks

Custodyn can notify your systems when key events happen — approvals, blocks, agent status changes.

Setting up a webhook

1
Go to Settings → Webhooks
2
Enter your endpoint URL
Must be publicly accessible. HTTPS required in production.
3
Copy the webhook secret
Use it to verify that payloads are genuinely from Custodyn.

Webhook events

EventTriggered when
action.blockedAn agent action was blocked by a policy
action.approval_requiredAn action is waiting for human approval
action.approvedA pending action was approved
action.deniedA pending action was denied
agent.pausedAn agent was paused (manually or via kill switch)

Verifying webhook signatures

Node.js
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)
  );
}
Compliance

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

GET/export/soc2-report
This export provides evidence for SOC2 reviews. Custodyn does not hold a formal SOC2 Type II certification — the technical controls are in place and a formal audit is planned as we scale.
Compliance

HIPAA-ready controls

Custodyn implements the technical safeguards required to support HIPAA compliance in AI agent workflows.

HIPAA-ready, not HIPAA certified. Custodyn provides the technical controls to support your HIPAA compliance program. Custodyn is not a covered entity. Consult your compliance team for formal certification.

Technical controls in place

ControlImplementation
Access controlRole-based access (Owner, Admin, Operator, Viewer). API keys scoped per agent.
Audit loggingAll agent actions logged with timestamp, outcome, and integrity hash.
Tamper evidenceSHA-256 hash on every log entry. Logs are append-only.
Human approval gatesHigh-risk actions require human approval before execution.
Encryption in transitAll API traffic over TLS 1.3.

Check HIPAA status via API

GET/compliance/hipaa-status

Returns a checklist of which HIPAA-ready controls are active for your account.

Help

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.

Still stuck? Email support@custodyn.app with your company ID and the action ID from your logs.
Help

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.