Verdict.
DocumentationDeveloper guide
DocumentationDeveloper guide

VERDICT DEVELOPER DOCUMENTATION

Build with confidence.
Govern every action.

Integrate Verdict into your agent or application. Evaluate tool calls before execution, route sensitive actions for human review, and keep a verifiable decision record.

Python SDK TypeScript SDK source DPoP-bound credentials
01Evaluate before execution
02Pause for human judgment
03Record the outcome
01

YOUR FIRST GUARDED ACTION

Quickstart

Go from a new workspace to a protected tool call in a few steps.

1

Create your workspace

Create a Verdict account. New organizations start on the Developer free tier.

Create an account
2

Model your application

In Organization, add a capability, team, and application. This hierarchy scopes credentials and policy.

Workspace setup
3

Define a policy

Use Policies to configure tool patterns, limits, and allow, escrow, or kill CEL expressions.

Open policy controls
4

Issue application credentials

In Settings, select the exact application and environment, then create and securely store its one-time credential bundle.

Credential setup
5

Wrap the side effect

Install an SDK, configure its server-side credentials, and place the guard around the function that performs the real-world action.

See the Python example

Try safely first. Use a development environment and a non-production tool implementation while validating policies and approval behavior.

02

RUNTIME & PACKAGING

Install an SDK

Python is an editable local package. TypeScript is currently distributed as repository source, not a published npm package.

Py

Python

Python 3.10 or newer. Install from the repository root.

Install Python SDKshell
pip install -e ./sdks/python
Installs httpx, PyJWT, and cryptography dependencies
TS

TypeScript / Node.js

Use the SDK source in this repository from a server-side Node.js application.

Source importtypescript
import { VerdictTypeScriptSDK } from "./sdks/typescript/src";
No npm package is published yet

Server-side only. Both SDKs require client credentials and a private DPoP key. Never bundle them into a browser application or expose credentials to end users.

03

ORGANIZATION MODEL

Set up your workspace

Use the hierarchy to define ownership boundaries and scope machine credentials.

01OrganizationTenant boundary, members, and plan
02CapabilityA business area or class of work
03TeamA group responsible for the capability
04ApplicationAn agent or service that invokes guarded tools

Environments

Credential bundles are scoped to one environment. The console supports DEV, STAGING, SHADOW, and PROD. Create a separate bundle per environment; do not reuse a development key in production.

Start with the plan limits

New organizations receive Developer: 10,000 governed calls per calendar month, 1 capability, 2 teams, and 3 applications. Members are unlimited. Limits are displayed in plan comparison and workspace settings.

04

MACHINE IDENTITY

Issue and protect credentials

Each bundle binds an OAuth client to one application, environment, and registered DPoP key.

  1. 01
    Select the scope

    Choose the capability, team, application, and environment in the console workspace bar.

  2. 02
    Generate once, store immediately

    Settings shows the client secret and private keys only in the creation response. Copy the bundle into a secret manager; Verdict cannot retrieve it later.

  3. 03
    Configure your runtime

    Load the values into server-side environment variables or your deployment platform’s secret store.

  4. 04
    Rotate deliberately

    Issue a replacement, update the application, verify it, then revoke the old key. Suspended credentials can be resumed; revocation is permanent.

Runtime environmentdotenv
VERDICT_BASE_URL=https://your-verdict-host
VERDICT_CLIENT_ID=your_client_id
VERDICT_CLIENT_SECRET=load_from_secret_manager
VERDICT_DPOP_PRIVATE_KEY=load_from_secret_manager

Token lifetime: access tokens last 5 minutes. Suspending or revoking a client prevents new token exchanges; already-issued tokens may remain valid until they expire.

05

DETERMINISTIC RULES

Policies and CEL expressions

Policies combine a scope, matching tool pattern, rate and session limits, and optional CEL decisions.

SettingPurposeExample
ScopeWhere the rule appliesORG, CAPABILITY, TEAM, APP
Tool patternTool name to match* or payments.create_transfer
EnvironmentDeployment environment or all environmentsDEV, PROD, ALL
EnforcementApply a decision or record a shadow resultENFORCE / SHADOW
Velocity limitsCalls per minute and per-session spend ceiling30 calls/min; 5000 USD

CEL variables and rule fields

Expressions can read args (proposed tool arguments), before (pre-flight snapshot), env (credential environment), and user (end-user identifier). Set allow, escrow, and kill expressions in the policy editor.

Example policy expressionscel
// Allow a transfer only below the per-action threshold
args.amount_usd <= 100.0

// Hold larger transfers for review
args.amount_usd > 100.0

// Block a transfer to a restricted destination
args.recipient_id == "restricted_account"

Rule ordering: matching policies are evaluated in ascending priority order. For each policy, kill is checked before escrow, then allow. Test overlapping scopes and rules in development before enforcing them in production.

06

PYTHON SDK

Guard a Python function

The decorator evaluates the request before calling your function and applies approved argument modifications.

Guard a transfer functionpython
import os
from verdict_sdk import (
    VerdictClient,
    VerdictEscrowRejectedError,
    VerdictPolicyBlockedError,
)

verdict = VerdictClient(
    base_url=os.environ["VERDICT_BASE_URL"],
    client_id=os.environ["VERDICT_CLIENT_ID"],
    client_secret=os.environ["VERDICT_CLIENT_SECRET"],
    dpop_private_key_b64=os.environ["VERDICT_DPOP_PRIVATE_KEY"],
    agent_id="payments-agent",
)

@verdict.guard(
    tool_name="payments.create_transfer",
    risk_category="FINANCIAL",
    value_field="amount",
)
def create_transfer(amount: float, currency: str, recipient_id: str):
    # This function is called only after the Verdict decision allows it.
    return payment_provider.create_transfer(
        amount=amount,
        currency=currency,
        recipient_id=recipient_id,
    )

try:
    transfer = create_transfer(
        amount=125.00,
        currency="USD",
        recipient_id="vendor_4821",
    )
except VerdictPolicyBlockedError as error:
    logger.warning("Transfer blocked: %s", error.reason)
except VerdictEscrowRejectedError as error:
    logger.info("Transfer rejected by %s", error.approver)

Useful decorator options

  • tool_name — stable name matched by policies
  • risk_category — classification recorded with the action
  • value_field — function argument used as monetary exposure
  • pre_flight_fn — capture state for review and before/after diffs
  • rollback_fn — register an application compensation callback

Expected exceptions

  • VerdictPolicyBlockedError — the kill switch or policy blocks execution
  • VerdictEscrowRejectedError — a reviewer rejects the action
  • VerdictEscrowTimeoutError — approval does not resolve in time
  • Network and HTTP errors — evaluation or downstream request failed

The Python client is synchronous. Its escrow helper retries the long-poll endpoint when it returns HTTP 408, up to its configured wait deadline. Keep the guarded operation idempotent where possible and make the surrounding job timeout longer than the expected approval window.

07

TYPESCRIPT SDK

Guard an async function

The current TypeScript SDK source targets server-side Node.js and wraps promise-returning functions.

Guard an async transfertypescript
import { VerdictTypeScriptSDK } from "./sdks/typescript/src";

const verdict = new VerdictTypeScriptSDK({
  baseUrl: process.env.VERDICT_BASE_URL,
  clientId: process.env.VERDICT_CLIENT_ID!,
  clientSecret: process.env.VERDICT_CLIENT_SECRET!,
  dpopPrivateKeyB64: process.env.VERDICT_DPOP_PRIVATE_KEY!,
  agentId: "payments-agent",
});

const createTransfer = verdict.guard(
  {
    toolName: "payments.create_transfer",
    riskCategory: "FINANCIAL",
    valueField: "amount",
  },
  async (args: {
    amount: number;
    currency: string;
    recipientId: string;
  }) => paymentProvider.createTransfer(args),
);

try {
  const transfer = await createTransfer({
    amount: 125,
    currency: "USD",
    recipientId: "vendor_4821",
  });
} catch (error) {
  // Evaluation, kill-switch, escrow, and downstream errors reject the promise.
  logger.error({ error }, "Guarded transfer did not complete");
}

Source distribution: the TypeScript SDK lives under sdks/typescript/src in this repository and is not published to npm. Vendor or build the source into your server-side application; keep Node’s crypto and fetch available.

The SDK caches its DPoP-bound access token until shortly before expiry. A blocked decision, rejected approval, API error, or failure in the wrapped function rejects the returned promise; handle failures at the caller boundary.

08

FROM REQUEST TO RECORD

Understand the decision lifecycle

Evaluation is a gate before your side effect, not a replacement for your application’s own authorization or validation.

ALLOWED

Continue

The SDK invokes the wrapped tool function with the proposed arguments.

SHADOW_LOGGED

Observe

The decision is recorded without holding the action. The function proceeds; shadow mode is not a production safety barrier.

ESCROW_PENDING

Wait for review

The SDK waits for an authorized reviewer. A rejection prevents the wrapped function from running.

MODIFIED_APPROVED

Use reviewed arguments

If a reviewer edits the payload, the SDK passes the modified arguments to the wrapped function.

KILL_SWITCH_BLOCKED

Stop

The SDK raises/rejects before calling the wrapped function.

After the side effect: the SDK submits the execution output as a snapshot. If the external system succeeds but the snapshot commit fails, handle that as an operational reconciliation case; do not assume the external action was rolled back.

09

MACHINE-TO-MACHINE API

API reference

SDKs handle token exchange and DPoP proofs. These endpoints describe the current guarded-action path.

POST/oauth2/tokenExchange scoped client credentials and a DPoP proof for a 5-minute access token.
POST/v1/guard/evaluateEvaluate proposed tool arguments against policies, velocity controls, and kill switches.
GET/v1/guard/escrow/{execId}/waitLong-poll for an escrow resolution. A 408 response means the wait interval ended without resolution.
POST/v1/guard/commit-snapshotRecord the downstream execution output after the guarded function succeeds.

Evaluation request

Send an OAuth access token as Authorization: DPoP <token> and a fresh DPoP proof for the request method and URL. The evaluation body includes action identity, original arguments, optional pre-flight state, and monetary exposure.

Evaluate action requestjson
{
  "correlation_id": "corr-8f91a203",
  "agent_id": "payments-agent",
  "session_id": "sess_92bc15a1",
  "end_user_id": "user_4821",
  "tool_name": "payments.create_transfer",
  "risk_category": "FINANCIAL",
  "monetary_value_usd": 125,
  "original_args": {
    "amount": 125,
    "currency": "USD",
    "recipient_id": "vendor_4821"
  },
  "pre_flight_snapshot": {
    "available_balance": 840.25
  }
}

Decision response

Example escrow responsejson
{
  "execution_id": "8bb7e9f4-4d3e-4e8f-a227-94716e7a940f",
  "verdict_status": "ESCROW_PENDING",
  "matched_policy_id": "1ca02b3c-...",
  "computed_diff": {
    "available_balance": {
      "before": 840.25,
      "proposed": 125
    }
  },
  "hot_path_latency_ms": 8.42,
  "current_rpm": "1",
  "session_spend_usd": "125.00",
  "record_hash": "..."
}

The API returns HTTP 200 for a successfully evaluated decision, including block and escrow statuses. Inspect verdict_status; do not treat HTTP success alone as permission to execute.

10

PRODUCTION READINESS

Security practices

Verdict adds a policy decision point. Your service still owns its identity, validation, and operational safety.

Protect the client bundle

Store the secret and Ed25519 private key in a secret manager. Never commit them, log them, or send them to a browser.

Use HTTPS

Use an HTTPS Core origin in deployed environments. The local Docker host may use an internally trusted TLS certificate.

Scope narrowly

Issue separate credentials for each application and environment. Rotate or revoke credentials when ownership changes.

Validate independently

Validate tool arguments and user authorization in your own service. Do not rely on a policy rule as the only input check.

Payload privacy: arguments, policy decisions, and execution outcomes contribute to Verdict’s audit trail. Minimize sensitive data in tool arguments and snapshots; never send credentials, payment-card data, or secrets as action fields.

11

COMMON SETUP ISSUES

Troubleshooting

Use these checks to narrow down configuration, authentication, and policy issues.

Token exchange returns 401

Check that the client ID, secret, and private key belong to the same generated bundle and that the credential is active. Verify the SDK is using the correct Core base URL and that its DPoP proof is signed by the registered private key.

Evaluation returns 401 or invalid DPoP

Confirm the SDK sends Authorization: DPoP with a current access token and generates a new proof for the exact HTTP method and URL. Avoid URL rewrites between the client and Core that alter the proof-bound target.

The tool is blocked or unexpectedly held

Review the application’s environment, tool name, matching scope, policy priority, CEL expressions, velocity limits, and kill-switch state. Start with a development credential and inspect the execution trace.

Escrow does not resume

Verify that an authorized reviewer can access the escrow queue and resolve the pending action. The wait endpoint uses bounded long-poll requests; application and worker timeouts must account for human response time.

Local Docker SDK cannot reach Verdict

Use the Core origin reachable from the SDK process, not the console’s browser proxy path. In the supplied local setup this is typically https://verdict.local; make sure the local TLS certificate is trusted by the runtime.

Why does the TypeScript SDK import fail?

The SDK is source-only and not published as an npm dependency. Include or build sdks/typescript/src within your Node.js project and resolve the import to that source or its compiled output.

Verdict documentationBuilt from the current product and SDK implementation.
Back to Verdict