Skip to content
Free · Scenario lab

Output Caging Lab: Constrained Decoding for AI Agents

This is a hands-on lab about caging what a model can say, and being honest about what the cage cannot do. A grammar or JSON Schema enforced at decoding time guarantees the shape of an agent’s output: the right keys, enumerated tool names, bounded strings, no link syntax where you forbid it. It does not make the content true or safe. You make 12 scored calls for a fictional support agent, from choosing the constraint to the layers that cover what it cannot stop.

It follows OWASP’s guidance on improper output handling and the vendor and project documentation for structured output, and quotes no benchmark numbers. For testing single injection probes see the Prompt Injection Tester.

No download, no card
Template & sample scenario. A fictional rehearsal built on common real-world patterns, not a record of any real organisation, audit or deal. Generated from a PlayCISO template as a starting point: it is not legal, audit, certification, investment or professional advice. Review, adapt and validate it for your organisation before you rely on it.

You are Marta Okonkwo, security lead at Northgate Freight. The support agent Dispatch reads customer emails (untrusted text) and returns a structured action that your orchestrator runs: look up an order, draft a reply, open a ticket, request a refund. Today it is asked nicely, in the prompt, to answer in JSON. Your engineering team wants to cage the output at decoding time with a grammar or JSON Schema. Over 12 scored decisions you choose what to cage, what a grammar cannot stop, and which layers sit around it. The honest rule to keep in mind: a grammar limits syntax, not meaning. Nothing here is an attack recipe, every host is a placeholder and every name is invented. Each call scores 0 to 10 with the source behind the feedback.

Make it yours

Replace the sample names so the scenario and the debrief you export are about your organisation.

TL;DR

What this is

5 points
  • A scenario lab about constraining what a model can emit. Constrained decoding (a grammar or a JSON Schema enforced token by token) guarantees the shape of an output. It does not guarantee the meaning. You act as security lead at a fictional freight company whose support agent returns structured actions for an orchestrator to run.
  • You make 12 scored decisions: what a decoding constraint really promises, which constraint to pick, enumerating tool names, bounding strings, caging the free-text channel, then the cases a grammar cannot stop (a valid field carrying exfiltrating content, a wrong-but-legal tool choice) and the layers around it: post-decode validation, identifiers instead of URLs, rendering that does not auto-fetch, destination allow-lists, human approval, testing and what you tell leadership.
  • It draws on OWASP LLM05 (Improper Output Handling) and LLM01, the OpenAI Structured Outputs guide, the llama.cpp GBNF guide and the abstracts of the Outlines and XGrammar papers. We quote no benchmark figures, and we say where only an abstract was read.
  • Free to play, no account needed. Every organisation, host and agent is fictional and no attack text appears.
  • Defensive and educational only.

How this differs from our other agent labs

The Insecure Output Lab traces model output into a downstream sink (a page, a query, a shell) and picks the mitigation for that sink. This lab works one step earlier, at the decoder: what you can stop the model from emitting at all, and what you cannot. The Agent Egress Containment Lab contains where a code executor can connect; here the question is the content of the agent’s own structured reply.

The Prompt Injection Tester builds probes for your own app, and the AI Prompt Injection Incident Lab is the response after a leak. For slow, multi-turn steering see the Crescendo Attack Lab, and for who may approve a risky action see the Agent Step-Up Approval Lab.

Frequently asked questions

What is constrained decoding?

It is a way of making a language model produce only outputs that fit a grammar or schema. At each step the runtime masks the tokens that would break the rules, so the result parses. The Outlines paper describes guiding generation with regular expressions and context-free grammars, and the llama.cpp guide describes GBNF grammars used to force valid JSON. It is a statement about structure, not about whether the content is right.

Does a JSON Schema or grammar stop prompt injection?

No. It limits which strings and shapes can be produced, so it can remove some channels, such as link or markdown syntax in a field that forbids those characters. It cannot tell that a well-formed recipient address is the wrong one, or that a legal tool choice is the wrong choice. OWASP LLM01 says it is unclear whether fool-proof prevention exists and recommends layered mitigations, including defined and validated output formats.

Is constrained output the same as OpenAI Structured Outputs or JSON mode?

Not exactly. OpenAI describes JSON mode as guaranteeing valid JSON and Structured Outputs as also guaranteeing adherence to a supplied JSON Schema. Its guide adds that Structured Outputs can still contain mistakes, that a safety refusal does not necessarily follow the schema, and that the supported schema subset has limits. Other engines, such as llama.cpp with GBNF, offer grammars with their own features.

What can a grammar never stop?

Anything that is valid under the rules. A syntactically correct field can carry sensitive data to an outside address, a plain-language instruction aimed at the reader, or a harmful value in the right type. A valid tool name can still be the wrong tool. Semantic abuse needs controls outside the model: policy checks in code, identifiers the server resolves, allow-lists, safe rendering and human approval for high-impact actions.

Why does the rendering policy matter if the output is constrained?

Because the output is displayed somewhere. OWASP LLM05 advises encoding model output for its context and using strict Content Security Policies, and warns about Markdown and JavaScript. A console that auto-fetches images or follows links from model text turns a harmless-looking string into an outbound request. Constrain the output, then render it as inert text.

Should I still validate outputs if I use a schema?

Yes. Validate in code against the same schema and against business rules, and treat refusals, empty or cut-off replies as failed steps. OWASP LLM05 advises treating the model like any other user and validating what it returns before it reaches backend functions.

How is the lab scored?

Each of the 12 decisions scores 0 to 10 and the result is your share of the maximum, with a short band that says what the score means. The debrief shows the source behind each rationale. Lines labelled PlayCISO practice are our reasoning, not a statement by a source.

Sources

All read on 4 November 2026. Lines in the feedback marked “PlayCISO practice” are our own reasoning, not a statement by any source. The scenarios are fictional. We cite primary sources, not vendor advisories, and say where a page could not be fully read.

The tools people use most on PlayCISO.

All tools
🖤 Black Friday: new customers get 3 months of Pro for $5, then $5/month. Ends 30 Nov. Claim 3 months for $5 →