DeveloperCCDV-F
Practice
Unofficial community study guide, not affiliated with or endorsed by Anthropic. Claude is a trademark of Anthropic, PBC.
Developer overview
Developer Guide
  1. Preface
  2. 1What This Exam Tests That an Interview Does Not
  3. 2Four Parts to Every Call, and Three Places It Breaks
  4. 3Messages, Streaming, Batches: Who Is Waiting Decides
  5. 4A Model Choice Is Three Numbers You Were Not Given
  6. 5Instruction Placement Is a Trust Decision
  7. 6Schema-Valid Is Not the Same as Correct
  8. 7The Window Is a Budget, and Everything Competes
  9. 8Cost Follows What You Resend, Not What You Ask
  10. 9The Description Is the Input, Not the Documentation
  11. 10One Server, Many Clients, Transport by Locality
  12. 11Four Mechanisms, Decided by What Must Execute
  13. 12Known Steps Take a Chain; Unknown Ones an Agent
  14. 13The Loop, the Harness, and What You Stop Owning
  15. 14Permission Modes and Where the Human Gate Goes
  16. 15The Constraints Nobody States Decide the Design
  17. 16Boundaries, Sessions, and Where Instructions Land
  18. 17REST, Versioning, Review: the Exam Beyond Claude
  19. 18An Unpinned Version Is an Untracked Change
  20. 19A Test Says It Broke; a Trace Says Where
  21. 20The Attack Arrives as Content You Asked For
  22. 21A Rule in a Prompt Is Not Enforcement
  23. 22One Credential: What It Reaches, and for How Long
  24. 23Deploy Is a Phase Boundary, Not the End
  25. Coverage Map
  26. Glossary
Developer overview
Developer Guide·17 / 26·29 min read

Chapter 16: Boundaries, Sessions, and Where Instructions Land

Summary: An application has an edge from the moment it exists: a place where material stops belonging to it and starts being read by a model. Leave that edge undrawn and it is still there, unchecked, because every component assumed the next one was looking. The chapter draws it five times over. What the interface already placed in front of your instruction, what may cross in either direction, what shape an answer has to hold to be consumed, when a conversation gets cleared, and which version of the machinery is running. Any one of them, wrong, produces the same symptom.

Every Application Has an Edge, and It Exists Before Anyone Draws It

Something goes in. A ticket body, a fetched page, a customer record, a schema saying what the answer has to look like. Something comes back out and lands somewhere that acts on it: a database write, a rendered reply, a call to a service that trusts what it was handed.

Between those two moments there is a place where material stops belonging to the application and starts being read by a model. That place exists from the first request anybody sends. Nobody has to design it. Designing it is what makes it checkable.

An edge nobody drew is not an edge that is missing. It is one where nothing gets checked, because no component believes the check belongs to it. Each piece passed its own tests. The seam between them was never anybody's test.

Three things have to be written down before an edge becomes a crossing rule: what is permitted to cross, which single component decides, and what happens to material that fails the decision. Drop the third and the arrangement still reports honestly and still lets everything through, because logging a violation and stopping one are different features. Drop the second and the check gets implemented twice, differently, and the two copies drift. No human owns a shared check, so nobody writes one.

The blueprint names five design areas for a Claude application, and all five are the same question aimed at different traffic.

Design areaWhat it settles about the edge
InterfaceWhat already sits inside the boundary before your instruction arrives
Content boundariesWhat is allowed to cross, inbound and outbound, and who checks
SchemaThe shape material has to hold to cross outward and be consumed
Session hygieneWhen everything inside the boundary is cleared, and on what trigger
Plugin managementWhich version of the machinery around the edge is currently running

Read that table as one subject rather than five. A defect in any row shows up as the same symptom: material crossed, and nothing stopped it.

The Same Instruction Arrives Into a Different Standing Context on Every Interface

Write one sentence of guidance. Send it through the API. Send the identical sentence through the SDK, then type it into the terminal. Three different behaviours are a normal outcome, and no interface is broken.

The reason is that your sentence is never the whole instruction. It joins whatever the surface already put in front of the model, and the surfaces differ enormously in how much that is. Your text is the last layer.

The Messages API supplies nothing at all. It is stateless, so every request carries the full conversational history explicitly, and anything not written into that request is absent.1 No project file loads. No standing preference persists. Your code is the only thing that remembers anything.

The SDK is where the surprise usually lands. With no system prompt configured, the SDK runs a minimal default that covers tool calling and leaves out Claude Code's coding guidelines, its response style and its project context. Ask for the claude_code preset instead and the model receives the full prompt the CLI uses: tool usage instructions, code style and formatting rules, tone and verbosity, security instructions, and context about the working directory. Headless CLI runs use that full prompt by default, which is exactly why an instruction that behaved one way under claude -p behaves another way under a bare SDK call.2 Same words, different standing prompt, and no error anywhere.

Project context arrives on a separate track again. CLAUDE.md is injected into the conversation as project context rather than into the system prompt, so it composes with whichever prompt was chosen, and it loads according to the configured setting sources rather than according to the preset.2 Two independent switches, and a design that assumes one implies the other will be wrong on half its deployments. Set both deliberately.

Then the interactive surfaces keep their own histories. The CLI, the desktop app, the web version and the editor extension each maintain a separate session store.3 "The conversation" is not one object that the user moves between windows. Each window keeps its own, and none of them syncs.

SurfaceWhat is already in context before your textWho holds the history
Messages APIOnly what the request containsYour application, entirely
Agent SDK, unconfiguredA minimal prompt covering tool callingThe SDK, per session ID
Agent SDK with the coding presetFull coding guidance, style, safety, working directoryThe SDK, per session ID
Headless CLIThe same full prompt, by defaultLocal transcript files
Interactive surfacesThat surface's own configuration and project filesThat surface, separately from the others

The design consequence is narrower than "test on every interface", which is advice nobody can act on. It is that a rule your application depends on has to be stated where the interface will actually read it, and the interfaces read different places. A constraint that lives in a project file is invisible to an API integration that never loads project files. A constraint written into a system prompt string is absent from a terminal session that uses the preset. Behaviour that is meant to hold everywhere gets stated once per channel, deliberately, and the statement is part of the application rather than part of somebody's local setup.

Anthropic's own test for whether a custom prompt is warranted is worth borrowing as a design question, because it is about the product rather than the prose. The further your agent sits from a coding assistant working in a repository with a human watching and steering, the more of the standing prompt you should be writing yourself: a different surface where output is not read in a terminal, a different identity that should not present as a coding tool, a different permission model where nobody approves each step, or work that is not coding at all, where coding guidance competes with the instructions you need.2

The instruction inherited by accident is the anti-pattern here. Somebody prototypes against the preset, likes the behaviour, and ships an integration that supplies its own prompt. Half the behaviour they liked came from the preset and is now gone, and the symptom is a quality complaint rather than an error. Nobody removed anything on purpose, which is why the loss is hard to trace.

Context Shapes a Decision; Only a Deterministic Gate Removes One

Both of Claude Code's memory systems, the files you write and the notes it accumulates, load at the start of every conversation. Both are read as context rather than as enforced configuration. To block an action regardless of what the model decides, the documentation points at a pre-tool hook instead.4

That distinction generalises well past any one product. Text that reaches the model influences a decision. Code that runs before the action removes the decision. Everything on the first side degrades gracefully and probabilistically; everything on the second side either runs or does not. Only one of them binds.

So a crossing rule written only as a sentence in a prompt is a preference with good adherence. It belongs there as well, because a model told what the policy is behaves better than one left to infer it. It just cannot be the only place, and the exam pressure-tests exactly this: an option that improves how reliably an instruction is followed is not an option that guarantees anything.

Adherence is still worth engineering. Specific, concise, well structured instructions are followed more consistently than long ones, and the documented sizing guidance is blunt: keep a project instruction file under about 200 lines, because a longer file consumes more context and reduces adherence.4 Concreteness is the other half. A rule stating which directory handlers live in is checkable by a human reading the output. A rule saying to keep files organised is not.

Content Boundaries Run in Two Directions, and the Outbound One Gets Forgotten

Inbound is the direction everybody designs for. Untrusted material reaching the model is a documented threat with documented handling: deliver third-party content inside tool_result blocks rather than in system prompts or plain user text, say in the tool description what the content is and where it came from, state in the system prompt that tool and document content is data that never overrides instructions, and wrap third-party strings in JSON so an attacker cannot close a delimiter and continue as an instruction.5 Chapter 5 owns where those blocks sit in a prompt and chapter 20 owns the attack itself. What belongs here is the placement rule read as a design constraint rather than as a security tip: the channel a piece of content arrives on is what sets its authority, so a component that concatenates fetched text into a standing instruction has promoted it, whatever anybody intended.

Two further inbound rules are easy to get backwards. Your own instructions do not belong in tool results, because content there is treated as untrusted, so guidance placed in a result may be ignored or flagged; send it in the user turn that follows the result instead.5 And screening runs on tool output as well as on user input: a small classifier call over what the tool returned, with a parseable verdict the application branches on, before the content is handed back as a result at all. Screen both directions, because only one of them looks dangerous.5

Outbound is the direction that fails a review. Material crossing to the model leaves whatever perimeter it was sitting in, and the properties of the receiving side are a design input rather than a procurement detail. Ask before you build.

Outbound questionWhat settles itWhat it constrains
Is anything kept after the response returnsA zero-retention arrangement, enabled per organisationWhether prompts and responses persist at rest at all6
Is health information in scopeA signed agreement and a readiness-enabled organisationWhich features may carry it, and what safeguards apply6
Where does inference physically runA per-request geography parameter, or a workspace defaultWhich regions may serve the request, at a stated price multiplier7
Where is the workspace itselfChosen at creation and not changeable afterwardsA decision you make once, before there is an application7

Two details in that material are worth carrying whole because they decide scenarios. The first is where regulated content actually turns up: in message content, in attached files, and in file names and metadata associated with message content, while workspace names, user contact details, billing data and support tickets are not expected to carry it.6 A boundary drawn around "the prompt" and not around the filename of the attachment is drawn in the wrong place. Metadata travels with the file, and the rule has to cover it.

The second is a genuine trap and it sits precisely where this chapter's two halves meet. Schemas sent for constrained output are compiled and cached separately from message content, and those cached schemas do not receive the same protections as prompts and responses. Regulated content must not appear in a schema definition.6 Field names and descriptions feel like configuration rather than data, which is why somebody eventually writes a patient identifier into an enum. Schemas are data too.

Least privilege is the last inbound-and-outbound rule at once: scope what the model can reach so that a successful injection has little to work with, run tools in sandboxed environments, and keep secrets it does not need out of its reach entirely.5 A boundary that permits everything through is still a boundary. It is just one where the crossing rule reads "anything".

The Schema Is a Contract With Three Parties, Not Just With the Model

A schema attached to a request looks like a formatting preference. It is a contract, and it binds in three directions at once: the model is constrained by it, downstream code is written against it, and the platform compiles it into something with properties of its own. Three parties, one document.

Constrained sampling is the mechanism, using compiled grammar artifacts built from the schema.8 That has consequences no prompt-level formatting request has, and they are design consequences rather than runtime ones.

Property order is not schema order. Required properties appear first, in the order the schema gives them, and optional properties follow. Where output order matters to a consumer, either mark everything required or write the parsing so reordering is expected.8 A consumer that reads positionally is a consumer that breaks the first time somebody makes a field optional. Read fields by name, never by position.

Enumerated values are not guaranteed to match your capitalisation. The response completes normally, raises no error and carries no special stop reason, and the value differs from the schema only in a capital letter. Compare case-insensitively, and never define two enum values that differ only in case.8 A downstream branch keyed on exact string equality is where this surfaces, several stages away from the request. Lowercase both sides before comparing, and the class of defect disappears.

The schema the model receives may not be the schema you wrote. SDK helpers strip features the platform does not support, adding the constraint to the field's description instead and closing objects to additional properties, so numeric and length bounds are enforced by your validation rather than by the grammar.8 The contract is still honoured. It is honoured in two places, and only one of them is the model.

Complexity is a budget with a hard edge. There are documented ceilings on how many strict tools one request may carry, on optional parameters across all schemas in the request, and on parameters with union types, which are the expensive ones because they multiply compilation cost. Exceed the compiled size and the request fails outright with a complexity error, even when every individual limit was satisfied.8 Schema design is therefore a shared resource across a request rather than a per-field decision. Budget it across the whole request.

There is one more party to the contract and it is the one scenarios test hardest. A single call carries exactly one output contract. When a system does two things that are judged differently, a classification whose success means the right category and a drafted reply whose success means an acceptable answer, those are two contracts and one call cannot hold both. The reflex argument for merging them is cost, and it holds only while quality is left out of the comparison. Separate calls give each stage a schema shaped for its own output, a prompt aimed at one job, and an evaluation against the standard that actually applies to it.

The schema written for the model alone is the named failure. It describes what a good answer contains, reads beautifully, and never asked the consumer what it needs to be able to do with the result. Then somebody adds a field, the parser keeps working because the parser was lenient, and a downstream service quietly receives a shape nobody agreed to. Chapter 6 owns validating what comes back. The design obligation here is upstream of that: the schema is written from the consumer's requirements, and it changes on the consumer's schedule. Ask the consumer first.

Continue, Resume and Fork Answer Different Questions About Whose History You Get

No interface will define a session for you. The API has no such concept, since every request carries its own history. The SDK gives you three ways to reach an existing one, and they differ in how the session is found rather than in what they do afterwards.

Continue picks up the most recent session in the current directory, so nothing has to be tracked. Resume takes a specific identifier that your application captured and stored, which is what multi-user applications need. Fork copies an existing history into a new session with a new identifier, leaving the original's history untouched, so two independent threads exist afterwards.9

Read those definitions as an access-control question and one of them becomes alarming. "The most recent session in this directory" is not the same statement as "this user's session". In a service handling several conversations at once, continue resolves by recency rather than by identity, which is the shape of the defect an exam will describe: context from one conversation surfacing in an unrelated one, with no bug anywhere in the code. Identity has to select the session, and only an identifier does that.

Session files are local to the machine that created them, so an application running on ephemeral workers or containers cannot resume by identifier alone. Attaching a session store mirrors transcripts to your own backend, and the lookup key derives from the working directory, so a resuming host has to match the directory the original run used.9 That is a deployment constraint hiding inside a conversation feature. Transcripts do not travel, and neither does the assumption that they do.

Resumption also restores less than people assume, and the gaps are deliberate. Conversation history returns in full. The model and the configured agent return. The permission mode returns with named exceptions: plan mode and a bypass mode are never restored, so a resumed session starts in the mode a new session would. Command-line configuration passed at launch, including settings files, server configuration, plugin directories and added directories, has to be passed again, while the standard settings files are re-read on their own.3 Pass your launch flags again.

One pattern runs through all of it. Content is restored and posture is not. Anything that widens what the session may do is re-established deliberately at launch, which is the right default and is also why an operator who resumed and assumed their elevated mode came back is running with less authority than they think, and an application that resumed and assumed its flags came back is running with less configuration than it needs. Re-establish posture at launch, explicitly, every time the session comes back.

Three Doors Lead Into a New Conversation, and a Timeout Closes Only One

Stale context leaking into an unrelated conversation is the failure this whole area exists to prevent, and it has a specific shape: material that was correct for a finished task turns up in a task that has nothing to do with it, phrased confidently, sourced from nothing the current user said. Nobody typed it.

A single timeout is the usual proposed fix and it is genuinely half an answer. There are three separate ways a conversation ends, and each one lets material through that the others catch.

DoorWhat triggers itWhat it fails to cover alone
The clockIdle time, or an absolute age since the session startedA session in continuous use that changed subject an hour ago
An eventLogout, a completed transaction, a role change, an error the application cannot recoverNothing at all happening for a long stretch between events
IntentThe application deciding this request begins new work, or the user saying soAnything the user does not think to ask for, since the guarantee then rests on their behaviour

Read the third row carefully, because it is the one that gets offered as sufficient. Handing the reset to the user makes the property depend on a human remembering. Guarantees do not live in habits.

So the shape of a defensible answer is all three together: expiry, so an abandoned session cannot live forever; reset triggers, so defined events clear state the moment they happen; and fresh-start rules, so the application itself knows when a request is new work rather than a continuation. Each door closes a path the other two leave open, which is why the arithmetic here is addition and not selection.

Two operational facts sit under the design. Transcripts are retained, on a documented default measured in years, or for whatever finite retention period an organisation has configured, so "the session ended" and "the material is gone" are unrelated claims.6 And a long-idle session picked up again may be restored from a summary rather than in full, because the cache behind it has expired, which means the continuity a user experiences and the tokens actually resent are two different things.3 Deletion is a separate question with a separate answer.

The named failure is the session that ends only when somebody closes the tab. It is not a missing feature. It is a feature that was never specified, so the default became whatever the interface happened to do.

Plugin Versions Are Pinned So a Regression Has Somewhere to Land

The last row of the opening table is the machinery around the edge, and it moves on its own unless somebody stops it.

The default is the part worth memorising. A declared dependency tracks the latest available version, so an upstream release changes what is running under your extension without any action, notification or record on your side.10 Nothing failed. The set of things running simply is no longer the set that was tested.

A version constraint is what converts that into a decision. Holding a dependency inside a tested range keeps installs on the highest matching patch and moves the upgrade to a moment somebody chose, by publishing a new version with a wider range.10 Several constraints on the same dependency intersect, resolving to the highest version satisfying all of them, and when nothing satisfies every range the update is skipped and reported with the constraining extension named.10 A conflict surfaces as a conflict rather than as behaviour.

Resolution runs against tags on the repository holding the dependency, under a naming convention pairing the plugin name with the version, and that version is expected to match the manifest at that commit.10 Two defaults sit alongside it and both are crossing rules with a default already chosen. Automatic updating is off by default for marketplaces Anthropic does not operate. And a dependency living in a different marketplace from the extension declaring it is refused by default, opened only by an allowlist on the marketplace hosting the extension being installed, with trust deliberately not chaining through intermediates.10 Trust is declared, never inherited.

Chapter 18 owns versioning as an operational practice. What belongs to design is narrower and it is a single obligation: attribution requires a record made before the change. A regression can be traced to a component only if what that component was is written down somewhere that predates the symptom. Pinning is how the record gets made, and rollback is the capability the record buys. An unpinned dependency does not merely risk breaking. It removes the possibility of proving what broke.

One packaging detail crosses into design rather than staying in operations. A bundle's name prefixes every command it ships, which is what lets two bundles ship the same command name without colliding, and renaming the bundle renames all of them.11 The name is part of the interface, so it is chosen once, early, by somebody thinking about the interface rather than about the directory.

The dependency that tracks latest is the anti-pattern, and it is almost never a decision. It is the absence of one, wearing the appearance of staying current.

How Wrong Answers Are Built on This Material

Wrong answers on application design are unusually convincing, because most of them describe real engineering that a competent team does. What makes one wrong is a single assumption sitting under it, and four assumptions produce most of them.

  • A guarantee claimed for a mechanism that only improves adherence. An option strengthens a written instruction, restructures a prompt, or adds guidance about what the model should refuse, in answer to a scenario asking that something never happen. Instructions shift probability. Code that runs before the action decides. Whenever the requirement contains the word never, ask which component would have to fail for the outcome to occur, and pick the option that names one.
  • One control offered against a failure with several entrances. A timeout aimed at stale context, a screen on user input while tool output goes unchecked, a check at one seam in a system with four. The option is correct about the path it covers and silent about the rest, which is what makes it read as an answer. A scenario naming several ways in wants a set, not a pick.
  • A boundary drawn around the obvious payload and not around its neighbours. Prompts protected while attachment filenames, schema definitions, cached artifacts and transcript retention go unconsidered. Ask what else travelled with the content, and what is stored that is not the content.
  • Enforcement placed where the habit is rather than where the authority is. Instructions written into tool results, standing rules appended to the newest turn, a policy documented for humans and checked by nobody, a session that resolves by recency where identity was required. Each one puts the control on a channel that carries no weight. Name the channel each option acts on, then ask whether that channel binds anything.

Match on what the scenario is doing rather than on the domain it is dressed in.

When the scenario saysThe answer is usuallyThe trap is usually
Context from a finished conversation surfaced in an unrelated oneExpiry, defined reset events, and application-owned rules for starting fresh, togetherA single timeout, or asking users to start a new conversation themselves
The same guidance behaves differently in the terminal and in an integrationState the rule on the channel each interface actually readsTreating one surface's default context as if every surface supplied it
A requirement says an action must never be possibleA deterministic check that runs before the actionStronger wording, more emphasis, or a better-written instruction file
Fetched or third-party content reaches the modelDeliver it as tool results, labelled, delimited, and screened before it is returnedConcatenating it into the standing instruction so the model definitely sees it
Two stages have different inputs, outputs and standards of successSeparate calls, each with its own contract and its own evaluationOne call for both, argued on token cost with quality left out
Downstream consumers keep breaking on well-formed outputWrite the schema from what the consumer needs, and version it on the consumer's scheduleA schema describing a good answer, with parsing loosened until it passes
Regulated or sensitive data is in scopeAsk where it appears, including filenames, metadata and schema definitionsProtecting message bodies alone and treating configuration as out of scope
A behaviour changed and nobody can say which component movedPinned versions recorded before the change, giving a rollback targetReproducing it, adding logging, or updating everything to current
Where processing physically happens is a requirementThe geography controls, chosen against a decision that may be unchangeable laterTreating placement as an operational detail settled after the build
Sessions are resumed on a different machine or workerExternal session storage, keyed consistently, with identity selecting the sessionResuming by recency, or assuming a local transcript is reachable elsewhere

One habit transfers past the table. For every option, ask what would have to be true for the guarantee to hold, and then ask who checks it. If the answer to the second question is the model, the option is describing an improvement rather than a control.

What to Remember

  • A crossing rule names three things: what may cross, which component decides, and what happens to material that fails. An edge with no rule is not an absent edge, it is one where nothing is checked because no component believes the check is its own.
  • Interfaces differ in what already sits in context before your text arrives. The API is stateless and supplies nothing; the SDK defaults to a minimal prompt covering tool calling, with the coding preset carrying full style, safety and working-directory context; headless runs use that full prompt by default. A rule the application depends on is stated once per channel.
  • Project instruction files load as conversation context, not as system prompt, and load by setting source rather than by preset. Two switches, neither implying the other.
  • Context shapes a decision; a deterministic gate removes one. Instruction files and accumulated notes are read as context, never as enforced configuration, so blocking an action regardless of what the model decides needs a hook or a check that runs first.
  • Authority follows the channel content arrived on. Third-party material belongs in tool results, labelled and delimited, with the policy stated in the system prompt; your own instructions do not belong in tool results, because content there is treated as untrusted and may be ignored.
  • Content boundaries run outbound too. Regulated data appears in message content, attached files, and filenames and metadata, and not in workspace names, user contact details, billing or support tickets. Schemas are compiled and cached separately and do not carry the same protections, so no regulated value goes in a schema definition.
  • Geography is two settings: a per-request inference control with a workspace default, and a workspace location fixed at creation that cannot be changed afterwards.
  • A schema is a contract with the model, the consumer, and the platform. Required properties are emitted first, then optional ones; enum capitalisation is not guaranteed, so compare case-insensitively; SDK helpers strip unsupported constraints and enforce them in your validation instead; and strict tools, optional parameters and union types share one complexity budget that fails the request when exceeded.
  • One call carries one output contract. Stages judged by different standards of success need separate calls with separate schemas, and the cost argument for merging them omits quality.
  • Continue resolves by recency, resume resolves by identifier, fork copies a history into a new identifier. In anything serving more than one conversation, identity must select the session, which only an identifier does.
  • Resuming restores content, not posture. History, model and agent return; plan and bypass permission modes never do, and launch-time configuration must be passed again. Session files are local to the machine that made them, so cross-host resumption needs an external store.
  • Three doors lead into a new conversation: the clock (idle or absolute age), an event (logout, completion, role change, unrecoverable error), and intent (the application deciding the request is new work). All three are required, because each covers a path the other two leave open, and a rule that depends on the user acting is not a guarantee.
  • Ending a session does not delete the transcript. Retention runs on a documented default measured in years, or on the organisation's configured period.
  • An unpinned dependency tracks latest, so upstream releases change what is running with no action and no record. Constraints intersect across everything that declares them and a conflict is reported rather than silently resolved.
  • Attribution requires a record made before the change. Pinning creates it, rollback is what it buys, and an unpinned component removes the ability to prove what broke.

Endnotes for this chapter

  1. The Messages API is stateless, so the full conversational history is sent on every request; a message with the system role may be placed after a user turn on supported models, carrying the same authority as the top-level system field, while the top-level field holds instructions applying from the first turn. Anthropic, Using the Messages API (Claude Platform Docs, accessed 2026-09-09), https://platform.claude.com/docs/en/build-with-claude/working-with-messages

  2. The Agent SDK's three starting points for a system prompt: a minimal default covering tool calling that omits Claude Code's coding guidelines, response style and project context; the claude_code preset carrying tool usage instructions, code style and formatting guidelines, response tone and verbosity rules, security and safety instructions and working-directory context, optionally with an appended addition; and a custom string, where only what is supplied is sent. Headless CLI runs use the full Claude Code prompt by default, which differs from the SDK's minimal default. The deciding factors for writing a custom prompt are a different surface, a different identity, a different permission model, or non-coding tasks where coding guidance competes with the needed instructions. CLAUDE.md content is injected into the conversation as project context rather than into the system prompt, and its loading is governed by setting sources rather than by the preset. Anthropic, Modifying system prompts (Claude Code Docs, accessed 2026-09-09), https://code.claude.com/docs/en/agent-sdk/modifying-system-prompts

  3. The CLI, desktop app, web version and editor extension each maintain their own session history; a resumed session restores conversation history including tool calls and results, the model, the configured agent and the permission mode, with plan and bypass modes never restored so the session resumes in the mode a new session would start in; command-line configuration for server configuration, settings files, plugin directories, fallback model and added directories must be passed again on resume, while standard settings files are re-read at launch; and a long-inactive, large session may be resumed from a summary because its prompt cache has expired. Anthropic, Manage sessions (Claude Code Docs, accessed 2026-09-09), https://code.claude.com/docs/en/sessions

  4. CLAUDE.md files and auto memory are both loaded at the start of every conversation and are treated as context rather than as enforced configuration, with a PreToolUse hook named as the way to block an action regardless of what Claude decides; instruction files should target under 200 lines because longer files consume more context and reduce adherence; and specific, concrete, verifiable instructions are followed more consistently than general ones. Anthropic, How Claude remembers your project (Claude Code Docs, accessed 2026-09-09), https://code.claude.com/docs/en/memory

  5. Untrusted third-party content should be delivered inside tool_result blocks rather than in system prompts or plain user text blocks; the tool description or result structure should make the nature and source of the content explicit; the system prompt should state that content returned from tools, documents or searches is untrusted data that must never override the system prompt or the user's request; untrusted strings should be JSON-encoded so escaping provides unambiguous delimiters; your own instructions should not be placed in tool results, because content there is treated as untrusted and may be ignored or flagged, and should be sent in a user turn following the result; tool outputs should be screened by a lightweight classifier call using structured outputs before being returned as results; and least privilege should be applied so a successful injection can do minimal damage, with sandboxed tools and narrowly scoped permissions. Anthropic, Mitigate jailbreaks and prompt injections (Claude Platform Docs, accessed 2026-09-09), https://platform.claude.com/docs/en/test-and-evaluate/strengthen-guardrails/mitigate-jailbreaks

  6. Under a zero data retention arrangement, enabled per organisation, Anthropic does not store customer prompts or responses at rest after the API response is returned; HIPAA readiness requires a signed BAA and a HIPAA-enabled organisation and applies encryption, access controls and audit logging rather than immediate deletion; protected health information typically appears in message content, attached files and file names or metadata associated with message content, while workspace names, user information, billing data and support tickets are not expected to contain it; JSON schemas used for structured outputs and strict tools are compiled into grammars cached separately from message content and do not receive the same protections, so PHI must not be included in schema definitions; and local session transcripts are stored for six years by default or for an organisation's configured finite conversation retention period, with remote session transcripts retained for six years. Anthropic, API and data retention (Claude Platform Docs, accessed 2026-09-09), https://platform.claude.com/docs/en/manage-claude/api-and-data-retention

  7. The inference_geo parameter controls where model inference runs for a specific request, with workspace settings restricting the available geographies and setting a default when the parameter is omitted; workspace geography is set when the workspace is created and cannot be changed afterwards; and regional inference is priced at 1.1 times the standard rate across all token pricing categories. Anthropic, Data residency (Claude Platform Docs, accessed 2026-09-09), https://platform.claude.com/docs/en/manage-claude/data-residency

  8. Structured outputs constrain responses to a schema using constrained sampling with compiled grammar artifacts; required properties are emitted first in schema order followed by optional properties, so schemas whose output order matters should mark all properties required or account for reordering; enum and const capitalisation is not guaranteed and a differing value completes normally with no error and no special stop reason, so enum values should be compared case-insensitively and values differing only in capitalisation avoided; SDK helpers transform schemas by removing unsupported constraints such as numeric and length bounds, moving them into the field description and adding additionalProperties: false, so the model receives a simplified schema while the code enforces the original constraints through validation; and complexity limits cap strict tools per request, total optional parameters and parameters using union types, with additional internal limits on compiled grammar size producing a 400 error when exceeded. Anthropic, Structured outputs (Claude Platform Docs, accessed 2026-09-09), https://platform.claude.com/docs/en/build-with-claude/structured-outputs

  9. Continue picks up the most recent session in the current directory with no identifier tracked, while resume takes a specific session ID and is required for multiple sessions such as one per user; forking creates a new session starting from a copy of the original's history with its own session ID, leaving the original's ID and history unchanged; session IDs are read from the result message; and session files are local to the machine that created them, so resuming on another host requires a session store adapter whose lookup key derives from the working directory. Anthropic, Work with sessions (Claude Code Docs, accessed 2026-09-09), https://code.claude.com/docs/en/agent-sdk/sessions

  10. By default a plugin dependency tracks the latest available version, so an upstream release can change it without warning; a version constraint holds a dependency at a tested range until the dependent plugin publishes a new version with a wider constraint; where several installed plugins constrain the same dependency the ranges are intersected and resolved to the highest version satisfying all of them, and when no version satisfies every range the update is skipped and reported with the constraining plugin named; constraints resolve against git tags on the repository hosting the dependency, tagged as the plugin name paired with the version and matching the manifest version at that commit, with non-git sources checked at load time and the dependent plugin disabled when unsatisfied; auto-update is off by default for non-Anthropic marketplaces; and a dependency in a different marketplace from the plugin declaring it is refused unless the root marketplace names the target in its allowlist, with trust not chaining through intermediate marketplaces. Anthropic, Constrain plugin dependency versions (Claude Code Docs, accessed 2026-09-09), https://code.claude.com/docs/en/plugin-dependencies

  11. A plugin manifest defines the plugin's identity through its name, description and version; plugin skills are always namespaced with the plugin's name as the prefix so that plugins shipping identically named skills do not collide, and changing the name field changes that prefix. Anthropic, Create plugins (Claude Code Docs, accessed 2026-09-09), https://code.claude.com/docs/en/plugins

For detailed info, read the official docs

  • Using the Messages API
    platform.claude.com
  • Agent SDK: Modifying system prompts
    code.claude.com
  • Manage sessions
    code.claude.com
PreviousChapter 15: The Constraints Nobody States Decide the DesignNextChapter 17: REST, Versioning, Review: the Exam Beyond Claude