By the end of this lesson you will understand how to design prompts as typed contracts — schema-first — so that your LLM calls are predictable, token-efficient, and safe to wire into production Java systems without post-hoc string parsing.
It's a Tuesday afternoon. A teammate opens a JIRA ticket: AI Lesson Generator returning 500s intermittently — cannot reproduce locally . You pull the logs. The stack trace is not from your code. It's from the JSON parser downstream — com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type 'List<SceneStep ' from String value . The LLM returned a prose paragraph instead of the JSON array your pipeline expected. You look at the prompt. It says, roughly: "Generate a lesson plan. Return JSON." Sometimes the model obeys. Sometimes it writes: "Sure! Here is the lesson plan in JSON format: json... " — and your Jackson parser chokes on the markdown fence. Sometimes it skips the fence but adds a trailing sentence: "Let me know if you need adjustments!" That kills deserialization too.…
The incident above is every team's first encounter with prompt brittleness — the gap between what the model usually does and what your downstream code requires it to do. You cannot unit-test around it. You cannot retry your way out of it. You need a different mental model for how a prompt is structured. What exactly is a schema-first prompt? A schema-first prompt is a prompt where the output structure is defined as a formal type contract — not described in English prose — and where the model is instructed to fill that contract, not compose a response. Instead of writing "Return a JSON object with fields for title and chapters" , you embed the actual JSON Schema (or a typed example that doubles as documentation) directly in the system prompt, and you configure the model call to validate or enforce that schema at the API level where the provider supports it.…
Scene Setup Imagine a wide horizontal canvas. On the far left is a box labeled LessonAuthorService — this is your Spring @Service bean. On the far right is a box labeled Claude on Bedrock — the model. Between them is a narrow channel: the HTTP request that carries the prompt. Below the channel, there is a conveyor belt leading to a box labeled LessonRepository — your JPA repository waiting to persist a Chapter entity. Every object on this canvas is static right now. Animation: the unschematized prompt A blue envelope slides from LessonAuthorService into the channel. Inside the envelope, in tiny text, you can read: "Write a chapter about binary search trees. Return JSON with a title and content." The envelope reaches Claude. Claude opens it, thinks, and sends back a red envelope. You open the red envelope: it contains a JSON object, but the key is "chapterTitle"…
The Three Enforcement Layers Schema-first prompting is not a single mechanism — it is a stack of three enforcement layers, and understanding each one independently is what separates a developer who knows the pattern from one who can debug it in production. Layer 1: In-prompt schema (training-time guidance) When you embed a JSON Schema in the system prompt, you are exploiting a property of how large language models are trained: they have seen enormous quantities of JSON Schema documents paired with JSON instances that satisfy those schemas. The model has learned the relationship between schema shape and valid instance. So when your system prompt ends with a JSON Schema block and the instruction "Your response must be a valid JSON object matching this schema" , the model's next-token probabilities are biased toward tokens that continue a conforming JSON document.…