System Prompts & Planning
Now that you have a working agent from Module 1, it’s time to learn how to control how it thinks and plans. Deep Agents gives you powerful tools to shape your agent’s behavior through system prompts and planning strategies.
Exercise 1: Custom System Prompts
Let’s create an agent with a specific persona — a senior Python code reviewer.
-
Create the review agent script:
-
Run
-
Code Preview
cat > review_agent.py << 'EOF' import os from deepagents import create_deep_agent from utils import agent_response MODEL = os.environ.get("DEEPAGENTS_MODEL", "anthropic:claude-sonnet-4-6") agent = create_deep_agent( model=MODEL, system_prompt="""You are a senior Python code reviewer. When reviewing code, always check for: 1. Type safety and proper type hints 2. Error handling 3. Security vulnerabilities 4. Performance considerations Be direct and specific in your feedback.""", ) result = agent.invoke({"messages": [("user", """Review this code: def get_user(id): data = eval(open(f"users/{id}.json").read()) return data """)]}) print(agent_response(result)) EOFimport os from deepagents import create_deep_agent from utils import agent_response MODEL = os.environ.get("DEEPAGENTS_MODEL", "anthropic:claude-sonnet-4-6") agent = create_deep_agent( model=MODEL, system_prompt="""You are a senior Python code reviewer. When reviewing code, always check for: 1. Type safety and proper type hints 2. Error handling 3. Security vulnerabilities 4. Performance considerations Be direct and specific in your feedback.""", ) result = agent.invoke({"messages": [("user", """Review this code: def get_user(id): data = eval(open(f"users/{id}.json").read()) return data """)]}) print(agent_response(result)) -
-
Run the review agent:
uv run review_agent.pySample output (your results may vary)This code has several serious issues: 1. Type safety and proper type hints: Missing type hints for the function parameter and return value. 2. Error handling: No try/except blocks to handle potential file read errors or JSON parsing failures. 3. Security vulnerabilities: CRITICAL - Using eval() on file contents is extremely dangerous. It will execute arbitrary Python code, creating a severe security vulnerability. Use json.load() instead. 4. Performance considerations: The f-string file path construction is vulnerable to path traversal attacks. Recommended fix: def get_user(user_id: str) -> dict: import json from pathlib import Path file_path = Path("users") / f"{user_id}.json" with open(file_path) as f: return json.load(f)
The system_prompt parameter is prepended to BASE_AGENT_PROMPT — the agent still has all its built-in capabilities (tool use, planning, etc.), but now also has your custom instructions. This lets you add domain expertise without losing the core agent behavior.
Exercise 2: The Base Prompt
Let’s explore what BASE_AGENT_PROMPT actually contains.
-
Create a script to inspect the base prompt:
-
Run
-
Code Preview
cat > inspect_prompt.py << 'EOF' from deepagents.graph import BASE_AGENT_PROMPT print(BASE_AGENT_PROMPT[:2000]) print(f"\n... ({len(BASE_AGENT_PROMPT)} total characters)") EOFfrom deepagents.graph import BASE_AGENT_PROMPT print(BASE_AGENT_PROMPT[:2000]) print(f"\n... ({len(BASE_AGENT_PROMPT)} total characters)") -
-
Run the inspection script:
uv run inspect_prompt.pySample output (your results may vary)You are a helpful AI assistant with access to tools. When given a task: 1. Analyze the request carefully 2. Determine which tools you need to use 3. Execute the tools in the correct order 4. Synthesize the results into a helpful response TOOL USAGE GUIDELINES: When using tools, always: - Check that required parameters are present - Validate inputs before making tool calls - Handle errors gracefully - Provide clear feedback about what you're doing BEHAVIORAL GUIDELINES: For complex tasks: - Break down the problem into manageable steps - Use the write_todos tool to plan your approach - Execute systematically and track progress ... ... (8547 total characters)
You’ll see this is no simple "you are a helpful assistant" prompt. It’s a comprehensive instruction manual covering:
-
Detailed tool usage instructions
-
Behavioral guidelines for complex tasks
-
Output formatting expectations
-
Error handling strategies
This is the "detailed system prompt" pillar in action — giving the LLM clear, specific guidance on how to operate as an agent.
You might wonder about the cost of such a large system prompt. Claude Code’s system prompt is reportedly around 16,000 words — a third of a novel! This is viable because Deep Agents includes AnthropicPromptCachingMiddleware in its middleware stack, which caches the system prompt across invocations. You pay the full token cost once, then subsequent calls reuse the cached prompt at a fraction of the cost. Verbose, detailed system prompts are an investment that pays off through caching.
|
Exercise 3: Planning with Todos
For complex multi-step tasks, Deep Agents can plan out the work before executing. Let’s see this in action.
-
Create the planning agent script:
-
Run
-
Code Preview
cat > planning_agent.py << 'EOF' import os from deepagents import create_deep_agent from utils import agent_response MODEL = os.environ.get("DEEPAGENTS_MODEL", "anthropic:claude-sonnet-4-6") agent = create_deep_agent(model=MODEL) result = agent.invoke({"messages": [("user", "Create a Python project structure for a REST API with " "user authentication, database models, and tests. " "Plan out the work first, then create the files." )]}) # Show planning tool calls for msg in result["messages"]: if hasattr(msg, 'tool_calls'): for tc in msg.tool_calls: if tc['name'] == 'write_todos': print("Planning step detected!") print(f"Todos: {tc['args']}") # Show the final response print("\n=== Agent Response ===") print(agent_response(result)) EOFimport os from deepagents import create_deep_agent from utils import agent_response MODEL = os.environ.get("DEEPAGENTS_MODEL", "anthropic:claude-sonnet-4-6") agent = create_deep_agent(model=MODEL) result = agent.invoke({"messages": [("user", "Create a Python project structure for a REST API with " "user authentication, database models, and tests. " "Plan out the work first, then create the files." )]}) # Show planning tool calls for msg in result["messages"]: if hasattr(msg, 'tool_calls'): for tc in msg.tool_calls: if tc['name'] == 'write_todos': print("Planning step detected!") print(f"Todos: {tc['args']}") # Show the final response print("\n=== Agent Response ===") print(agent_response(result)) -
-
Run the planning agent:
uv run planning_agent.pySample output (your results may vary)Planning step detected! Todos: {'todos': [ '[ ] Create project directory structure with src/, tests/, and config folders', '[ ] Create database models (User, Session) in src/models/', '[ ] Create authentication handlers in src/auth/', '[ ] Create REST API endpoints in src/api/', '[ ] Create test files for models and API endpoints', '[ ] Create requirements.txt and basic configuration' ]}
The write_todos tool is provided by TodoListMiddleware — a context engineering strategy. By giving the agent a way to write down a plan, it can break complex tasks into manageable steps and track progress.
Exercise 4: Guiding Planning Behavior
You can use system prompts to influence how the agent plans.
-
Create the guided planning script:
-
Run
-
Code Preview
cat > guided_planning.py << 'EOF' import os from deepagents import create_deep_agent from utils import agent_response MODEL = os.environ.get("DEEPAGENTS_MODEL", "anthropic:claude-sonnet-4-6") agent = create_deep_agent( model=MODEL, system_prompt="""Before starting any task: 1. Always create a todo list with write_todos 2. Break work into steps of no more than 3 files each 3. Complete and check off each step before moving to the next 4. Never skip the planning phase""", ) result = agent.invoke({"messages": [("user", "Create a Python project structure for a REST API with " "user authentication, database models, and tests." )]}) # Show planning tool calls for msg in result["messages"]: if hasattr(msg, 'tool_calls'): for tc in msg.tool_calls: if tc['name'] == 'write_todos': print("Planning step detected!") print(f"Todos: {tc['args']}") # Show the final response print("\n=== Agent Response ===") print(agent_response(result)) EOFimport os from deepagents import create_deep_agent from utils import agent_response MODEL = os.environ.get("DEEPAGENTS_MODEL", "anthropic:claude-sonnet-4-6") agent = create_deep_agent( model=MODEL, system_prompt="""Before starting any task: 1. Always create a todo list with write_todos 2. Break work into steps of no more than 3 files each 3. Complete and check off each step before moving to the next 4. Never skip the planning phase""", ) result = agent.invoke({"messages": [("user", "Create a Python project structure for a REST API with " "user authentication, database models, and tests." )]}) # Show planning tool calls for msg in result["messages"]: if hasattr(msg, 'tool_calls'): for tc in msg.tool_calls: if tc['name'] == 'write_todos': print("Planning step detected!") print(f"Todos: {tc['args']}") # Show the final response print("\n=== Agent Response ===") print(agent_response(result)) -
-
Run the guided planning agent:
uv run guided_planning.pySample output (your results may vary)Planning step detected! Todos: {'todos': [ '[ ] Step 1: Create base project structure (pyproject.toml, README.md, .gitignore)', '[ ] Step 2: Create user and session models (src/models/user.py, src/models/session.py)', '[ ] Step 3: Create authentication module (src/auth/handlers.py, src/auth/middleware.py)', '[ ] Step 4: Create API endpoints (src/api/routes.py, src/api/dependencies.py)', '[ ] Step 5: Create test files (tests/test_models.py, tests/test_auth.py, tests/test_api.py)' ]}
Compare the planning behavior with and without the custom instructions. The system prompt gives you fine-grained control over the agent’s approach.
|
CLI Note: The |
Module Summary
In this module, you accomplished:
-
Created agents with custom personas using
system_prompt -
Explored the comprehensive
BASE_AGENT_PROMPT -
Observed planning behavior with
write_todos -
Guided planning through system prompt instructions
Key takeaways:
-
System prompts are prepended to the base prompt, adding domain expertise
-
The base prompt is a detailed instruction manual, not a simple directive
-
Todo lists are a context engineering strategy for complex tasks
-
System prompts can shape both what the agent does and how it plans
Next up: you’ll explore the filesystem tools and storage backends that make agents truly useful for code and file manipulation.