In a previous post we argued that “guardrails” had come to mean too much, and that a word covering everything specifies nothing. Three words in this post deserve the same scrutiny: safe, secure, governed.
Each carries an implication worth questioning. These words seem to name a property an agent either has or doesn’t. For agents we believe that framing is wrong. Safety is not a property an agent possesses. It is a position on a frontier between how useful the agent is and how much of its risk you have closed off. Here we try to describe that frontier in more detail and discuss ways of “pushing it out”: i.e., making an agent more useful while retaining a level of security.
Unconditional guarantees don’t hold
Let’s begin with the strongest thing a vendor might have on offer: an unconditional guarantee — “this agent will never do X,” with no “rarely” and no “we’ll catch it.”
For any agent worth deploying, that guarantee is likely unavailable. Why? Well, a guarantee has to be enforced somewhere. If the enforcement lives anywhere the agent can reach — its own code, its prompt, its configuration, a process it can signal — then an agent that’s able to write and run code can, in principle, alter it. Self-modification is the clean case: the constraint sits inside the action space it is meant to constrain.
You can try to move the enforcement out of reach: a kernel boundary, or a separate process the agent can’t address. That helps, and it’s worth doing. But it only holds if the boundary is complete and the agent can’t get around it — and if every action that matters actually passes through it. In practice that surface is usually partial. If an agent acts through a channel you don’t observe — an unhooked subprocess, a tool you don’t proxy, a sub-agent the host doesn’t report — that action goes ungoverned, whatever your policies say. And each step you take to close the surface tends to narrow what the agent can still do.
So we’d put it this way: it isn’t that nothing can be guaranteed. It’s that a guarantee is always conditional — on a bounded action space, a complete interception surface, and a set of classifications you’ve taken on trust. Tightening any of those costs you capability. And at least three of them tend to leak for structural reasons, not because the tooling is immature:
- Semantics are hard to pin down. You can block
rm -rf /, butfind / -delete, a short script, orT=/; rm -rf $Tdo the same thing in forms no pattern will catch. Deciding what a step will do, rather than how it’s written, is undecidable in the general case. So enforcement runs on proxies you can decide, and proxies have edges. - You can only govern what you see. Enforcement acts on the steps the runtime surfaces to it. Anything that happens where your instrumentation doesn’t reach is ungoverned, however good the policy.
- Classifications are taken on trust. “This file is a secret,” “this domain is internal,” “this output has no PII” — each is an assumption, and a wrong one leaves a silent gap.
A guarantee that’s honest about these conditions is fine. One that leaves them out hasn’t removed them; it just isn’t mentioning them.
What you actually want is a useful agent
It’s worth noticing that nobody really wants a maximally safe agent. Maximum safety is easy: don’t deploy it, or strip its tools until it can’t act. You deploy an agent in the first place because you want it to do things — query the database, send the mail, change something in production, act on your behalf. Capability and exposure are two sides of the same thing; you can’t ask for one without taking on some of the other.
So the real goal is more modest: make the agent as useful as it needs to be, while keeping the residual risk at a level you’ve chosen deliberately. That’s an optimization, and it traces out a frontier — usefulness on one axis, risk closed off on the other. The safe-but-useless corner is always available, but it is hardly ever what you really want. So, the core questions are a) where do we want to sit on the usefulness-vs-risk trade-off, and b) (and perhaps more importantly), how can we push the curve? Thus, how can we have more usefulness and less risk simultaneously?
Every “security” method moves the frontier
Seen this way, each layer of the stack we mapped earlier is a way to reduce risk without giving up usefulness.
- Isolation and least privilege move the frontier by deliberately shrinking the action space — splitting the reader from the sender, scoping tools. Effective, paid for in capability, and limited once combinations multiply.
- IAM moves it on the identity axis: may this agent reach this resource? Cheap and foundational, but silent on the full behavioral trace.
- Content guardrails move the frontier on the payload axis: no PII in this output, no injection in this input. Fast, and blind to whether a clean-looking action is the right one.
- Gateways centralize control of model traffic, at a data-residency cost, because the traffic has to reach the inspection point.
- Credential brokering moves the frontier at the authentication boundary, issuing short-lived scoped tokens. It governs the request for access, not the use of it afterwards.
- Red-teaming moves it before deployment by sampling the behavior distribution — useful, but a sample is not a bound.
Stacked together they reach further than any one of them alone, because each closes off a different “region”, and the way around one is usually not the way around another. That’s the real argument for defense in depth. But none of them — and not all of them together — gets you to the safe-and-useless corner; the ceiling we described earlier is still there. They move you outward, not to the edge. In this light, kyvvu provides simply a new axis to push the frontier.
The missing axis
Every layer above looks at something local: this identity, this payload, this token, this step on its own. But the risks that are specific to agents usually aren’t local. They live in the sequence — read customer data, then send it outside the org; fetch a credential, then move it out through a channel that’s perfectly allowed. Each step on its own is fine; the path is the problem. That’s the gap we built kyvvu for: it checks each step against the history of the task so far, and decides before the step runs. It’s prevention of risk at a very low level.
To be fair about it, we’re not the only ones who touch the trajectory. Anomaly and (model) drift detection can look across multiple runs. However, this is often simply detection. What seems rare is enforcement on the path: a hard allow-or-deny on the next step, computed from everything before it, applied before it runs. That’s the part kyvvu focuses on, and we think the gap between spotting a bad sequence after the fact and stopping it before is the one that matters most in practice.
At its core, path-dependent interception is not a new idea. It’s one of the older ones in security. History-dependent access control goes back to the Chinese Wall model in 1989; “no network call after reading a secret” is information-flow control; a policy that watches a trace and blocks a forbidden sequence is a runtime monitor, which is a field with decades behind it. We didn’t invent reasoning over history, and we don’t claim to.
What didn’t really exist was this primitive applied to agents: a single behavior vocabulary that different frameworks can map onto, evaluated inline, portable across runtimes. The idea is well understood; the application is the new part. And honestly, we think that’s the right way round — a control built on a proven idea is a safer thing to put in production than one built on a brand-new one. Most of the work here is engineering, not concept. If you want the formal version, it’s in our arXiv paper, Runtime Governance for AI Agents: Policies on Paths.
What it costs to reach that axis
An axis nobody else enforces on would still be a bad trade if it were expensive to reach. We’ve tried to keep that cost low, and that’s mostly down to implementation rather than the idea itself.
- Latency. Evaluation is local, in the agent’s own process, and sub-millisecond — 296µs at p99 with 100 policies and 50 steps of history in our published benchmarks. Fast enough to sit in front of every step.
- Data residency. kyvvu isn’t a gateway. Prompts, tool arguments, retrieved documents and customer data don’t travel to us; enforcement runs inside your own environment, and only the policy crosses the boundary, out of your own git repository. The enforcement comes to the data rather than the other way around — which, for regulated workloads, is often the difference between something you can deploy and something you can’t.
- Reach. Because each action is modeled as the same
(step_type, scope, verb)behavior wherever it comes from, one set of policies applies across a LangGraph app, a CrewAI crew, or a Claude Code session — which matters, because a dangerous sequence often spans more than one of them.
None of this makes adoption free — you still have to write policies and wire in the runtime. What it does remove are the usual reasons a path-aware control would be impractical in the first place: latency, data leaving your environment, and being tied to a single framework.
The takeaway
If there’s one thing to take away: safety isn’t a property your agent has, it’s a position you pick on a frontier between usefulness and risk. That frontier is there whether or not anyone names it. The thing to avoid is pretending it isn’t.
No one can really sell you a guarantee; the ceiling is structural. What a control can do is move your frontier outward — more capability at the same risk, or less risk at the same capability. Most of the stack does that on axes that are already fairly well covered. kyvvu tries to do it on the one the rest can see but don’t enforce on — the path — at low latency, without moving your data, and across the runtimes your agents already run in.
Whatever you end up using, it’s worth picking your spot on the frontier deliberately, and knowing which layer is buying you which part of it.
If you’d like to try the path-dependent part yourself: pip install kyvvu, point it at a policy manifest in your own repository, and you’ll have a first enforced policy running in a few minutes.