A denied action never runs.
A register tells you what an agent should do. Enforcement makes it true. Castle decides at the policy decision point and enforces at the action boundary: the agent's runtime asks Castle before an action executes, and a deny stops the action before it happens, not in a log entry after it happened.
Current status, stated plainly
The enforcement surfaces described here are built and tested and in early access. Castle is not yet live-proven in a customer runtime, and it holds no certifications. Ask which surfaces are live for your deployment.
Decide at the policy decision point, enforce at the action boundary
Castle separates the two jobs cleanly. Castle is the policy decision point: it holds the registries, the policy rules, and the decision log, and it answers one question: authorize(agent, tool, data, action) returns allow or deny. The enforcement point is a thin hook installed where the agent actually acts: in the process, in front of the tool server, or around the runtime's tool registry.
This is the policy-as-code pattern, built for agents. The hook does no reasoning of its own. It asks, and it refuses to proceed on a deny. That separation is what makes the system auditable: every decision comes from one place, with one log, under one set of rules you can read.
Deterministic, and computed outside the prompt
Decisions come from fixed rules evaluated over declared facts: the agent's registered tools, data access, and allowed actions, the data classifications involved, the vendor's review status, and the policy gates that apply. No model output ever sets a binding decision.
That design choice has a security consequence worth being precise about: because the decision is computed outside the prompt, prompt injection cannot move it. An attacker who fully controls an agent's context can make the agent ask for something it should not have. They cannot make Castle say yes. The same inputs produce the same decision, every time, and you can read the rule that produced it.
Five ways to install the boundary, plus one for everything else
SDK guard
A guard inside your agent code wraps tool calls and raises on a deny. The tightest integration: the call never leaves the process, and the deny is an exception your code handles like any other.
Drop-in MCP gateway
A gateway that sits in front of any MCP tool server. The agent connects to the gateway instead of the server; every tool call is authorized before it is forwarded. No changes to the agent and no changes to the tool server. It runs over both transports an MCP host uses, local stdio and remote HTTP/SSE, so a hosted or networked tool server is governed exactly the same way as a local one, fail-closed included.
ARI runtime adapter
An adapter that wraps the tool registry of an ARI-compatible agent runtime, so every registered tool is governed at the registry level. Agents built on the runtime inherit enforcement without knowing it exists.
OpenAI Agents SDK adapter
An adapter that hooks the tool layer of agents built on the OpenAI Agents SDK, so every tool call is authorized before it executes. Keep the framework you already use; add the boundary.
LangChain / LangGraph adapter
The same boundary for LangChain and LangGraph agents: each tool call is checked against the agent's registered identity and declared reach before it runs, with no rework of your chains or graphs.
REST policy-decision endpoint
For everything else, a plain REST endpoint answers the same authorize question. Any runtime that can make an HTTP call can install the boundary.
All five surfaces, and the REST endpoint, call the same decision point and land on the same log, so you can mix them: an SDK guard in the agents you build, the gateway in front of the tools you buy, a framework adapter where a fleet already runs. The decision is computed on the agent's registered identity and the tool name, never taken from the client stream. Model allowlists in authorize() policies govern which models may be used per use case, so routing is policy, not an afterthought.
Blocked means blocked, and the gateway fails closed
- A denied action never runs. The hook blocks before execution. This is prevention, not detection: there is no window where the action happened and the log caught up later.
- The gateway fails closed. If the decision service is unreachable, the gateway refuses the call rather than waving it through. An outage degrades to safety, not to an ungoverned hour.
- Reaching past the register is recorded. When an agent requests a tool or data class outside what it declared, the call is blocked and an
access_violationis stamped on the chain. Declared versus actual is a comparison you can run, not an assumption.
Every decision lands on the tamper-evident chain
Each allow, deny, and violation is appended to the same hash-chained audit log as your obligations and evidence. Every event links to the one before it, so inserting, deleting, or editing any record breaks the chain at that exact point, and verification is a built-in command. The decision log exports inside signed evidence packets that anyone can verify with the standalone castle-verify tool, with zero access to Castle. The full trust and verification model.
Posture is re-verified on a schedule, not asserted once
castle monitor re-runs the checks that keep the record honest: event-chain integrity, signing and encryption key rotation age, agent tool use against declared allowlists, and overdue remediation. Results are persisted as run history and stamped onto the audit chain, so "the controls were checked" is itself evidence on the same log. Every check is a deterministic read; no LLM is involved.
Time-boxed access for the people who check your work
For a regulator, carrier auditor, or bank partner, Castle issues a read-only portal grant scoped to one engagement. The link is shown once and stored only as a hash, the grant expires on its TTL, and expiry or revocation kills live sessions on the next request. Every grant, revocation, and access lands on the audit chain, so examiner activity is part of the same record they came to inspect.
From register to enforcement
No form, no email gate. Why registries alone fail for agents, and the sequence that fixes it:
Why a register is not enough
AI inventories were designed for models: systems that score, predict, or draft, with a human acting on the output. The register described the system, the human was the enforcement point, and that was roughly fine.
Agents break that assumption three ways. First, the agent acts directly: it calls tools, moves data, and triggers side effects with no human between intention and execution, at machine speed and machine volume. Second, registers drift: what an agent was declared to do at review time and what it can actually reach six weeks later diverge silently, because nothing checks the declaration against live behavior. Third, agents can be steered: a model that takes instructions from documents and web pages can be talked into attempting things its operators never intended. A document cannot stop any of this. A policy PDF has no opinion at the moment a tool call fires.
Logging is not enough either. After-the-fact review tells you which wire transfer should not have happened. The interesting tense is the present: the call that is about to execute.
The sequence
- Register with intent to enforce. Declare each agent's tools, data access, and allowed actions as machine-checkable facts, not prose. A declaration that cannot be evaluated at runtime is documentation; one that can is policy.
- Write decision rules you can read. Risk tiers, approval gates, and data rules as fixed logic over those declarations. If two reviewers can disagree about what a rule means, an enforcement point cannot apply it.
- Install the boundary where it costs the least. Start with the gateway in front of an existing MCP tool server: no agent changes, immediate coverage. Add the SDK guard in agents you control, a framework adapter where a fleet runs on the OpenAI Agents SDK, LangChain/LangGraph, or an ARI-compatible runtime, and the REST endpoint for anything else.
- Turn on declared-versus-actual. Let violations surface. Early on, most are stale registrations rather than attacks; fixing them is how the register becomes true.
- Make the log the system of record. Decisions, violations, and approvals on one tamper-evident chain, exported as verifiable evidence. At that point the register, the rules, and reality are the same document, which is what an auditor was asking for all along.
Where another tool is the enforcement point, Castle governs its signal
Some runtime checks are not Castle's to make. An agent-identity or behavioral-security tool watching for intent drift, an anomaly engine, a broker that already gates credentials: each makes a call Castle does not. Rather than duplicate or replace them, Castle ingests their decisions as obligation-mapped, hash-chained evidence on the same log as everything else. Castle runs no detector of its own here and renders no verdict on the content of a signal; it records what an external tool decided, maps it to the obligation that signal satisfies, and lets you prove it later.
It then reconciles intent: the behavior an agent was registered to perform against the signals that actually fired. A signal for an agent you never declared is drift; a declared agent no tool ever reports on is a coverage gap. The aim is not to out-detect the security tools you already run. It is to turn their output into examiner-grade evidence mapped to the rule it answers, so the tool enforces and Castle proves.
Watch a live allow, deny, and block
The demo shows the real product authorize an in-policy action, deny regulated data to an unapproved vendor, and block a tool outside the agent's declared reach, in under ninety seconds.