TLDR
Claude is one model family reached through several host surfaces, claude.ai/Desktop, Claude Code, and the raw Messages API/SDKs, and each supplies a different (or absent) scaffold: system prompt, persistent instructions, session hygiene, plugin infrastructure. The Messages API is a blank slate by default: Anthropic states its host system-prompt updates "do not apply to the Claude API," so every convenience a prototype enjoyed in claude.ai must be built explicitly at the API layer. Anthropic: system-prompts release notes
What it is
A Claude application is designed against whichever host surface it runs on, and the surfaces do not behave identically. claude.ai and Desktop inject a versioned system prompt into every conversation (today's date, Markdown-for-code conventions, guardrails); Claude Code auto-loads project memory from CLAUDE.md at the start of every session; a raw messages.create() call gets no default system prompt at all unless you pass your own system parameter. Designing a Claude application means knowing precisely what the host supplies for free and what has to be built explicitly once you leave that host.
This matters most at the boundary where a team prototypes in one surface and ships in another. A prompt tuned inside claude.ai or Claude Code is quietly relying on that surface's injected system prompt, session conventions, and persistent-memory file, none of which travel with the prompt text itself when it moves to POST /v1/messages.
How it works
System prompts are host-specific, not model-inherent. claude.ai/mobile ship a versioned system prompt per conversation; Anthropic is explicit that "these system prompt updates do not apply to the Claude API." A bare Messages API call starts with nothing until you set system yourself, request by request.
Persistent instructions are a Claude Code convention, not an API primitive. CLAUDE.md files "are loaded into the context window at the start of every session, consuming tokens alongside your conversation." The API has no equivalent auto-load: persistent instructions must be re-sent in system or the first message on every single request, or built into your own harness.
Session hygiene is a Claude Code UX layer. /clear resets stale context between unrelated tasks; /compact [focus instructions] summarizes history near context limits and is steerable from CLAUDE.md; /context and /mcp show what is consuming the window. Anthropic recommends keeping CLAUDE.md "under 200 lines," pushing workflow detail into on-demand Skills instead. The API's analogous unit is the message list you build per call plus prompt caching; there is no built-in /compact equivalent, that logic is yours to write.
Plugin management is Claude Code-specific infrastructure. A plugin is a directory containing .claude-plugin/plugin.json plus any of skills/, commands/, agents/, hooks/hooks.json, .mcp.json, .lsp.json, bin/, and settings.json at the plugin root (never inside .claude-plugin/). A plugin's MCP servers auto-start when the plugin is enabled, no manual startup step. Manage plugins via /plugin, add a marketplace with /plugin marketplace add owner/repo, and skills namespace as /plugin-name:skill so two plugins never collide on the same command name.
Schema design and content boundaries live at the API layer as two independent, combinable controls. output_config.format (a JSON Schema) constrains the *response text itself*; strict: true on a tool definition constrains *tool-call arguments* via grammar-constrained sampling, applied per tool. Both support basic types, enum, const, required, additionalProperties: false, select string formats, and minItems of 0 or 1; neither supports minimum/maximum, minLength/maxLength, recursive schemas, or external $ref. Compliance is not guaranteed when stop_reason is "refusal" (the refusal message overrides the schema) or "max_tokens" (the output is simply cut off mid-schema).

Where you'll see it
Internal code-review plugin
A team packages a repeatable code-review workflow as a Claude Code plugin (skills + hooks + an MCP server) and distributes it via an internal marketplace instead of leaving it in one developer's .claude/ directory.
Guaranteed-shape extraction service
A data-extraction endpoint on messages.create() uses output_config.format for the response schema, since no host scaffold like claude.ai's system prompt exists at the API layer to make the output shape trustworthy on its own.
Side-by-side
| Interface | System prompt | Persistent instructions | Session hygiene | Structured output control |
|---|---|---|---|---|
| claude.ai / Desktop | Host-injected, versioned per conversation | Project custom instructions + knowledge base | Host-managed (rolling, chat UI) | None; conversational output only |
| Claude Code | Harness-level, not a per-app system prompt | CLAUDE.md auto-loaded every session | /clear, /compact, /context, /mcp | N/A; agentic coding, not schema-bound output |
| Messages API / SDKs | None; blank slate unless you set system | Must be re-sent every request, no auto-memory | You build it: message list + prompt caching | output_config.format (response) or tool strict: true (args) |
Decision tree
Are you inside a host surface (claude.ai/Desktop or Claude Code), or calling the raw Messages API?
system, persistent instructions, and session logic explicitly.Do you need Claude's output to guarantee a schema?
output_config.format, or a tool's arguments with strict: true, these are independent, combinable controls, not the same knob.Are you building a capability meant to be reused by a whole Claude Code team, not just you?
skills/, hooks/hooks.json, .mcp.json) distributed via a marketplace, not left in one developer's personal .claude/ directory.Is context ballooning toward the window limit?
/compact [focus]; on the API, you implement your own summarization/prompt-caching strategy, there is no server-side /compact.Question patterns

6 V2 questions wired to this concept. Tap an answer to check it instantly - you'll see whether it's right and why - then expand the full breakdown for the mental model and all four rationales.
messages.create() and gets flatter, less-structured output. Why?Tap your answer to check it.
.claude/ directory. What is the correct application-design pattern?Tap your answer to check it.
refund_reason as {"type": "string", "enum": ["approve", "deny"]} with no null option, intending to force a definitive answer even when the source document is silent on a reason. What content-boundary problem does this schema design introduce?Tap your answer to check it.
Tap your answer to check it.
Tap your answer to check it.
Tap your answer to check it.
Frequently asked
Does claude.ai's injected system prompt apply to API calls?
messages.create() call has no default system prompt unless you set system yourself.Do a plugin's MCP servers need to be started manually?
Work this with your AI
Work this concept hands-on with Claude Code, Codex, or claude.ai. Copy a prompt, paste it into your assistant, and practise in tandem. Each one keeps you active (explain it back, get drilled, or build) rather than just reading.
- Drill it like the exam (scenario MCQs)Practice in the exam's scenario-MCQ format with trap awareness.
- Explain it back (Feynman)Build durable, transferable understanding of a concept you can half-state.
- Test me, adapting the difficultyActive recall practice on a concept you think you know.
- Check my prerequisites firstBefore studying a concept that keeps not sticking.
- Find the high-leverage 20%When a domain feels too big and you are short on time.
