Unleash the agent.
Leash the action.
Your support agent will eventually try to refund €2,400 to the wrong customer. Veritrellis turns that attempt into a log line instead of an incident — every risky action needs a signed, short-lived permit your own backend verifies. No valid permit, no action.
Nobody's agent is malicious.
It's worse than that — it's confident. Confident at 3 a.m. when nobody's reviewing. Confident about the bereavement-policy exception it just invented. Confident in front of your billing API, your account admin, your customer's inbox.
You gave it tools because tools are the point. But somewhere between "the agent decided" and "the refund executed," there's supposed to be a moment where something checks. For most teams right now, that moment is a system prompt.
A system prompt is a suggestion. A permit is a fact.
Every request. One enforcement boundary.
No permit, no action. If Veritrellis does not issue a valid signed permit, the gateway blocks execution. Doesn't matter who asked.
Not IAM. Not OPA. Not a workflow.
The execution boundary.
Existing tools identify, evaluate, approve, or log. You have five tools that almost do this — and "almost" is where the incident lives. Veritrellis creates the signed, action-scoped permit your execution layer must verify before any risky action runs.
| Tool | What it does | Where it stops | Veritrellis adds |
|---|---|---|---|
| IAM / RBAC | Proves caller identity and grants access | "Can call the refund API" isn't "should refund €1,200, to this account, today." Roles are set-up-time. Damage is action-time. | Action-scoped execution permit |
| OPA / policy engine | Evaluates rules and returns a decision | A decision is a return value. Your policy said no; the service three hops downstream never heard. | Signed permit + downstream verification |
| Workflow approvals | Routes human decisions through a queue | The approval lives in a ticket. The ticket doesn't stand between the agent and the database. | Fail-closed gateway check |
| Observability / logs | Records what happened after the fact | Past tense. Logs are how you write the postmortem, not how you avoid it. | Pre-execution authorization decision |
| Agent frameworks | Let agents propose and call tools | The agent decides what to attempt — and the agent is the thing you don't trust. | Independent enforcement boundary the agent can't bypass |
Start where it would hurt.
Pick the action where "the agent was confident" would be unacceptable in the postmortem. That's your first schema. Define and gate any action after that — financial, operational, or your own.
Refunds & credits
Money moves need explicit authorization.
Gate AI-proposed refunds above your threshold. Auto-allow low-risk amounts, require manager approval above threshold, and issue a signed permit your billing service verifies before processing.
Commitments
Binding commitments require a permit.
"We'll refund you." "Your price is locked." "Ships Friday." An AI promise is a company promise — a court already made an airline pay for one. Gate the send, not the sentiment.
Destructive changes
Production actions stay gated. Always.
Infra deployments, config mutations, data exports, and permission grants require a valid signed permit — or execution is blocked. Full stop.
define and gate any action your product performs — financial, operational, or your own
Five primitives. One unbroken chain.
Every authorization request moves through the same sequence. The primitives are discrete, composable, and individually observable.
Action Schema
The schema defines what the agent may even ask for.
Typed contract for every high-risk action. Validates payload structure, field constraints, and actor context before evaluation begins.
Policy Decision
Policy decides whether this exact request proceeds — allow, deny, or "a human looks first."
Rule-based evaluation engine. Each action is matched against versioned policies — returning allow, deny, or pending approval with a full decision trace.
Approval State
Approval has an owner, a clock, and an expiry. It physically cannot become a pile.
First-class approval routing to human reviewers. Configurable approver groups, escalation thresholds, and expiry windows.
Signed Permit
Not a flag. Not a row. A five-minute cryptographic fact.
A short-lived ES256 JWT issued only when a request is authorized. Contains action, request ID, actor, and expiry. Verified downstream before execution.
Audit Event
When the dispute comes — and it comes — this is what "authorized" looks like.
Every authorization attempt, approval decision, permit issuance, and gateway verification is recorded as an append-only audit event.
Policy evaluates. Permit issues. Audit records.
Every authorization produces three artefacts — a decision trace, a signed permit, and an append-only audit event.
Direct allow threshold
amount ≤ 100
Approval required
amount > 100 · route to finance
Default deny
fallback · no conditions
DECISION
pending_approval · execution blocked
JWT
eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI...
refund.create €350.00
agent:support-v2
refund-policy@v7 matched rule 2
· approval required
Routed to finance@acme.com
awaiting decision
Signed permit ES256
JWKS kid: wvt-key-1
Gateway verified permit
· action allowed
Most actions never meet a human. That's the point.
Approval isn't the product. It's one of three exits — and the rarest one.
€18 refund, eligible customer, clean history.
Policy matches, permit issues, money moves. Total human involvement: zero. Total elapsed time: the latency of one API call. Your agent stays fast — it just stops being unaccountable.
auto_allowed_under_threshold
€2,400 refund, requested very politely by a prompt injection.
Hard no, with a reason code. The agent gets a machine-readable rejection. The audit trail gets the attempt. You get to read about it Monday instead of explaining it Monday.
amount_exceeds_policy_limit
€350 — above auto-allow, below alarming.
Routed to support leads with the payload and the policy reason. Two-hour expiry. Approved? Permit. Ignored? Dead. Approval here has an owner, a clock, and an escalation path — it physically cannot become a pile.
pending: support_leads · expires 2h
Your agents keep drafting, deciding, doing. Veritrellis only shows up at the exact moment a guess is about to become a consequence.
The permit is real.
Not a flag. Not a lookup. A signed artifact.
Every authorized action produces a short-lived ES256 JWT. Your backend verifies the signature, the action type, the payload hash, and the expiry before execution. If any check fails — execution is blocked.
eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ind2dC1rZXktMSJ9.eyJqdGkiOiJwZXJtaXRfMDFIWFlaN0syTSIsImlzcyI6InZlcml0cmVsbGlzLmFpIiwic3ViIjoiYWdlbnQ6c3VwcG9ydC12MiIsImFjdCI6InJlZnVuZC5jcmVhdGUiLCJleHAiOjE3NDY0NTE2MjF9.SIGNATURE_TRUNCATED
{
"jti": "permit_01HZ8K2M",
"iss": "veritrellis.ai",
"sub": "agent:support-v2",
"act": "refund.create",
"payload_hash": "sha256:a3f2c8...",
"policy": "refund-policy@v7",
"policy_rule": 2,
"approver": "finance@acme.com",
"workspace": "acme-production",
"iat": 1746451321,
"exp": 1746451621,
"aud": "api.acme.com"
} Short-lived. Action-scoped. Cryptographically signed. Your gateway verifies this — not a flag, not a database lookup, not best-effort.
Two calls. Your architecture doesn't move.
authorizeRequest() before the risky path.
verifyPermit() before the write. Express,
Fastify, queue workers, webhook handlers, MCP tools — the gate goes where your writes
actually happen, which is rarely where the diagram pretends they happen.
import { createClient } from "@veritrellis/sdk-node";
const client = createClient({
apiKey: process.env.VERITRELLIS_API_KEY,
});
// Authorize before the agent acts
const result = await client.authorizeRequest({
actionType: "refund.create",
actor: { id: "agent:support-refund-agent" },
payload: {
amount: 350,
currency: "USD",
customer_id: "cus_456",
},
});
if (result.status === "allowed" && result.permit) {
await verifyPermit(result.permit);
await executeRefund(result.permit);
}// Your execution boundary — verify before
// any risky action runs
import { verifyPermit } from "@veritrellis/sdk-node";
app.post("/refunds", async (req, res) => {
const permit =
req.headers["x-veritrellis-permit"];
const result = await verifyPermit(permit, {
action: "refund.create",
payload: req.body,
audience: "api.acme.com" });
if (!result.valid) {
return res.status(403).json({
error: "execution_blocked",
reason: result.reason
});
}
await processRefund(req.body);
});Fail-closed. Always.
What breaks when we break.
You're considering putting us in front of refunds and production writes — so here's the table other vendors put behind an NDA, including the row about our own outage.
| Scenario | What happens |
|---|---|
| FAILS CLOSED Veritrellis unavailable | Gateway fails closed — no new permits, no new risky writes. Existing permits keep verifying locally against cached keys. Configure your own break-glass per action type; it's yours, and it's audited. |
| CACHED KEYS JWKS endpoint unavailable | Verification continues against cached keys within TTL; otherwise fails closed. |
| BLOCKED Permit expired | Signature verification fails — action blocked. TTL is configurable per policy. Default: 5 minutes. |
| BLOCKED Payload changed after approval | Payload hash mismatch — execution blocked even if permit was previously valid. |
| BLOCKED Duplicate execution attempt | Permit jti already consumed — replay blocked. Idempotency is enforced at the verification layer. |
| BLOCKED Approval denied by reviewer | No permit issued. Action never reaches the execution boundary. Audit event written. |
| FAILS CLOSED Approval timeout | Configurable expiry. Default behavior: deny. Action blocked, audit event written. |
| VERSIONED Policy changed after approval | Permit references policy version at time of issuance. Execution proceeds against that version. New policy applies to new requests. |
Every blocked execution writes an audit event. Nothing fails silently.
Admin app
A purpose-built interface for reviewing requests, managing policies, and inspecting the full audit trail.
agent:support-refund-agent
via veritrellis API
Reviewed order #refund_456. Cancellation confirmed. Customer eligible for refund.
Process refund $350.00 for order #refund_456 — cancellation approved.
agent:support-refund-agent
via veritrellis API
Reviewed order #refund_456. Cancellation confirmed. Customer eligible for refund.
Process refund $350.00 for order #refund_456 — cancellation approved.
Not another agent platform.
The execution boundary beneath them.
Agent platforms run workflows. Veritrellis enforces the authorization boundary on every high-risk action those workflows attempt to execute.
| Dimension | Agent platforms | Veritrellis |
|---|---|---|
| Primary function | Build and run agents | Permit execution of actions |
| Output | Internal approval flows | Signed execution permits |
| Scope | Workflow ownership | Action-boundary enforcement |
| Integration | Platform-specific integrations | SDK / REST API across any stack |
| Execution control | Best-effort guardrails | Cryptographically verified permits |
| Audit model | Platform logs | Immutable product audit trail |
What's true today.
No "designed to," no "intends to." Future tense is where trust goes to hedge. These controls exist now — ask every vendor in your execution path for this list. Including us, quarterly.
Signed Permits
Every authorization issues an ES256-signed JWT. Downstream code verifies the cryptographic signature — not just a flag or a database lookup.
JWKS Verification
SDK and middleware verify permits against a JWKS endpoint. Rotation is handled without redeployment. No shared secrets required.
Policy Versioning
Every policy change creates a new version. Decision traces reference the exact policy version that produced the outcome.
Approval Audit Trail
Every approval decision — who approved, when, and in response to which request — is recorded as an append-only audit event.
Sandbox / Production Separation
Environments are strict boundaries. Sandbox API keys and policies cannot issue permits valid against production endpoints.
Workspace-Scoped Keys
API keys are scoped to a workspace and environment. A compromised key cannot authorize actions outside its explicit scope.
On the roadmap
- SOC 2 Type I — in progress
- Third-party penetration test
- Audit export API
Pay per controlled action.
POC and evaluation
- 10 production controlled actions
- Unlimited sandbox evaluations
- 1 action type
- 1 active production policy
- Full sandbox environment for integration testing
One production approval rail for a small team.
- 500 production controlled actions/mo
- 5,000 sandbox evaluations/mo
- 5 members included (up to 15 at $10/extra)
- 1 workspace, 3 action types
- 5 active production policies
- $0.05/controlled action over 500
- 30-day audit retention
- Standard webhooks, basic policy simulation
The production permit rail for high-risk agent actions.
- 5,000 production controlled actions/mo
- 50,000 sandbox evaluations/mo
- 25 members included (up to 75 at $12/extra)
- 3 workspaces (up to 10 at $49/extra)
- 10 action types, 50 active production policies
- $0.015/controlled action over 5,000
- Approval groups, escalation rules
- Audit export, 1-year retention
Custom volume, SSO/SCIM, SLAs, and invoice billing.
- Custom controlled-volume and overage
- SSO, SCIM, advanced RBAC
- Audit streaming and custom retention
- Approval groups and escalation rules
- Dedicated SLA and support
- Invoice billing
All plans include ES256 signed permits, JWKS verification, and a full audit trail.
Building agents that touch production?
Let's talk about the one action type you'd gate first. 30 minutes, no deck, no pitch — just the problem.
Allow, pending, deny, and one failed payload-swap before your coffee's done.
Read the quickstartA €350 refund gets proposed, paused, approved, permitted, verified, and proven. Ninety seconds.
Watch the refund flowThirty minutes, your architecture, one insertion point. Worst case, you leave with a diagram.
Bring us your scariest action