Your model can be jailbroken. What happens next is the part you control.
Most of the argument about agent safety is an argument about whether the model can be convinced to do something it shouldn't. It can. The more useful question is what a convinced model is actually able to carry out — and that question has a deterministic answer.
Start by conceding the whole first half of the argument: the model can be jailbroken. Not "might be under unusual conditions" — assume it has already happened, in production, and that you didn't notice. Indirect injection through a tool response, a poisoned document in a RAG index, a malicious MCP server, a user patient enough to find the phrasing that works. Pick whichever you find most plausible; the rest of this holds regardless.
What most agent-safety writing does next is explain how to make that less likely. That's worth doing, and input firewalls are good at it. But it leaves the interesting question untouched, which is: the model is now working for someone else. What can it actually do?
What the jailbreak captured, and what it didn't
A compromised model has complete control over its own output. It decides which tool to call and with what arguments, which sub-agent to spawn and with which capabilities, what plan to commit to, and what to write into memory. If those decisions are also what executes, the jailbreak is total — the attacker has the agent's full permission set and there is nothing left to discuss.
Action-layer governance separates those two things. The model's decision becomes a request, and the request is evaluated before anything happens:
| The jailbroken model controls | It does not control |
|---|---|
| Which tool it asks for, with which arguments | Whether that tool call is permitted to execute |
| Which capabilities it requests for a child agent | Whether a child may hold a scope the parent never had |
| What plan it proposes | Whether the plan runs, evaluated whole, before step one |
| How long it wants to keep going | Whether the session's budget is already spent |
The reason the right-hand column holds under adversarial pressure is that the model isn't in that code path. The decision is made by Open Policy Agent — the same deterministic engine used for Kubernetes admission control — against version-controlled Rego, after the model has decided and before the call lands. There's no prompt that changes the answer, because nothing the model emits is an input to it.
The four lifecycle attacks in the previous post are what this looks like concretely — each one is a jailbroken agent attempting a specific escalation, and each has a runnable demo that evaluates the real policy and asserts the outcome.
The soft-deny case: routing instead of refusing
Not every risky action should be a hard deny. The shipped example is a refund: an agent holding a session token scoped to approve_refund_under_100 attempts a $5,000 refund, against a financial policy that requires human review above $1,000. No allow rule matches. Rather than failing outright, the policy classifies the action as TRANSACTIONAL_HIGH and sets requires_hitl=true — the call enters a review queue, the agent pauses, a human decides, and the outcome is recorded in the audit trail either way.
session scope : approve_refund_under_100
requested : approve_refund(cust_001, $5,000)
policy : no allow rule matches; amount > $1,000 review threshold
classification: TRANSACTIONAL_HIGH
decision : requires_hitl -> review queue (agent paused)This is the shape most real policies take. Hard denies are for things that are never acceptable; everything expensive-but-legitimate routes to a person. It's also where the honest caveat belongs, which is the next section.
What a jailbreak still gets you
Four gaps, in rough order of how much they should worry you.
1. Everything the policy permits
This is the big one and it isn't subtle. If the agent may read the customer table and may send email, then a jailbroken agent may read the customer table and send email — each call is individually in scope, and an engine evaluating one call at a time has no grounds to deny either. The attacker didn't escalate; they used what was already granted. This is the classic confused deputy, and no amount of enforcement fixes an over-broad grant. It's a policy design problem: narrow scopes, per-session tokens, and deny-by-default are what shrink it, and the work is in writing the policy rather than running it.
2. A human who says yes
Routing to a person is not the same as being safe. A jailbroken agent writing the justification for its own approval request is a persuasion problem, and reviewers under time pressure approve things. OWASP tracks this as Human-Agent Trust Exploitation in its 2026 agentic top 10. HITL narrows the blast radius by putting a human in front of the highest-risk actions — it doesn't eliminate it, and an approval queue that doesn't give the reviewer enough context to disagree is a rubber stamp with extra latency.
3. Everything that lives in the output
A jailbroken model can still say things. Leaked system prompt contents, harmful text, a convincing lie to the user, a plausible-looking but wrong answer — none of that is an action, so none of it touches the policy layer at all. That's the input/output layer's job, and it's a real job. Run a text-layer tool alongside this; Guardrails AI, NeMo Guardrails, and LLM Guard all address a layer that action governance does not cover.
4. Whatever the tool itself lets them do
Policy decides whether a tool runs, not what happens inside it. An agent permitted to call a tool with a SQL injection bug can still reach that bug. Enforcement doesn't audit your tool implementations, vet your dependencies, or watch the network for a side channel. It's one layer of a defence-in-depth story and it behaves like one.
The honest version of the claim
"Kite Logik makes your agents safe" is not a claim that survives ten minutes with a security engineer, and it shouldn't. The defensible one is narrower and more useful:
Your model can be jailbroken. Policy enforcement stops the jailbreak from translating into an action the agent was never permitted to take — and leaves you with a recorded, reviewable decision for every attempt.
That's a smaller claim than the category usually makes. It's also one you can verify yourself in about a minute, which is worth more than the bigger claim.
Run it yourself
git clone https://github.com/kitelogik/kitelogik
cd kitelogik
docker compose up -d opa # demos 1-3 evaluate a real policy
python examples/adversarial/delegation_scope_escalation.py
python examples/adversarial/plan_step_injection.py
python examples/adversarial/budget_exhaustion_runaway.py
python examples/adversarial/memory_poisoning_minja.py # no OPA needed
python examples/05_hitl_escalation.py # the soft-deny pathFrequently asked questions
Does policy enforcement prevent jailbreaks?
No, and nothing that sits below the model can. A jailbreak is a property of the model — you can make it harder with better prompts and an input firewall, but you cannot make it impossible. Policy enforcement addresses the next question instead: given that the model has been convinced, which of the actions it now requests are actually permitted to execute. Those are different problems, and only the second one has a deterministic answer.
What can a jailbroken agent still do under policy?
Everything the policy permits. If the agent is allowed to read a customer table and allowed to send email, a jailbroken agent can read that table and send that email — each call is individually within scope, and a policy engine evaluating one call at a time has no grounds to deny either. This is the confused deputy problem, and it is a policy design problem rather than an enforcement one. Narrow scopes are the mitigation.
Can a jailbroken agent talk its way past a human approver?
Yes. Human-in-the-loop routing moves the decision to a person, and a person can be given a persuasive-looking justification. OWASP tracks this as Human-Agent Trust Exploitation (ASI09) in its 2026 agentic top 10. HITL narrows the blast radius by putting a human in the path of the highest-risk actions; it does not eliminate it. Approval queues need enough context for the reviewer to make a real decision, not a rubber stamp.
Why not just improve the system prompt?
A system prompt is a request the model can ignore, and under adversarial pressure with enough injected context, models do ignore them. It is worth writing a good one — it changes behaviour in the common case. It is not worth relying on, because there is no version of it that is enforced. The policy decision happens after the model has decided and before the call executes, with the model outside that code path entirely.
Is there a demo of this?
Four of them, in examples/adversarial/ in the repo — delegation scope escalation, plan step injection, budget exhaustion, and memory poisoning. Each constructs the action a compromised agent would attempt, evaluates it against a real Rego policy, and asserts the outcome. Three need OPA running locally; the memory one is pure in-process.