blog

May 7, 2026

The moves your coding agent can't make

The security controls that don't fit in a tool definition need a layer of their own. Here's what the kernel enforces — and an honest account of what it doesn't.

Your coding agent will eventually try to deploy before the tests pass, or approve its own pull request, or retry a flaky call and charge the customer twice. Your system prompt politely asks it not to. It does anyway. This post is about the layer that makes those moves not discouraged but unreachable — a call the model literally cannot place.

Praxec sits between the model and your tools as a single checkpoint, and the model only ever sees two tools through it: praxec.query for reads and praxec.command for writes. Everything below is the payload.

The controls that don’t fit in a tool definition

A tool definition can describe a tool: name, arguments, schema. It cannot say any of the things you actually want said about a dangerous action:

Those aren’t properties of a tool. They’re policy. And policy needs somewhere to live that every call has to pass through. That’s the kernel: a single checkpoint where the rules are enforced instead of hoped for.

What the kernel enforces before the executor runs

Three checks happen between a call arriving and a tool actually running. Each can stop the call cold.

And the move it isn’t offered from this state at all? That returns INVALID_TRANSITION — the move doesn’t exist here, so there’s nothing to talk its way around.

Where the guarantees stop — the honest part

Most tools skip this section. Here it is. The permission and role guards assume a deployment with real identity wiring; the bundled binary treats every caller as anonymous, which is the right default for a developer on a laptop but is not a security boundary — wire in real identity before you lean on those guards for isolation. Links guide the model but don’t bind it; enforcement is the guards and actor checks, not the links. And how airtight the whole thing is depends on how you run the kernel: sitting behind an editor as a gateway, it governs every capability routed through it but not the host’s own built-in shell. The docs spell out each mode and what it enforces.

The point isn’t that the kernel makes your agent unhackable. It’s that the controls which don’t fit in a tool definition finally have a place to live — one checkpoint, every call passes through it, and the refusals are recorded whether or not the model tries to route around them.

← All posts