Follow Discord
Sweep 22 Oct 2026 · 04:32Z Build v2.1.308 527 read Stable v2.1.308 Latest v2.1.308 Next v2.1.308 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One change · claude-code

Modifying system prompts changedagent-sdk/modifying-system-prompts

Nearest release: v2.1.300, published 7 hours before upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Upstream edited this page at 14 Oct 2026 21:42 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 20 Oct 2026 18:37 UTC.

Upstream edited
Recorded here
Lines+306added
Lines−318removed
From line 46 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits17to this page, all time

The whole hunk

from line 46, old and new numbered
/
lines

The two sides of this change are more than 400 edits apart, too far apart to line up, so this is the differ's own diff of it and the words inside a line are not marked.

from line 46
4646 
4747To load CLAUDE.md, set `settingSources` to include the level where you keep your CLAUDE.md. The example below loads a project-level CLAUDE.md alongside the `claude_code` preset, so Claude has both the coding-agent prompt and your project's conventions:
4848 
49<CodeGroup>
50 ```typescript TypeScript theme={null}
51 import { query } from "@anthropic-ai/claude-agent-sdk";
52 
53 const messages = [];
54 
55 for await (const message of query({
56 prompt: "Add a new React component for user profiles",
57 options: {
58 systemPrompt: {
59 type: "preset",
60 preset: "claude_code" // Use Claude Code's system prompt
61 },
62 settingSources: ["project"] // Loads CLAUDE.md from project
63 }
64 })) {
65 messages.push(message);
66 }
67 
68 // Now Claude has access to your project guidelines from CLAUDE.md
69 ```
70 
71 ```python Python theme={null}
72 import asyncio
73 
74 from claude_agent_sdk import query, ClaudeAgentOptions
75 
76 messages = []
77 
78 
79 async def main():
80 async for message in query(
81 prompt="Add a new React component for user profiles",
82 options=ClaudeAgentOptions(
83 system_prompt={
84 "type": "preset",
85 "preset": "claude_code", # Use Claude Code's system prompt
86 },
87 setting_sources=["project"], # Loads CLAUDE.md from project
88 ),
89 ):
90 messages.append(message)
91 
92 
93 asyncio.run(main())
94 
95 # Now Claude has access to your project guidelines from CLAUDE.md
96 ```
97</CodeGroup>
49```typescript TypeScript theme={null}
50import { query } from "@anthropic-ai/claude-agent-sdk";
51 
52const messages = [];
53 
54for await (const message of query({
55 prompt: "Add a new React component for user profiles",
56 options: {
57 systemPrompt: {
58 type: "preset",
59 preset: "claude_code" // Use Claude Code's system prompt
60 },
61 settingSources: ["project"] // Loads CLAUDE.md from project
62 }
63})) {
64 messages.push(message);
65}
66 
67// Now Claude has access to your project guidelines from CLAUDE.md
68```
69 
70```python Python theme={null}
71import asyncio
72 
73from claude_agent_sdk import query, ClaudeAgentOptions
74 
75messages = []
76 
77 
78async def main():
79 async for message in query(
80 prompt="Add a new React component for user profiles",
81 options=ClaudeAgentOptions(
82 system_prompt={
83 "type": "preset",
84 "preset": "claude_code", # Use Claude Code's system prompt
85 },
86 setting_sources=["project"], # Loads CLAUDE.md from project
87 ),
88 ):
89 messages.append(message)
90 
91 
92asyncio.run(main())
93 
94# Now Claude has access to your project guidelines from CLAUDE.md
95```
9896 
9997When you run either example, the SDK streams messages as Claude works: a system init message, assistant messages, user messages carrying tool results, and a final result message with the session outcome.
10098 
from line 146
148146 
149147You can use the Claude Code preset with an `append` property to add your custom instructions while preserving all built-in functionality.
150148 
151<CodeGroup>
152 ```typescript TypeScript theme={null}
153 import { query } from "@anthropic-ai/claude-agent-sdk";
154 
155 const messages = [];
156 
157 for await (const message of query({
158 prompt: "Help me write a Python function to calculate fibonacci numbers",
159 options: {
160 systemPrompt: {
161 type: "preset",
162 preset: "claude_code",
163 append: "Always include detailed docstrings and type hints in Python code."
164 }
149```typescript TypeScript theme={null}
150import { query } from "@anthropic-ai/claude-agent-sdk";
151 
152const messages = [];
153 
154for await (const message of query({
155 prompt: "Help me write a Python function to calculate fibonacci numbers",
156 options: {
157 systemPrompt: {
158 type: "preset",
159 preset: "claude_code",
160 append: "Always include detailed docstrings and type hints in Python code."
165161 }
166 })) {
167 messages.push(message);
168 if (message.type === "assistant") {
169 console.log(message.message.content);
162 }
163})) {
164 messages.push(message);
165 if (message.type === "assistant") {
166 console.log(message.message.content);
167 }
168}
169```
170 
171```python Python theme={null}
172import asyncio
173 
174from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage
175 
176messages = []
177 
178 
179async def main():
180 async for message in query(
181 prompt="Help me write a Python function to calculate fibonacci numbers",
182 options=ClaudeAgentOptions(
183 system_prompt={
184 "type": "preset",
185 "preset": "claude_code",
186 "append": "Always include detailed docstrings and type hints in Python code.",
187 }
188 ),
189 ):
190 messages.append(message)
191 if isinstance(message, AssistantMessage):
192 print(message.content)
193 
194 
195asyncio.run(main())
196```
197 
198#### Improve prompt caching across users and machines
199 
200By default, two sessions that use the same `claude_code` preset and `append` text still can't share a prompt cache entry when their auto memory locations differ. The preset embeds that location in the system prompt ahead of your `append` text. The location defaults to an absolute path under `~/.claude/projects/` named for the repository's path on disk, so it differs across users, machines, and checkouts.
201 
202CLAUDE.md content and environment details such as the working directory, platform, shell, and OS version don't affect the system prompt cache, because Claude Code delivers them in the conversation, not the system prompt.
203 
204To make the system prompt identical across sessions, set `excludeDynamicSections: true` in TypeScript or `"exclude_dynamic_sections": True` in Python. The per-user context moves into the first user message, leaving only the static preset and your `append` text in the system prompt so identical configurations share a cache entry across users and machines.
205 
206> [!NOTE]
207>
208> `excludeDynamicSections` requires `@anthropic-ai/claude-agent-sdk` v0.2.98 or later, or `claude-agent-sdk` v0.1.58 or later for Python. Set it on the preset object form only. The SDK ignores it when you pass a custom prompt instead of the preset; to keep a custom prompt's instructions cached in the TypeScript SDK, see [Cache the static part of a custom prompt](#cache-the-static-part-of-a-custom-prompt).
209 
210The following example pairs a shared `append` block with `excludeDynamicSections` so a fleet of agents can reuse the same cached system prompt:
211 
212```typescript TypeScript theme={null}
213import { query } from "@anthropic-ai/claude-agent-sdk";
214 
215for await (const message of query({
216 prompt: "Triage the open issues in this repo",
217 options: {
218 systemPrompt: {
219 type: "preset",
220 preset: "claude_code",
221 append: "You operate Acme's internal triage workflow. Label issues by component and severity.",
222 excludeDynamicSections: true
170223 }
171224 }
172 ```
173 
174 ```python Python theme={null}
175 import asyncio
176 
177 from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage
178 
179 messages = []
180 
181 
182 async def main():
183 async for message in query(
184 prompt="Help me write a Python function to calculate fibonacci numbers",
185 options=ClaudeAgentOptions(
186 system_prompt={
187 "type": "preset",
188 "preset": "claude_code",
189 "append": "Always include detailed docstrings and type hints in Python code.",
190 }
191 ),
192 ):
193 messages.append(message)
194 if isinstance(message, AssistantMessage):
195 print(message.content)
196 
197 
198 asyncio.run(main())
199 ```
200</CodeGroup>
201 
202#### Improve prompt caching across users and machines
203 
204By default, two sessions that use the same `claude_code` preset and `append` text still can't share a prompt cache entry when their auto memory locations differ. The preset embeds that location in the system prompt ahead of your `append` text. The location defaults to an absolute path under `~/.claude/projects/` named for the repository's path on disk, so it differs across users, machines, and checkouts.
205 
206CLAUDE.md content and environment details such as the working directory, platform, shell, and OS version don't affect the system prompt cache, because Claude Code delivers them in the conversation, not the system prompt.
207 
208To make the system prompt identical across sessions, set `excludeDynamicSections: true` in TypeScript or `"exclude_dynamic_sections": True` in Python. The per-user context moves into the first user message, leaving only the static preset and your `append` text in the system prompt so identical configurations share a cache entry across users and machines.
209 
210<Note>
211 `excludeDynamicSections` requires `@anthropic-ai/claude-agent-sdk` v0.2.98 or later, or `claude-agent-sdk` v0.1.58 or later for Python. Set it on the preset object form only. The SDK ignores it when you pass a custom prompt instead of the preset; to keep a custom prompt's instructions cached in the TypeScript SDK, see [Cache the static part of a custom prompt](#cache-the-static-part-of-a-custom-prompt).
212</Note>
213 
214The following example pairs a shared `append` block with `excludeDynamicSections` so a fleet of agents can reuse the same cached system prompt:
215 
216<CodeGroup>
217 ```typescript TypeScript theme={null}
218 import { query } from "@anthropic-ai/claude-agent-sdk";
219 
220 for await (const message of query({
221 prompt: "Triage the open issues in this repo",
222 options: {
223 systemPrompt: {
224 type: "preset",
225 preset: "claude_code",
226 append: "You operate Acme's internal triage workflow. Label issues by component and severity.",
227 excludeDynamicSections: true
228 }
229 }
230 })) {
231 // ...
232 }
233 ```
234 
235 ```python Python theme={null}
236 import asyncio
237 
238 from claude_agent_sdk import query, ClaudeAgentOptions
239 
240 
241 async def main():
242 async for message in query(
243 prompt="Triage the open issues in this repo",
244 options=ClaudeAgentOptions(
245 system_prompt={
246 "type": "preset",
247 "preset": "claude_code",
248 "append": "You operate Acme's internal triage workflow. Label issues by component and severity.",
249 "exclude_dynamic_sections": True,
250 },
251 ),
252 ):
253 ...
254 
255 
256 asyncio.run(main())
257 ```
258</CodeGroup>
225})) {
226 // ...
227}
228```
229 
230```python Python theme={null}
231import asyncio
232 
233from claude_agent_sdk import query, ClaudeAgentOptions
234 
235 
236async def main():
237 async for message in query(
238 prompt="Triage the open issues in this repo",
239 options=ClaudeAgentOptions(
240 system_prompt={
241 "type": "preset",
242 "preset": "claude_code",
243 "append": "You operate Acme's internal triage workflow. Label issues by component and severity.",
244 "exclude_dynamic_sections": True,
245 },
246 ),
247 ):
248 ...
249 
250 
251asyncio.run(main())
252```
259253 
260254**Tradeoffs:** the text that moves out of the system prompt still reaches Claude, but in a user message. That text is at least the auto memory directory's location, and often the whole auto memory section. Instructions in a user message carry marginally less weight than the same text in the system prompt, so Claude may follow its auto memory guidance less consistently. Enable this option when cross-session cache reuse matters more than that.
261255 
from line 259
265259 
266260You can provide a custom string as `systemPrompt` to replace the default entirely with your own instructions.
267261 
268<CodeGroup>
269 ```typescript TypeScript theme={null}
270 import { query } from "@anthropic-ai/claude-agent-sdk";
271 
272 const customPrompt = `You are a Python coding specialist.
273 Follow these guidelines:
274 - Write clean, well-documented code
275 - Use type hints for all functions
276 - Include comprehensive docstrings
277 - Prefer functional programming patterns when appropriate
278 - Always explain your code choices`;
279 
280 const messages = [];
281 
282 for await (const message of query({
283 prompt: "Create a data processing pipeline",
284 options: {
285 systemPrompt: customPrompt
286 }
287 })) {
288 messages.push(message);
289 if (message.type === "assistant") {
290 console.log(message.message.content);
291 }
292 }
293 ```
294 
295 ```python Python theme={null}
296 import asyncio
297 
298 from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage
299 
300 custom_prompt = """You are a Python coding specialist.
301 Follow these guidelines:
302 - Write clean, well-documented code
303 - Use type hints for all functions
304 - Include comprehensive docstrings
305 - Prefer functional programming patterns when appropriate
306 - Always explain your code choices"""
307 
308 messages = []
309 
310 
311 async def main():
312 async for message in query(
313 prompt="Create a data processing pipeline",
314 options=ClaudeAgentOptions(system_prompt=custom_prompt),
315 ):
316 messages.append(message)
317 if isinstance(message, AssistantMessage):
318 print(message.content)
319 
320 
321 asyncio.run(main())
322 ```
323</CodeGroup>
262```typescript TypeScript theme={null}
263import { query } from "@anthropic-ai/claude-agent-sdk";
264 
265const customPrompt = `You are a Python coding specialist.
266Follow these guidelines:
267- Write clean, well-documented code
268- Use type hints for all functions
269- Include comprehensive docstrings
270- Prefer functional programming patterns when appropriate
271- Always explain your code choices`;
272 
273const messages = [];
274 
275for await (const message of query({
276 prompt: "Create a data processing pipeline",
277 options: {
278 systemPrompt: customPrompt
279 }
280})) {
281 messages.push(message);
282 if (message.type === "assistant") {
283 console.log(message.message.content);
284 }
285}
286```
287 
288```python Python theme={null}
289import asyncio
290 
291from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage
292 
293custom_prompt = """You are a Python coding specialist.
294Follow these guidelines:
295- Write clean, well-documented code
296- Use type hints for all functions
297- Include comprehensive docstrings
298- Prefer functional programming patterns when appropriate
299- Always explain your code choices"""
300 
301messages = []
302 
303 
304async def main():
305 async for message in query(
306 prompt="Create a data processing pipeline",
307 options=ClaudeAgentOptions(system_prompt=custom_prompt),
308 ):
309 messages.append(message)
310 if isinstance(message, AssistantMessage):
311 print(message.content)
312 
313 
314asyncio.run(main())
315```
324316 
325317In Python, load a large custom prompt from a file with `system_prompt={"type": "file", "path": "..."}` instead of passing it as a string. The Python SDK passes a string prompt as one command-line argument to the CLI subprocess, so a prompt that exceeds the OS argument-length limit fails at process spawn before any API request is sent. On Linux the error is `Argument list too long`. See [`SystemPromptFile`](/docs/en/agent-sdk/python#systempromptfile) for the platform thresholds and the Windows behavior.
326318 
from line 320
328320 
329321In the TypeScript SDK, you can pass a custom prompt as an array of strings instead of one string, with the `SYSTEM_PROMPT_DYNAMIC_BOUNDARY` marker between the static part and the rest. Use this when your prompt combines instructions that are the same on every request with context that changes per request, such as the customer or ticket the agent is handling. When you pass both parts as one string, a change to the per-request part changes the whole system prompt, so the static instructions miss the cache too. The array form isn't available in the Python SDK; [`ClaudeAgentOptions`](/docs/en/agent-sdk/python#claudeagentoptions) lists the forms `system_prompt` accepts.
330322 
331<Note>
332 Claude Code splits the prompt only when it calls the Claude API directly or runs on [Claude Platform on AWS](/docs/en/claude-platform-on-aws). In every other configuration, such as Amazon Bedrock, Google Cloud's Agent Platform, Microsoft Foundry, or an [LLM gateway](/docs/en/llm-gateway-connect), it sends the whole prompt as one block, the same as passing one string. The same happens whenever you set [`CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1`](/docs/en/llm-gateway-protocol#disable-pre-release-capabilities).
333</Note>
323> [!NOTE]
324>
325> Claude Code splits the prompt only when it calls the Claude API directly or runs on [Claude Platform on AWS](/docs/en/claude-platform-on-aws). In every other configuration, such as Amazon Bedrock, Google Cloud's Agent Platform, Microsoft Foundry, or an [LLM gateway](/docs/en/llm-gateway-connect), it sends the whole prompt as one block, the same as passing one string. The same happens whenever you set [`CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1`](/docs/en/llm-gateway-protocol#disable-pre-release-capabilities).
334326 
335327To split the prompt, import `SYSTEM_PROMPT_DYNAMIC_BOUNDARY` from `@anthropic-ai/claude-agent-sdk` and pass it as its own array element between the two parts. The SDK sends the strings before the marker as one text block and the strings after it as a second block, each with its own cache breakpoint. In the example below, a support agent loads its triage instructions from a file and receives details about one ticket on each request, so the instructions stay cached while the ticket details change:
336328 
from line 425
433425 
434426The following example is for an agent that carries its own commit rules in `append`. It sets both `attribution` keys to empty strings to remove the trailer and footer, and turns off `includeGitInstructions` so Claude Code's own commit workflow instructions don't compete with yours:
435427 
436<CodeGroup>
437 ```typescript TypeScript theme={null}
438 import { query } from "@anthropic-ai/claude-agent-sdk";
439 
440 for await (const message of query({
441 prompt: "Commit the staged changes for ticket PROJ-142",
442 options: {
443 systemPrompt: {
444 type: "preset",
445 preset: "claude_code",
446 append: "Write commit messages as: <ticket id>: <summary>. Add no trailers."
447 },
448 settings: {
449 includeGitInstructions: false,
450 attribution: { commit: "", pr: "" }
451 },
452 allowedTools: ["Bash(git *)"]
453 }
454 })) {
455 if (message.type === "result") console.log(message.subtype);
456 }
457 ```
458 
459 ```python Python theme={null}
460 import asyncio
461 from claude_agent_sdk import query, ClaudeAgentOptions
462 
463 
464 async def main():
465 async for message in query(
466 prompt="Commit the staged changes for ticket PROJ-142",
467 options=ClaudeAgentOptions(
468 system_prompt={
469 "type": "preset",
470 "preset": "claude_code",
471 "append": "Write commit messages as: <ticket id>: <summary>. Add no trailers.",
472 },
473 settings='{"includeGitInstructions": false, "attribution": {"commit": "", "pr": ""}}',
474 allowed_tools=["Bash(git *)"],
475 ),
476 ):
477 print(message)
478 
479 
480 asyncio.run(main())
481 ```
482</CodeGroup>
428```typescript TypeScript theme={null}
429import { query } from "@anthropic-ai/claude-agent-sdk";
430 
431for await (const message of query({
432 prompt: "Commit the staged changes for ticket PROJ-142",
433 options: {
434 systemPrompt: {
435 type: "preset",
436 preset: "claude_code",
437 append: "Write commit messages as: <ticket id>: <summary>. Add no trailers."
438 },
439 settings: {
440 includeGitInstructions: false,
441 attribution: { commit: "", pr: "" }
442 },
443 allowedTools: ["Bash(git *)"]
444 }
445})) {
446 if (message.type === "result") console.log(message.subtype);
447}
448```
449 
450```python Python theme={null}
451import asyncio
452from claude_agent_sdk import query, ClaudeAgentOptions
453 
454 
455async def main():
456 async for message in query(
457 prompt="Commit the staged changes for ticket PROJ-142",
458 options=ClaudeAgentOptions(
459 system_prompt={
460 "type": "preset",
461 "preset": "claude_code",
462 "append": "Write commit messages as: <ticket id>: <summary>. Add no trailers.",
463 },
464 settings='{"includeGitInstructions": false, "attribution": {"commit": "", "pr": ""}}',
465 allowed_tools=["Bash(git *)"],
466 ),
467 ):
468 print(message)
469 
470 
471asyncio.run(main())
472```
483473 
484474To confirm the change, run the example in a repository with staged changes and check the new commit with `git log -1`. The message ends without a `Co-Authored-By` trailer.
485475 
from line 507
517507 
518508The example below assumes a Code Reviewer output style is already active. The `append` block layers session-specific focus areas on top of the persona, so a single review session can prioritize OAuth and token storage without changing the saved output style:
519509 
520<CodeGroup>
521 ```typescript TypeScript theme={null}
522 import { query } from "@anthropic-ai/claude-agent-sdk";
523 
524 // Assuming "Code Reviewer" output style is active (via /config or settings)
525 // Add session-specific focus areas
526 const messages = [];
527 
528 for await (const message of query({
529 prompt: "Review this authentication module",
530 options: {
531 systemPrompt: {
532 type: "preset",
533 preset: "claude_code",
534 append: `
535 For this review, prioritize:
536 - OAuth 2.0 compliance
537 - Token storage security
538 - Session management
539 `
540 }
510```typescript TypeScript theme={null}
511import { query } from "@anthropic-ai/claude-agent-sdk";
512 
513// Assuming "Code Reviewer" output style is active (via /config or settings)
514// Add session-specific focus areas
515const messages = [];
516 
517for await (const message of query({
518 prompt: "Review this authentication module",
519 options: {
520 systemPrompt: {
521 type: "preset",
522 preset: "claude_code",
523 append: `
524 For this review, prioritize:
525 - OAuth 2.0 compliance
526 - Token storage security
527 - Session management
528 `
541529 }
542 })) {
543 messages.push(message);
544 }
545 ```
546 
547 ```python Python theme={null}
548 import asyncio
549 
550 from claude_agent_sdk import query, ClaudeAgentOptions
551 
552 # Assuming "Code Reviewer" output style is active (via /config or settings)
553 # Add session-specific focus areas
554 messages = []
555 
556 
557 async def main():
558 async for message in query(
559 prompt="Review this authentication module",
560 options=ClaudeAgentOptions(
561 system_prompt={
562 "type": "preset",
563 "preset": "claude_code",
564 "append": """
565 For this review, prioritize:
566 - OAuth 2.0 compliance
567 - Token storage security
568 - Session management
569 """,
570 }
571 ),
572 ):
573 messages.append(message)
574 
575 
576 asyncio.run(main())
577 ```
578</CodeGroup>
530 }
531})) {
532 messages.push(message);
533}
534```
535 
536```python Python theme={null}
537import asyncio
538 
539from claude_agent_sdk import query, ClaudeAgentOptions
540 
541# Assuming "Code Reviewer" output style is active (via /config or settings)
542# Add session-specific focus areas
543messages = []
544 
545 
546async def main():
547 async for message in query(
548 prompt="Review this authentication module",
549 options=ClaudeAgentOptions(
550 system_prompt={
551 "type": "preset",
552 "preset": "claude_code",
553 "append": """
554 For this review, prioritize:
555 - OAuth 2.0 compliance
556 - Token storage security
557 - Session management
558 """,
559 }
560 ),
561 ):
562 messages.append(message)
563 
564 
565asyncio.run(main())
566```
579567 
580568## See also
581569 
582570 
Feedback