System Prompt
System prompts anchor your agent's behavior across every invocation — but only add one when it earns its tokens. This article covers when to omit, how to structure for production, how to cache large prompts at ~90% cost reduction, and where dynamic prompts open injection vectors you must close.
Quick Reference
- →Omit system_prompt when the user message fully defines the task — adding one without purpose adds noise and cost
- →Production prompts have five layers: role, scope, output format, constraints, examples — in that order
- →system_prompt='...' sets a static persona; never embed user-specific data in a shared static prompt
- →SystemMessage with cache_control caches large prompts on Anthropic — cached reads cost ~10% of standard input tokens
- →@dynamic_prompt generates the prompt at runtime from context_schema — every field it reads from user input is an injection surface
- →Test prompt changes with an eval harness; a change that looks benign can silently break a behavioral constraint
- →Version prompts alongside code — treat a prompt edit as requiring the same review as a code edit
When You Don't Need a System Prompt
Most agents default to having a system prompt. Don't add one by reflex. A system prompt costs input tokens on every call. If the user message fully specifies the task and there is no consistent persona, scope, or output format to maintain across calls, omit it. The agent still works — it infers task from messages and tool descriptions alone.
One-off task agents where the user message is the complete spec. Eval harnesses where you want raw model behavior without persona bias. Debugging sessions where you're isolating whether a problem is in the model or the prompt.