Most agent failures aren’t model failures — they’re prompt failures. The model does exactly what you told it to do. You just didn’t tell it what you actually meant. After shipping dozens of production agents across customer support, lead qualification, document processing, and code review, the single highest-leverage improvement is almost always the system prompt, not the model swap or the infrastructure change. Getting system prompts for agents right is the difference between an agent that works reliably at 10 requests per day and one that holds up at 10,000.
The problem is that most teams treat system prompts like config files — write once, forget, debug later. That approach works until you hit an edge case the model wasn’t primed to handle, switch models mid-project, or hand off the project to someone who doesn’t know why the prompt is structured the way it is. This article gives you a structured framework, working templates, and the three biggest misconceptions that cause well-intentioned prompts to fail in production.
Why Most System Prompts Break at Scale
The gap between “works in the playground” and “works in production” is almost always rooted in three problems: ambiguity, missing failure modes, and no defined output contract.
Ambiguity means the model has too much interpretive freedom. “Be helpful and professional” is not a behavioral specification — it’s a vibe. Claude will interpret it differently depending on what precedes it in context, what the user says, and subtle differences between model versions. Haiku interprets “concise” differently than Sonnet. Opus will elaborate where Haiku will summarize. If your prompt relies on implicit assumptions, those assumptions will fail.
Missing failure modes means the prompt only describes the happy path. What should the agent do when the input is ambiguous? When data is missing? When the user asks something out of scope? If you don’t specify, the model improvises — and improvisation at scale is a liability.
No output contract means downstream systems can’t reliably parse what the agent returns. If you’re passing agent output to a CRM, a webhook, or another model, you need deterministic structure. Asking for JSON and hoping for the best isn’t a contract. (For a full treatment of structured output, see our guide on getting consistent JSON from Claude without hallucinations.)
The Five-Layer System Prompt Framework
After iterating through enough production failures, I landed on a five-layer structure that makes prompts testable, transferable, and model-agnostic. Every layer has a specific job. Skip one and something breaks.
Layer 1: Identity and Role Boundary
Start with a crisp definition of what the agent is and — critically — what it is not. This isn’t flavor text. It’s the frame that governs all downstream behavior.
You are a contract review assistant for a B2B SaaS company. Your job is to
analyze MSAs, SOWs, and NDAs for non-standard clauses, liability exposure,
and missing standard protections.
You are NOT a lawyer and do not provide legal advice. You identify risks for
review by legal counsel — you do not recommend accepting or rejecting contracts.
The negative definition matters. Without it, users will push the agent toward things it shouldn’t do, and the model will often comply because it’s trying to be helpful. Explicit boundaries prevent scope creep at the prompt level rather than requiring output filtering later.
Layer 2: Behavioral Rules (Explicit, Not Implied)
List the rules as imperatives. Not suggestions. Not principles. Rules.
Rules:
1. Always cite the specific clause or section number when flagging an issue.
2. If a clause is ambiguous, flag it as "Needs Clarification" — do not interpret
intent on behalf of either party.
3. Never summarize without first completing the full analysis.
4. If the document type is unrecognized, say so explicitly before proceeding.
5. Do not reference external legal precedents or case law.
Numbered lists work better than prose paragraphs here. Models attend to list items more reliably than buried sentences in a paragraph, and numbered lists are easier to version-control and audit when something goes wrong.
Layer 3: Output Contract
Define exactly what the response looks like — format, fields, and data types. If you need JSON, write the schema. If you need a structured report, show the skeleton.
{
"document_type": "MSA | SOW | NDA | Unknown",
"risk_flags": [
{
"clause": "string (section reference)",
"issue": "string (one sentence)",
"severity": "High | Medium | Low",
"recommendation": "string (what legal should review)"
}
],
"missing_standard_clauses": ["string"],
"overall_risk_level": "High | Medium | Low",
"requires_legal_review": true
}
This schema goes directly in the system prompt. It removes ambiguity about field names, casing, and value types. When combined with temperature settings near zero for classification tasks, you get output that’s parse-safe 99%+ of the time. If you’re running high-volume batch jobs, this matters enormously — a 1% parse failure rate across 10,000 documents is 100 manual interventions.
Layer 4: Worked Example (The Most Underused Layer)
Include one complete input/output example in the system prompt. Not in a few-shot user message — in the system prompt itself. This is the single biggest improvement I’ve seen across teams who adopt this framework.
## Example
Input: "Section 8.2 states: 'Either party may terminate this agreement for
convenience with 5 days written notice.'"
Output:
{
"clause": "Section 8.2",
"issue": "5-day termination for convenience is significantly below industry
standard (typically 30-90 days), creating operational risk.",
"severity": "High",
"recommendation": "Legal should negotiate minimum 30-day notice period."
}
The example teaches the model the tone, the level of specificity expected, and how to map inputs to the output schema. It acts as a behavioral anchor that persists across long conversations where the initial instructions can drift in influence.
Layer 5: Escalation and Fallback Behavior
What does the agent do when it can’t complete the task? Define it explicitly.
If you cannot complete the analysis because:
- The document is not in English → return {"error": "unsupported_language"}
- The input is too short to analyze (< 100 words) → return {"error": "insufficient_content"}
- The document type is unrecognized → proceed with analysis, set document_type to "Unknown"
Never return an empty risk_flags array without explanation. If no issues are
found, include one entry with severity "Low" noting the document appears standard.
Building this fallback behavior into the prompt means you don’t need to catch it entirely in application code. The agent self-reports failure modes in a structured format your error handling can act on. This connects directly to graceful degradation patterns at the infrastructure level — prompt-level fallbacks and code-level fallbacks should be designed together.
Misconception 1: Longer Prompts Are Always Better
More context helps — up to a point. Past roughly 1,500-2,000 tokens in the system prompt, you start hitting two problems: attention dilution and cost.
On attention dilution: models don’t attend to all parts of a long prompt equally. Instructions buried in the middle of a 3,000-token system prompt are followed less reliably than instructions at the start or end. If you have a rule that’s critical, it should be near the top or repeated at the bottom — not somewhere in the middle after the third paragraph of context-setting.
On cost: a 2,000-token system prompt sent with every request costs roughly $0.006 per call with Claude Sonnet 3.5 at current pricing ($3/M input tokens). At 50,000 calls per month that’s $300/month in system prompt tokens alone, before you count the user message or output. Use prompt caching to cache the system prompt and cut this by 80-90% — it’s one of the highest-ROI optimizations available.
The right prompt length is the minimum necessary to fully specify behavior, with the worked example included. For most agents that’s 600-1,200 tokens. If you’re going longer, audit every sentence for whether it’s actually load-bearing.
Misconception 2: System Prompts Are Model-Agnostic
They are not. A prompt tuned for Claude Sonnet 3.5 will behave differently on Haiku 3.5, and differently again on GPT-4o. This matters if you’re planning to run multiple models in parallel, switch models based on cost, or run evals across model versions.
Concrete differences I’ve observed in production:
- Instruction following: Haiku is more literal; Sonnet will infer intent where Haiku won’t. This means Haiku needs more explicit rules but rewards you with more predictable behavior.
- JSON compliance: All Claude models respond well to JSON schemas in the system prompt. GPT-4o requires more explicit “respond only with valid JSON” instructions to avoid markdown wrapping.
- Rule prioritization: When rules conflict, Claude tends to defer to safety constraints first, then the most recent relevant instruction. If your rules can conflict, test the conflict scenarios explicitly.
If you’re evaluating which model fits your use case, our comparison of Claude Agents vs OpenAI Assistants covers behavioral differences that directly affect how you’ll need to tune your prompts for each.
The practical answer: maintain separate prompt variants per model if your application is cost-sensitive enough to route between models dynamically. Don’t assume a prompt that works on Sonnet will transfer cleanly to Haiku without testing.
Misconception 3: You Can Fix Bad Prompts With Better User Messages
Teams sometimes try to compensate for a weak system prompt by engineering elaborate user message wrappers. This is backwards. The system prompt sets the behavioral frame; the user message operates within it. If the frame is wrong, clever user messages will work inconsistently — some will hit the right behavior, others won’t.
The correct pattern is: write the system prompt until the agent behaves correctly with the simplest possible user input. If you need a 500-token user message preamble to get reliable output, your system prompt is doing too little.
A Real Production Example: Email Lead Qualification Agent
Here’s the system prompt skeleton we used for a lead qualification agent processing inbound sales emails. It runs on Haiku 3.5 for cost (~$0.001 per email at typical lengths) with Sonnet fallback for complex cases.
You are a lead qualification assistant for a B2B software company. You analyze
inbound sales inquiries and classify leads for the sales team.
## Your Role
Classify leads as Hot, Warm, or Cold based on buying signals. Extract key
contact data. Identify the primary use case and urgency signals.
## Rules
1. If company size is mentioned, record it exactly as stated — do not estimate.
2. If urgency is implied but not stated, mark urgency as "Implied" not "High".
3. Do not contact or respond to the sender — analysis only.
4. If the email appears to be spam or automated, set quality to "Discard".
## Output Format
{
"lead_score": "Hot | Warm | Cold | Discard",
"contact": {"name": "string | null", "email": "string | null",
"company": "string | null", "size": "string | null"},
"use_case": "string (one sentence)",
"urgency": "High | Medium | Low | Implied | Unknown",
"buying_signals": ["string"],
"recommended_action": "string"
}
## Example
Input: "Hi, we're a 200-person logistics company looking to replace our
current contract management tool. Need something live by Q2. Who should I
talk to?"
Output:
{
"lead_score": "Hot",
"contact": {"name": null, "email": null, "company": null, "size": "200-person"},
"use_case": "Replace existing contract management tool",
"urgency": "High",
"buying_signals": ["specific use case", "timeline mentioned", "replacement intent"],
"recommended_action": "Route to AE immediately, respond within 2 hours"
}
## Fallback
If email content is fewer than 20 words, return {"error": "insufficient_content"}.
If language is not English, return {"error": "unsupported_language"}.
This runs at roughly $0.001 per email on Haiku, produces parse-safe JSON in 98.7% of cases (tracked across 12,000 runs), and has needed only two prompt iterations in three months of production. The key was specifying every failure mode upfront rather than patching them reactively. If you want to see how this kind of agent integrates into a full pipeline, the AI lead generation email agent walkthrough covers the surrounding infrastructure.
Testing Your System Prompt Before Shipping
A system prompt is software. It needs tests. Run at minimum these four test categories before treating a prompt as production-ready:
- Happy path: 5-10 representative inputs that should work normally. Verify output structure and content quality.
- Edge cases: Empty input, partial input, off-topic input, adversarial input. Verify fallback behavior triggers correctly.
- Rule conflict: Design inputs that should trigger competing rules. Verify the model resolves them the way you’d want.
- Model transfer: If you’re targeting multiple models, run the same test suite on each. Document differences.
Log every test run with the full prompt, input, and output. When you change the prompt, re-run the full suite and diff the outputs. Prompt changes are deployments — treat them accordingly. For a full testing framework, see our guide on evaluating LLM output quality.
When to Use This Framework
Solo founders and small teams: Use the five-layer framework from day one, even for simple agents. The cost is 30 minutes of upfront thinking; the savings are hours of debugging later. Start with Haiku to keep iteration costs near zero, promote to Sonnet only when Haiku’s literal interpretation creates too many false fallbacks.
Teams building multi-agent systems: Define the output contract layer first — it becomes the interface contract between agents. Every agent that receives output from another needs to know exactly what it’s getting. Prompt contracts and code contracts should be versioned together.
Enterprise teams with compliance requirements: The identity and boundary layer is your first line of defense for scope control. Document every constraint and the reason for it. System prompts for agents in regulated environments should go through the same review process as application code.
The framework isn’t magic. A bad prompt well-structured is still a bad prompt. But a good prompt without structure will eventually fail at scale in ways that are hard to debug and harder to fix. Structure first, then tune. That’s the order that works in production.
Frequently Asked Questions
How long should a system prompt for an agent be?
For most production agents, 600–1,200 tokens is the sweet spot. Long enough to fully specify behavior, include a worked example, and define fallback behavior — short enough to avoid attention dilution and keep per-call costs manageable. If your system prompt exceeds 2,000 tokens, audit every sentence to confirm it’s load-bearing and consider whether some content belongs in the user message instead.
Do system prompts work the same way across Claude models?
No. Haiku is more literal and rule-bound; Sonnet will infer intent where Haiku won’t. Prompts that work on Sonnet often need more explicit rules on Haiku. If you’re routing between models based on cost or complexity, maintain separate prompt variants per model and run your test suite on each to document behavioral differences before shipping.
Should I put few-shot examples in the system prompt or the user message?
Put your canonical worked example in the system prompt — it acts as a behavioral anchor that persists across the conversation. Use user message few-shot examples when you need to demonstrate handling of a specific input type that differs from the system-level example. The system prompt example sets the baseline; user message examples handle exceptions.
How do I prevent my agent from going out of scope?
Define what the agent is NOT in the identity layer of the system prompt, using explicit negative statements. Then define fallback behavior for out-of-scope requests in the escalation layer — what should the agent return or say when the input doesn’t match its role? Explicit boundaries in the prompt are more reliable than application-level output filtering because they prevent the out-of-scope response from being generated in the first place.
How do I version control system prompts for agents in a team environment?
Store system prompts as plain text files in your code repository alongside the application code that uses them. Tag prompt versions with semantic versioning (v1.0, v1.1) and require prompt changes to go through the same PR review process as code changes. Maintain a test suite that runs against each prompt version so you can diff behavioral changes between versions before deploying.
Can I use the same system prompt framework for GPT-4o and Claude?
The five-layer structure (identity, rules, output contract, example, fallback) transfers across models, but the content needs tuning per model. GPT-4o needs more explicit JSON-only instructions to avoid markdown wrapping. Claude follows structured schemas more naturally but may elaborate where GPT-4o stays terse. Use the framework as the architecture and treat model-specific tuning as implementation detail.
Put this into practice
Try the Connection Agent agent — ready to use, no setup required.
Editorial note: API pricing, model capabilities, and tool features change frequently — always verify current details on the vendor’s website before building in production. Code examples are tested at time of writing; pin your dependency versions to avoid breaking changes. Some links in this article may be affiliate links — we may earn a commission if you sign up, at no extra cost to you.

