If you've been scrolling through Hacker News or tech Twitter lately, you’ve likely seen the viral phrase "Dario, Please" echoing across developer threads. It’s a community-wide, half-joking, half-desperate plea directed at Dario Amodei, the CEO of Anthropic. What started as a meme has highlighted a very real transition in our industry: developers are no longer just writing deterministic code; we are orchestrating, steering, and debugging non-deterministic AI models like Claude 3.5 Sonnet to run our production systems.
But when we cry "Dario, please make the model stop hallucinating my database schema" or "Dario, please lower the latency on Claude 3.5," what we are actually asking for is better control over LLM behavior. We want reliable, predictable, and structurally sound outputs. In this post, we’re going to look past the memes and dive deep into the actual engineering patterns, system prompt architectures, and API tricks you can use today to make Claude behave exactly how your production application requires.
The Core Challenge: Determinism in an Indeterministic World
As software engineers, we are accustomed to clear inputs, outputs, and stack traces. When an API fails, we get a 500 error or a serialization exception. With LLMs, the "failure mode" is often a beautifully formatted, highly confident, but completely incorrect string of text.
To bend Claude to our will without waiting for Anthropic to release an update, we have three primary leverage points in our code:
- System Prompt Engineering: Setting the behavioral rails, identity, and logical boundaries before the execution starts.
- Structured JSON Output (Tool Calling): Forcing the model to return syntactically valid JSON schemas instead of freeform prose.
- Prefill Manipulation: Leveraging Anthropic’s unique API feature to guide the very first tokens of the model's response.
Let's roll up our sleeves and look at how to implement these patterns in real Node.js and Python environments.
1. The Anatomy of a Production-Grade System Prompt
A weak system prompt says: "You are a helpful assistant that writes SQL." This is a recipe for SQL injection vulnerabilities and hallucinations. A production-grade system prompt acts like a strict security policy and execution runtime environment.
When designing system prompts for Claude, we want to leverage XML tags. Anthropic's models are explicitly trained to recognize and parse XML tags (like <instructions>, <rules>, and <context>) much better than markdown or raw text. It helps the model separate your instructions from user-provided data, reducing the risk of prompt injection.
Example: The Secure SQL Generator Prompt
const systemPrompt = `
You are a secure database assistant. Your sole task is to translate natural language queries into read-only PostgreSQL queries.
<rules>
1. ONLY generate SELECT statements.
2. NEVER generate INSERT, UPDATE, DELETE, DROP, ALTER, or TRUNCATE statements.
3. If the user query implies a write operation, return an error block inside the <error> tag and do not generate SQL.
4. Always qualify table names with the "public" schema.
5. Limit all queries to 100 rows maximum unless specified otherwise.
</rules>
<schema>
Table: public.users
- id (UUID, PK)
- email (VARCHAR)
- created_at (TIMESTAMP)
Table: public.orders
- id (UUID, PK)
- user_id (UUID, FK to public.users.id)
- amount (NUMERIC)
- status (VARCHAR)
</schema>
<output_format>
You must output your response inside a valid JSON object matching this schema:
{
"sql": "string or null",
"explanation": "string describing the query logic",
"error": "string or null"
}
</output_format>
`;
2. Forcing Structured Output with Tool Calling (Function Calling)
Even with strict system prompts, Claude might occasionally append conversational filler like "Here is the SQL query you requested:". In a production backend, this breaks JSON.parse() and crashes your service.
To guarantee structured data, we use Anthropic's tools API. By defining a tool and setting the tool_choice parameter to type: "tool", we force Claude to bypass conversational output entirely and respond directly with JSON matching our JSON Schema.
Here is how to implement this pattern using the official @anthropic-ai/sdk in TypeScript:
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
async function generateDatabaseQuery(userInput: string) {
const response = await anthropic.messages.create({
model: "claude-3-5-sonnet-20240620",
max_tokens: 1000,
system: systemPrompt, // Our structured system prompt from above
tools: [
{
name: "execute_sql_query",
description: "Executes a safe read-only SQL query against the database.",
input_schema: {
type: "object",
properties: {
sql: {
type: "string",
description: "The complete, valid PostgreSQL query."
},
explanation: {
type: "string",
description: "A brief, one-sentence description of what the query retrieves."
}
},
required: ["sql", "explanation"]
}
}
],
tool_choice: { type: "tool", name: "execute_sql_query" }, // Forces tool execution
messages: [
{ role: "user", content: userInput }
]
});
// Extract the structured parameters safely
const toolUseBlock = response.content.find(block => block.type === 'tool_use');
if (toolUseBlock && 'input' in toolUseBlock) {
const { sql, explanation } = toolUseBlock.input as { sql: string; explanation: string };
return { sql, explanation };
}
throw new Error("Failed to retrieve structured tool execution from Claude.");
}
By enforcing tool_choice, you eliminate the variance of freeform text. Your API responses are predictable, typings are clean, and your error handlers remain happy.
3. The Secret Weapon: Assistant Message Prefilling
One of the most powerful features of the Anthropic Messages API (which is frequently overlooked compared to OpenAI's offering) is the ability to seed the assistant's response.
In a standard API interaction, you send a list of messages alternating between user and assistant, ending with a user message. The model then responds. However, with Claude, you can append a final assistant message to the array. Claude will continue writing from the exact spot where your prefilled message ends.
This is incredibly useful for steering behavior, enforcing output formats (like starting an XML block), or bypassing model hesitation.
Example: Prefilling JSON to Reduce Latency and Token Overhead
If you don't want to use full tool calling but still need a raw JSON block without the conversational fluff, you can prefill the opening bracket of a JSON object:
const response = await anthropic.messages.create({
model: "claude-3-5-sonnet-20240620",
max_tokens: 500,
messages: [
{ role: "user", content: "Generate a list of three mock user profiles for testing." },
{ role: "assistant", content: "{\n \"users\": [" } // Prefilling the JSON response
]
});
// Claude's response will continue exactly from where we left off:
// "id\": 1, \"name\": \"Alice\"}, ..."
const fullJsonString = "{\n \"users\": [" + response.content[0].text;
const parsedData = JSON.parse(fullJsonString);
This technique completely bypasses Claude's standard introductory chatter (e.g., "Sure, I can help you with that! Here are three users..."), saving you latency, reducing prompt token costs, and eliminating parsing bugs.
Architectural Best Practices for Production AI
As you build systems on top of these APIs, keep these high-level architectural patterns in mind:
Idempotency and Caching
Claude requests can be slow compared to traditional REST endpoints. Always implement an application-level caching layer (like Redis) keyed by the hash of your system prompt and user input. If a user asks the exact same query twice, serve it from memory.
Graceful Degredation
Never rely solely on the LLM. If your SQL generator output fails verification or times out, degrade gracefully. Fall back to a traditional search index or a standard error UI. Your application's uptime should not be completely tied to an external AI API's availability.
Conclusion
While the "Dario, Please" meme is a fun reminder of how chaotic the rapid pace of AI development can feel, we aren't helpless. By using structured system prompts with XML tags, enforcing schema compliance through explicit tool-calling configurations, and using assistant prefilling, we can build robust, production-grade applications that treat LLMs like predictable execution engines rather than mysterious black boxes.
Are you building production systems with Claude? How have you handled the predictability problem? Let’s talk shop in the comments below!
If you enjoyed this deep dive, subscribe to "Coding with Alex" at sysseder.com for weekly engineering guides, architectural blueprints, and honest security reviews.