Compilers for Agent Systems
A model-generated plan is a program in an untrusted language. Parse it, type it, validate it and check its permissions before any of it executes.
A model-generated plan is source code in an untrusted language written by an unreliable author. That single reframing hands you a whole compiler frontend of techniques — a grammar, a parser, name resolution, a type checker and an authorization pass — and tells you the order to run them in.
Give the agent a small language with a grammar, and its plans become trees you can print, diff, refuse, rewrite and replay. `SEARCH(...) |> FILTER(...) |> SUMMARIZE()` as an AST before any tool runs is worth more than the same three calls made one at a time, and the reasons are the ordinary reasons an IR exists.
A tool call is a function call whose arguments came from an untrusted source, so the boundary needs a type checker. JSON Schema is that type system, constrained decoding is the technique that makes malformed calls unsamplable rather than merely detectable, and neither of them says anything about whether the call should happen.
Four gates, each rejecting a class of problem the others structurally cannot, in an order that is not arbitrary. The reason the ordering matters is the same reason `[[phase-ordering]]` matters in a compiler: a later phase depends on facts an earlier one established, and running them out of order either weakens the check or leaks information.
The practical lesson: how to get a reliable data structure out of text a model wrote. A strict parser with real error recovery beats a pile of regular expressions for the same reasons it does in a compiler, repair-and-retry is a legitimate strategy with a cost worth naming, and no parser will ever tell you whether the output meant what the user wanted.