Skip to content
Back to skills

Claude Sdk System Prompt

ASecurity

System prompts in the Claude Agent SDK — string vs file vs preset, the claude_code preset and its append field, dynamic prompts via per-turn rebuilding, and how setting_sources composes user/project/local instructions. Read when designing the agent's voice and operating principles, when migrating an existing prompt into the SDK shape, or when choosing between a static and a dynamic prompt.

  • 2 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added October 2, 2026
ai-agentspythongosqlrailsgit

Works with

  • claude code
  • cli

Security analysis

A100/100

Scanned October 2, 2026

npx -y skills add Folken2/nuvel --skill claude-sdk-system-prompt --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Claude Sdk System Prompt?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Claude Sdk System Prompt
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/folken2-claude-sdk-system-prompt/badge)](https://www.skillsdirectory.com/skills/folken2-claude-sdk-system-prompt)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: claude-sdk-system-prompt
description: System prompts in the Claude Agent SDK — string vs file vs preset, the claude_code preset and its append field, dynamic prompts via per-turn rebuilding, and how setting_sources composes user/project/local instructions. Read when designing the agent's voice and operating principles, when migrating an existing prompt into the SDK shape, or when choosing between a static and a dynamic prompt.
---

# System prompts in the Claude Agent SDK

The SDK accepts the `system_prompt` field in three different shapes. Pick by use case, not by what looks shortest:

| Shape | Use when | Example |
|-------|----------|---------|
| **String** | The prompt is short and stable | `system_prompt="You are a helpful assistant."` |
| **`{"type": "file", "path": "..."}`** | The prompt is long and edited often | `system_prompt={"type": "file", "path": "prompt.md"}` |
| **`{"type": "preset", "preset": "claude_code", "append": "..."}`** | You want Claude Code's tool-using personality plus your domain instructions | (below) |

## File mode — the right default for production

Inline string prompts grow until they're unmaintainable. Move to a file as soon as the prompt is more than 5 lines:

```python
system_prompt={"type": "file", "path": "my_agent/prompt/system_prompt.md"}
```

Benefits:
- Edit the prompt without touching code
- `git diff` shows prompt changes clearly
- Reviewers can read it without scrolling through Python
- Markdown rendering in editors makes structure visible

The SDK reads the file every time the option is constructed, so you can edit it and restart the process. Hot-reloading mid-session requires rebuilding `ClaudeAgentOptions` and starting a fresh `ClaudeSDKClient`.

## The `claude_code` preset

```python
system_prompt={
    "type": "preset",
    "preset": "claude_code",
    "append": "You're a SQL specialist. Prefer CTEs over subqueries. Always validate schema before writing migrations.",
}
```

This gives Claude:
- The `claude_code` system prompt (proactive, tool-using, error-handling personality, autonomy norms)
- Your `append` text added at the end

Use this when your agent should *act like* Claude Code — multi-step planning, tool use without permission-asking, terse status updates. Don't use it when you want a different personality (a customer-service voice, a teaching voice, a strict review voice). The base personality is opinionated and bleeds through.

## Dynamic prompts — rebuild per turn

The SDK doesn't support "dynamic system prompt at runtime" as a first-class feature (no `InstructionProvider` like ADK). The workaround is to rebuild `ClaudeAgentOptions` and start a fresh client per turn:

```python
async def run_turn(prompt: str, user_id: str):
    options = ClaudeAgentOptions(
        system_prompt=build_dynamic_prompt(user_id),
        # ... other options ...
    )
    async with ClaudeSDKClient(options=options) as client:
        await client.query(prompt)
        async for msg in client.receive_response():
            yield msg
```

You lose session continuity (each turn is a fresh session) — that's the cost of dynamic prompts. For multi-turn dynamic agents, use the SDK's `session_id` + `resume` to thread the conversation across these per-turn rebuilds.

A common middle ground: keep the base system prompt static and inject per-turn context via a `UserPromptSubmit` hook (see `claude-sdk-hooks`). Faster, simpler, no session juggling.

## `setting_sources` and how skills layer in

```python
options = ClaudeAgentOptions(
    system_prompt=...,
    setting_sources=["user", "project", "local"],
)
```

This loads `CLAUDE.md` files and `.claude/skills/` directories from those layers — exactly like Claude Code does. `user` means `~/.claude/`, `project` means the project root's `.claude/`, `local` means the current directory.

The system prompt you set via `system_prompt` is composed *with* whatever Claude finds in those sources. So you don't have to embed your skills' content in the system prompt — drop SKILL.md files into `.claude/skills/<name>/` and they're discovered.

For nuvel-scaffolded SDK agents, `setting_sources=["project"]` is the sensible default — it picks up the project's `.claude/` without leaking the user's home-directory settings into a server deployment.

## Writing a good system prompt

Three sections, in order:

1. **Identity** — who the agent is, what it's for, who's talking to it.
2. **Operating principles** — concrete behaviors. "Use tools to take action, don't ask permission." "Cite tool outputs." "Surface ambiguity in one sentence; don't block."
3. **Guardrails** — things to never do, in declarative form. "Never delete user data without explicit confirmation."

Avoid the three patterns that hurt prompts:
- **Long lists of "do this"** — Claude weights the last item. Pick 3-5 principles, ordered by importance.
- **Telling Claude its capabilities** ("you can use tools, you can read files") — the SDK already tells it. Redundant text dilutes the prompt.
- **Personality without purpose** ("you are a friendly assistant who loves to help") — describes vibes, not actions. Replace with verbs.

## Common mistakes

- **Inlining a 200-line prompt as a Python string.** Use file mode.
- **Using `claude_code` preset for non-Claude-Code agents.** The personality is too strong; users feel like they're talking to a coding agent.
- **Dynamic prompts via Python f-strings rebuilt every turn.** Works but breaks session continuity. Use `UserPromptSubmit` hook injection for per-turn context, or `session_id`/`resume` to bridge.
- **Hardcoding tool names in the prompt.** Claude already sees the tool list; mentioning specific tools in the prompt creates drift when you add/remove them.

## Quick reference

```python
# Static, file-based (recommended)
system_prompt={"type": "file", "path": "prompt/system_prompt.md"}

# Claude Code personality + your additions
system_prompt={"type": "preset", "preset": "claude_code", "append": "..."}

# With user/project/local skills auto-discovered
ClaudeAgentOptions(
    system_prompt={"type": "file", "path": "..."},
    setting_sources=["project"],
)
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.