System Prompts in the Claude Agent SDK

Three ways to write system prompts: plain string, the Claude Code preset, and the preset with a custom append. How the invisible base prompt works and what your prompt actually controls.

4 min read
system prompt agent SDK claude_code preset agent instructions SDK systemPrompt option operator agent prompt

What system prompts actually do in the SDK

Every Agent SDK deployment has an invisible system prompt running underneath. It contains all the tool definitions, the agent's operational instructions, and the behavioral guardrails that Anthropic sets up. You never see this layer. Anthropic manages it, and it updates automatically when the SDK ships new features.

Your system prompt stacks on top of that invisible layer. You add the instructions specific to your use case. The tool definitions and core behavior are already handled.

This is a meaningful difference from calling the raw Anthropic API, where you define everything. With the SDK, you only need to specify what makes your agent unique.

Three ways to write a system prompt

1. Pass a string

The most common approach. Write your instructions, pass them as a string:

for await (const message of query(messages(), {
  model: "claude-sonnet-4-5",
  systemPrompt: `You are a research assistant.
Present multiple perspectives on every topic.
Use clear headers and bullet points.
Cite specific data points when possible.`,
  permissionMode: "bypassPermissions",
  dangerouslyAllowBypassPermissions: true,
})) {
  // handle messages
}

Your prompt gets injected alongside the invisible layer. The agent follows both.

You can also store the system prompt in a separate file and import it:

import { readFileSync } from "fs";
const systemPrompt = readFileSync("system-prompt.md", "utf-8");

Useful when your prompt is long or when you want version control over it separately from your agent code.

2. Use the Claude Code preset

Instead of writing a system prompt from scratch for coding-focused agents, you can reuse the same prompt Anthropic uses for Claude Code:

for await (const message of query(messages(), {
  model: "claude-sonnet-4-5",
  systemPrompt: {
    type: "preset",
    preset: "claude_code",
  },
  permissionMode: "bypassPermissions",
  dangerouslyAllowBypassPermissions: true,
})) {
  // handle messages
}

The full Claude Code prompt is private — Anthropic does not expose the text. But it is the same one that powers the Claude Code product, which means it is optimized for file operations, code reasoning, and agentic software tasks.

3. Use the preset with a custom append

Combine both: use the Claude Code base and add your own instructions on top:

for await (const message of query(messages(), {
  model: "claude-sonnet-4-5",
  systemPrompt: {
    type: "preset",
    preset: "claude_code",
    append: "You are working inside a fractional consulting context. Reference client deliverables and engagement timelines in your responses.",
  },
  permissionMode: "bypassPermissions",
  dangerouslyAllowBypassPermissions: true,
})) {
  // handle messages
}

The append text gets added to the end of the Claude Code preset.

> When to use the preset: If you are building a coding agent or a file-manipulation agent, the preset saves you from having to write all the tool-use instructions yourself. If you are building something that has nothing to do with coding — a client briefing agent, a research tool, a Slack assistant — write your own string prompt. The Claude Code preset has behaviors optimized for code work that will feel out of place in other contexts.

Writing effective system prompts for operator agents

A few patterns that hold up across different operator use cases:

Define the role clearly. "You are a research assistant" is a starting point. "You are a research assistant helping fractional leaders prepare for client board meetings" is better. The context shapes how the agent prioritizes and frames its responses.

Set output format expectations. If you need markdown, say so. If you need bullet points rather than paragraphs, specify it. If you are deploying to Slack, tell the agent to use Slack markdown (bold with asterisks, code with backticks) rather than standard markdown.

Define what the agent should not do. Negative instructions prevent the agent from going off-course. "Do not make recommendations outside your available data" or "Do not write code unless explicitly asked" eliminates a class of outputs that would require follow-up correction.

Keep it focused. A system prompt that tries to do everything creates an agent that does nothing well. One specific role, one output format, two or three behavioral constraints. That is usually enough to get a reliable agent.

---

Author: FractionalSkill

Keep Going

Ready to Start Building?

Pick the next step that matches where you are right now.

Tutorial
Claude Code Basics

Start with the terminal basics. A hands-on, step-by-step guide to your first 10 minutes with Claude Code.

Start the Tutorial
Guide
AI-Powered Workflows

Automate your client work. Learn how to connect AI tools into workflows that handle repetitive tasks for you.

Read the Guide
Community
Join the Community

Connect with other fractional leaders building with AI. Share workflows, get feedback, and learn from operators who are ahead of you.

Apply to Join