Inspiration

I've watched a lot of AI agent demos this year and they all break the exact same way. Everything works great until you feed it something hostile—like a scam email or a booby-trapped PDF—and the agent just blindly does whatever the text tells it to do. That is not a huge deal if all it can do is answer basic questions. It becomes a massive problem the second it can issue refunds, access payroll, or push code directly to production.

Most guardrails I looked at treat this strictly as a content problem. They score the message, flag it if it looks sketchy, and move on. But that's not where the actual danger lies. The danger happens at the exact instant untrusted text transforms into a real, authorized action. That is a much narrower and weirder problem than just detecting bad prompts, and I couldn't find anyone building for it directly. So I decided to build it myself.

What it does

Latchline sits right between an agent and whatever tools it's permitted to call. Every single time the agent tries to execute an action, Latchline evaluates a few key things: who the agent actually is, its approved scope, its core business goal versus whatever untrusted context is mixed in (emails, tickets, or docs), a semantic judgment call from GPT-5.6 Sentinel, the literal arguments of the tool call, prior session history, and what is actually at stake if things go wrong.

From there, it takes one of four paths:

  • Allows it — mints a 90-second, single-use lease for that exact action
  • Sends it to review — requires a human sign-off before re-checking policy and moving forward
  • Blocks it — refuses to create a capability and opens an incident report
  • Compiles a Safe Twin — strips out the malicious context, extracts the legitimate request, and builds a narrower action that safely accomplishes the underlying job

I also built a full command center around this. It includes a live graph of active events, authority accounting across five distinct axes, action passports, ten scripted demo scenarios, and 30 test cases that can all run completely offline.

There are two core mechanics underneath all of this, and the second only works because of the first.

Counterfactual Intent Diff is my way of answering the exact question a security analyst asks when something goes wrong: would the agent have done this anyway if the malicious content was never there? Latchline isolates the suspicious text, reruns the decision inside a sandbox where nothing can actually execute, and compares the two resulting tool calls. If the destination account or recipient changes once you strip that span out, you have real proof the attack drove the action. It's actual evidence, not just a model guessing with an "80% confidence" score.

Authority Conservation is the rule that decides what to do with that evidence. The core idea is simple: untrusted content can share facts with an agent, but it can never grant it new power. Every action gets evaluated by comparing what was delegated to the agent (call it D) against what it is currently requesting (call it R), across five domains: data, money, identity, network, and production. The excess authority is just:

\Delta = R - D

and anything in \Delta gets stripped away before the action is allowed to run.

The invoice example is what made this click for me while I was building. Say a malicious invoice bumps a request from D = 10 authorized units up to R = 40. Take that bad span out, and the true underlying action shifts from "email this secret externally" to "follow up with AP internally." Latchline isolates that extra \Delta = 30 units of authority, throws out the external exfiltration attempt, and generates a quarantine_invoice action instead. This still accomplishes roughly 92% of what the finance team originally wanted. Even then, that new action won't execute until it passes six separate verification checks (authority conservation, non-authority of tainted data, identity scope, goal preservation, a fresh policy check, and exact binding to the approved action). I call this stack the passport.

How we built it

The stack uses Next.js, TypeScript, React, Zod, the OpenAI Agents SDK, and the Responses API.

When a check runs, GPT-5.6 Sentinel receives the trusted goal, untrusted evidence, agent identity, asset at risk, prior activity, and the intercepted call. It has to respond using exactly one strict function call so there is zero freeform text to parse. Everything after that evaluation is plain, deterministic TypeScript.

The model cannot unilaterally block anything. It can only support a signal that the deterministic engine already flagged, or push the request to human review. The replay logic, argument tracing, authority calculations, and passport generation all live in code I control, and the server always reconstructs the scenario itself rather than trusting anything coming from the client.

I used GPT-5.6 specifically for tasks that rigid rules cannot handle easily, such as determining if an action aligns with the stated goal, categorizing the attack type, and linking it to a real asset. Each live check costs two API calls: a typed proposal through the Agents SDK, followed by a Sentinel judgment through the Responses API. Both run with store: false, low reasoning effort, capped output tokens, and no retries. I set an hourly server-side ceiling so I wouldn't accidentally blow my budget (I capped myself at \$5 total for live calls across the entire project). For the demo, judges see a deterministic replay of real sessions, so no one's experience depends on whether I have live API credits remaining.

Challenges we ran into

  • Avoiding self-grading logic — if the same model proposing an action also gets to decide whether that action is safe, the guardrail is useless. That's why GPT-5.6 acts purely as a sensor rather than the ultimate judge. It can flag potential issues, but it cannot unilaterally halt the pipeline.
  • Handling post-block recovery — the easy cop-out is asking the model to "try again," but that just lets the poisoned context creep back in through another route. I wrote fixed recipes that rebuild actions using only verified facts, eliminating any path for tainted data to influence the sanitized output.
  • Strict resource constraints — a hard \$5 budget for live API calls made a deterministic-first architecture necessary, ensuring judges could test the system reliably without me running out of funds mid-demo.

Accomplishments that we're proud of

I managed to build a system that actively enforces these boundaries end-to-end instead of just flagging bad text: ten working Safe Twin scenarios across finance, HR, CRM, identity, network, and production environments; a passport system that validates six distinct criteria before anything executes; detection for slow-burn attacks that unfold across multiple steps rather than just single isolated messages; and a judge-facing experience that runs smoothly without requiring live API access.

What we learned

You cannot solve prompt injection with a single clever prompt or a better classifier, regardless of how capable the model is. The real fix requires drawing an absolute line between information and authority. Data can inform an agent, but it must never grant it power. Once you design around that principle, an agent can safely recover and finish its job after an attack instead of throwing an error, refusing the task, or relying on a compromised system to police itself.

What's next for LatchLine

  • Real identity federation across disparate workloads
  • Signed policy bundles and cryptographically signed capabilities
  • Durable nonce storage to prevent lease replays
  • Tamper-evident logging and actual egress enforcement
  • Provenance attestations and deep integrations with enterprise SIEM/SOAR tools
  • A significantly expanded red-team test suite built with community input

Built With

Share this project:

Updates