Files
claude-cookbooks/claude_code_sdk/01_The_chief_of_staff_agent.ipynb
Jiri De Jonghe f26aa5891c Add Claude Code SDK tutorials and examples (#195)
* Add Claude Code SDK tutorials and examples

This PR adds comprehensive tutorials and examples for the Claude Code SDK, including:
- Research agent implementation with web search capabilities
- Chief of Staff agent with multi-agent coordination
- Observability agent with Docker configuration
- Supporting utilities and documentation

The examples demonstrate key SDK features:
- Multi-turn conversations with ClaudeSDKClient
- Custom output styles and slash commands
- Hooks for automated actions and governance
- Script execution via Bash tool
- Multi-agent orchestration patterns

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: rodrigo olivares <rodrigoolivares@anthropic.com>
Co-authored-by: Alex Notov <zh@anthropic.com>
2025-09-12 15:04:34 -07:00

673 lines
27 KiB
Plaintext

{
"cells": [
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from dotenv import load_dotenv\n",
"from utils.agent_visualizer import print_activity, visualize_conversation\n",
"\n",
"from claude_code_sdk import ClaudeCodeOptions, ClaudeSDKClient\n",
"\n",
"load_dotenv()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 01 - The Chief of Staff Agent\n",
"\n",
"#### Introduction\n",
"\n",
"In notebook 00, we built a simple research agent. In this notebook, we'll incrementally introduce key Claude Code SDK features for building comprehensive agents. For each introduced feature, we'll explain:\n",
"- **What**: what the feature is\n",
"- **Why**: what the feature can do and why you would want to use it\n",
"- **How**: a minimal implementation showing how to use it\n",
"\n",
"If you are familiar with Claude Code, you'll notice how the SDK brings feature parity and enables you to leverage all of Claude Code's capabilities in a programmatic headless manner.\n",
"\n",
"#### Scenario\n",
"\n",
"Throughout this notebook, we'll build an **AI Chief of Staff** for a 50-person startup that just raised $10M Series A. The CEO needs data-driven insights to balance aggressive growth with financial sustainability.\n",
"\n",
"Our final Chief of Staff agent will:\n",
"- **Coordinate specialized subagents** for different domains\n",
"- **Aggregate insights** from multiple sources\n",
"- **Provide executive summaries** with actionable recommendations"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Basic Features"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Feature 0: Memory with [CLAUDE.md](https://www.anthropic.com/engineering/claude-code-best-practices)\n",
"\n",
"**What**: `CLAUDE.md` files serve as persistent memory and instructions for your agent. When present in the project directory, Claude Code automatically reads and incorporates this context when you initialize your agent.\n",
"\n",
"**Why**: Instead of repeatedly providing project context, team preferences, or standards in each interaction, you can define them once in `CLAUDE.md`. This ensures consistent behavior and reduces token usage by avoiding redundant explanations.\n",
"\n",
"**How**: \n",
"- Have a `CLAUDE.md` file in the working directory - in our example: `chief_of_staff_agent/CLAUDE.md`\n",
"- Set the `cwd` argument of your ClaudeSDKClient to point to directory of your CLAUDE.md file"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"async with ClaudeSDKClient(\n",
" options=ClaudeCodeOptions(\n",
" model=\"claude-sonnet-4-20250514\",\n",
" cwd=\"chief_of_staff_agent\", # Points to subdirectory with our CLAUDE.md\n",
" )\n",
") as agent:\n",
" await agent.query(\"What's our current runway?\")\n",
" async for msg in agent.receive_response():\n",
" if hasattr(msg, \"result\"):\n",
" print(msg.result)\n",
"# The agent should know from the CLAUDE.md file: $500K burn, 20 months runway"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Feature 1: The Bash tool for Python Script Execution\n",
"\n",
"**What**: The Bash tool allows your agent to (among other things) run Python scripts directly, enabling access to procedural knowledge, complex computations, data analysis and other integrations that go beyond the agent's native capabilities.\n",
"\n",
"**Why**: Our Chief of Staff might need to process data files, run financial models or generate visualizations based on this data. These are all good scenarios for using the Bash tool.\n",
"\n",
"**How**: Have your Python scripts set-up in a place where your agent can reach them and add some context on what they are and how they can be called. If the scripts are meant for your chief of staff agent, add this context to its CLAUDE.md file and if they are meant for one your subagents, add said context to their MD files (more details on this later). For this tutorial, we added five toy examples to `chief_of_staff_agent/scripts`:\n",
"1. `hiring_impact.py`: Calculates how new engineering hires affect burn rate, runway, and cash position. Essential for the `financial-analyst` subagent to model hiring scenarios against the $500K monthly burn and 20-month runway.\n",
"2. `talent_scorer.py`: Scores candidates on technical skills, experience, culture fit, and salary expectations using weighted criteria. Core tool for the `recruiter` subagent to rank engineering candidates against TechStart's $180-220K senior engineer benchmarks.\n",
"3. `simple_calculation.py`: Performs quick financial calculations for runway, burn rate, and quarterly metrics. Utility script for chief of staff to get instant metrics without complex modeling.\n",
"4. `financial_forecast.py`: Models ARR growth scenarios (base/optimistic/pessimistic) given the current $2.4M ARR growing at 15% MoM.Critical for `financial-analyst` to project Series B readiness and validate the $30M fundraising target.\n",
"5. `decision_matrix.py`: Creates weighted decision matrices for strategic choices like the SmartDev acquisition or office expansion. Helps chief of staff systematically evaluate complex decisions with multiple stakeholders and criteria."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"async with ClaudeSDKClient(\n",
" options=ClaudeCodeOptions(\n",
" model=\"claude-sonnet-4-20250514\",\n",
" allowed_tools=[\"Bash\", \"Read\"],\n",
" cwd=\"chief_of_staff_agent\", # Points to subdirectory where our agent is defined\n",
" )\n",
") as agent:\n",
" await agent.query(\n",
" \"Use your simple calculation script with a total runway of 2904829 and a monthly burn of 121938.\"\n",
" )\n",
" async for msg in agent.receive_response():\n",
" print_activity(msg)\n",
" if hasattr(msg, \"result\"):\n",
" print(\"\\n\")\n",
" print(msg.result)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Feature 2: Output Styles\n",
"\n",
"**What**: Output styles allow you to use different output styles for different audiences. Each style is defined in a markdown file.\n",
"\n",
"**Why**: Your agent might be used by people of different levels of expertise or they might have different priorities. Your output style can help differentiate between these segments without having to create a separate agent.\n",
"\n",
"**How**:\n",
"- Configure a markdown file per style in `chief_of_staff_agent/.claude/output-styles/`. For example, check out the Executive Ouput style in `.claude/output-styles/executive.md`. Output styles are defined with a simple frontmatter including two fields: name and description. Note: Make sure the name in the frontmatter matches exactly the file's name (case sensitive)\n",
"\n",
"> **IMPORTANT**: Output styles modify the system prompt that Claude Code has underneath, leaving out the parts focused on software engineering and giving you more control for your specific use case beyond software engineering work."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"🤖 Thinking...\n",
"🤖 Thinking...\n"
]
}
],
"source": [
"messages_executive = []\n",
"async with ClaudeSDKClient(\n",
" options=ClaudeCodeOptions(\n",
" model=\"claude-sonnet-4-20250514\",\n",
" cwd=\"chief_of_staff_agent\",\n",
" settings='{\"outputStyle\": \"executive\"}',\n",
" )\n",
") as agent:\n",
" await agent.query(\"Tell me in two sentences about your writing output style.\")\n",
" async for msg in agent.receive_response():\n",
" print_activity(msg)\n",
" messages_executive.append(msg)\n",
"\n",
"messages_technical = []\n",
"async with ClaudeSDKClient(\n",
" options=ClaudeCodeOptions(\n",
" model=\"claude-sonnet-4-20250514\",\n",
" cwd=\"chief_of_staff_agent\",\n",
" settings='{\"outputStyle\": \"technical\"}',\n",
" )\n",
") as agent:\n",
" await agent.query(\"Tell me in two sentences about your writing output style.\")\n",
" async for msg in agent.receive_response():\n",
" print_activity(msg)\n",
" messages_technical.append(msg)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(messages_executive[-1].result)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(messages_technical[-1].result)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Feature 3: Plan Mode - Strategic Planning Without Execution\n",
"\n",
"**What**: Plan mode instructs the agent to create a detailed execution plan without performing any actions. The agent analyzes requirements, proposes solutions, and outlines steps, but doesn't modify files, execute commands, or make changes.\n",
"\n",
"**Why**: Complex tasks benefit from upfront planning to reduce errors, enable review and improve coordination. After the planning phase, the agent will have a red thread to follow throughout its execution.\n",
"\n",
"**How**: Just set `permission_mode=\"plan\"`\n",
"\n",
"> Note: this feature shines in Claude Code but still needs to be fully adapted for headless applications with the SDK. Namely, the agent will try calling its `ExitPlanMode()` tool, which is only relevant in the interactive mode. In this case, you can send up a follow-up query with `continue_conversation=True` for the agent to execute its plan in context."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"🤖 Thinking...\n",
"🤖 Using: Read()\n",
"✓ Tool completed\n",
"🤖 Using: Glob()\n",
"✓ Tool completed\n",
"🤖 Using: Read()\n",
"✓ Tool completed\n",
"🤖 Using: Glob()\n",
"✓ Tool completed\n",
"🤖 Using: Read()\n",
"✓ Tool completed\n",
"🤖 Using: Read()\n",
"✓ Tool completed\n",
"🤖 Using: Glob()\n",
"✓ Tool completed\n",
"🤖 Thinking...\n",
"🤖 Using: ExitPlanMode()\n",
"✓ Tool completed\n"
]
}
],
"source": [
"messages = []\n",
"async with (\n",
" ClaudeSDKClient(\n",
" options=ClaudeCodeOptions(\n",
" model=\"claude-opus-4-1-20250805\", # We're using Opus for this as Opus truly shines when it comes to planning!\n",
" permission_mode=\"plan\",\n",
" )\n",
" ) as agent\n",
"):\n",
" await agent.query(\"Restructure our engineering team for AI focus.\")\n",
" async for msg in agent.receive_response():\n",
" print_activity(msg)\n",
" messages.append(msg)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
]
}
],
"source": [
"print(messages[-1].result)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As mentioned above, the agent will stop after creating its plan, if you want it to execute on its plan, you need to send a new query with `continue_conversation=True` and removing `permission_mode=\"plan\"` "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Advanced Features"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Feature 4: Custom Slash Commands\n",
"\n",
"> Note: slash commands are syntactic sugar for users, not new agent capabilities\n",
"\n",
"**What**: Custom slash commands are predefined prompt templates that users can trigger with shorthand syntax (e.g., `/budget-impact`). These are **user-facing shortcuts**, not agent capabilities. Think of them as keyboard shortcuts that expand into full, well-crafted prompts.\n",
"\n",
"**Why**: Your Chief of Staff will handle recurring executive questions. Instead of users typing complex prompts repeatedly, they can use already vetted prompts. This improves consistency and standardization.\n",
"\n",
"**How**:\n",
"- Define a markdown file in `.claude/commands/`. For example, we defined one in `.claude/commands/slash-command-test.md`. Notice how the command is defined: frontmatter with two fields (name, description) and the expanded prompt with an option to include arguments passed on in the query.\n",
"- You can add parameters to your prompt using `{{args}}`\n",
"- The user uses the slash command in their prompt"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"🤖 Thinking...\n"
]
}
],
"source": [
"# User types: \"/slash-command-test this is a test\"\n",
"# -> behind the scenes EXPANDS to the prompt in .claude/commands/slash-command-test.md\n",
"# In this case the expanded prompt says to simply reverse the sentence word wise\n",
"\n",
"messages = []\n",
"async with ClaudeSDKClient(\n",
" options=ClaudeCodeOptions(model=\"claude-sonnet-4-20250514\", cwd=\"chief_of_staff_agent\")\n",
") as agent:\n",
" await agent.query(\"/slash-command-test this is a test\")\n",
" async for msg in agent.receive_response():\n",
" print_activity(msg)\n",
" messages.append(msg)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"test a is this\n"
]
}
],
"source": [
"print(messages[-1].result)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Feature 5: Hooks - Automated Deterministic Actions\n",
"\n",
"**What**: Hooks are Python scripts that you can set to execute automatically, among other events, before (pre) or after (post) specific tool calls. Hooks run **deterministically**, making them perfect for validation and audit trails.\n",
"\n",
"**Why**: Imagine scenarios where you want to make sure that your agent has some guardrails (e.g., prevent dangerous operations) or when you want to have an audit trail. Hooks are ideal in combination with agents to allow them enough freedom to achieve their task, while still making sure that the agents behave in a safe way.\n",
"\n",
"**How**:\n",
"- Define hook scripts in `.claude/hooks/` -> _what_ is the behaviour that should be executed when a hook is triggered\n",
"- Define hook configuration in `.claude/settings.local.json` -> _when_ should a hook be triggered\n",
"- In this case, our hooks are configured to watch specific tool calls (WebSearch, Write, Edit, etc.)\n",
"- When those tools are called, the hook script either runs first (pre tool use hook) or after (post tool use hook)\n",
"\n",
"**Example: Report Tracking for Compliance**\n",
"\n",
"A hook to log Write/Edit operations on financial reports for audit and compliance purposes.\n",
"The hook is defined in `chief_of_staff_agent/.claude/hooks/report-tracker.py` and the logic that enforces it is in `chief_of_staff/.claude/settings.local.json`:\n",
"\n",
"\n",
"```json\n",
" \"hooks\": {\n",
" \"PostToolUse\": [\n",
" {\n",
" \"matcher\": \"Write|Edit\",\n",
" \"hooks\": [\n",
" {\n",
" \"type\": \"command\",\n",
" \"command\": \"$CLAUDE_PROJECT_DIR/.claude/hooks/report-tracker.py\"\n",
" }\n",
" ]\n",
" }\n",
" ]\n",
" }\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"🤖 Thinking...\n",
"🤖 Using: TodoWrite()\n",
"✓ Tool completed\n",
"🤖 Thinking...\n",
"🤖 Using: TodoWrite()\n",
"✓ Tool completed\n",
"🤖 Using: Bash()\n",
"✓ Tool completed\n",
"🤖 Thinking...\n",
"🤖 Using: TodoWrite()\n",
"✓ Tool completed\n",
"🤖 Using: Bash()\n",
"✓ Tool completed\n",
"🤖 Thinking...\n",
"🤖 Using: TodoWrite()\n",
"✓ Tool completed\n",
"🤖 Using: Write()\n",
"✓ Tool completed\n",
"🤖 Using: TodoWrite()\n",
"✓ Tool completed\n",
"🤖 Thinking...\n"
]
}
],
"source": [
"messages = []\n",
"async with ClaudeSDKClient(\n",
" options=ClaudeCodeOptions(\n",
" model=\"claude-sonnet-4-20250514\",\n",
" cwd=\"chief_of_staff_agent\",\n",
" allowed_tools=[\"Bash\", \"Write\", \"Edit\", \"MultiEdit\"],\n",
" )\n",
") as agent:\n",
" await agent.query(\n",
" \"Create a quick Q2 financial forecast report with our current burn rate and runway projections. Save it to our /output_reports folder.\"\n",
" )\n",
" async for msg in agent.receive_response():\n",
" print_activity(msg)\n",
" messages.append(msg)\n",
"\n",
"# The hook will track this in audit/report_history.json"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you now navigate to `./chief_of_staff_agent/audit/report_history.json`, you will find that it has logged that the agent has created and/or made changes to your report. The generated report itself you can find at `./chief_of_staff_agent/output_reports/`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Feature 6: Subagents via Task Tool\n",
"\n",
"**What**: The Task tool enables your agent to delegate specialized work to other subagents. These subagents each have their own instructions, tools, and expertise.\n",
"\n",
"**Why**: Adding subagents opens up a lot of possibilities:\n",
"1. Specialization: each subagent is an expert in their domain\n",
"2. Separate context: subagents have their own conversation history and tools\n",
"3. Parallellization: multiple subagents can work simultaneously on different aspects.\n",
"\n",
"**How**:\n",
"- Add `\"Task\"` to allowed_tools\n",
"- Use a system prompt to instruct your agent how to delegate tasks (you can also define this its CLAUDE.md more generally)\n",
"- Create a markdown file for each agent in `.claude/agents/`. For example, check the one for `.claude/agents/financial-analyst.md` and notice how a (sub)agent can be defined with such an easy and intuitive markdown file: frontmatter with three fields (name, description, and tools) and its system prompt. The description is useful for the main chief of staff agent to know when to invoke each subagent."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"🤖 Thinking...\n",
"🤖 Using: Task()\n",
"🤖 Using: Bash()\n",
"🤖 Using: Read()\n",
"✓ Tool completed\n",
"✓ Tool completed\n",
"🤖 Using: Bash()\n",
"🤖 Using: Bash()\n",
"✓ Tool completed\n",
"✓ Tool completed\n",
"🤖 Using: Read()\n",
"🤖 Using: Read()\n",
"🤖 Using: Read()\n",
"✓ Tool completed\n",
"✓ Tool completed\n",
"✓ Tool completed\n",
"🤖 Using: Bash()\n",
"✓ Tool completed\n",
"🤖 Using: Bash()\n",
"✓ Tool completed\n",
"✓ Tool completed\n",
"🤖 Thinking...\n"
]
}
],
"source": [
"messages = []\n",
"async with ClaudeSDKClient(\n",
" options=ClaudeCodeOptions(\n",
" model=\"claude-sonnet-4-20250514\",\n",
" allowed_tools=[\"Task\"], # this enables our Chief agent to invoke subagents\n",
" system_prompt=\"Delegate financial questions to the financial-analyst subagent. Do not try to answer these questions yourself.\",\n",
" cwd=\"chief_of_staff_agent\",\n",
" )\n",
") as agent:\n",
" await agent.query(\"Should we hire 5 engineers? Analyze the financial impact.\")\n",
" async for msg in agent.receive_response():\n",
" print_activity(msg)\n",
" messages.append(msg)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"visualize_conversation(messages)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here, when our main agent decides to use a subagent, it will:\n",
" 1. Call the Task tool with parameters like:\n",
" ```json\n",
" {\n",
" \"description\": \"Analyze hiring impact\",\n",
" \"prompt\": \"Analyze the financial impact of hiring 5 engineers...\",\n",
" \"subagent_type\": \"financial-analyst\"\n",
" }\n",
" ```\n",
" 2. The Task tool executes the subagent in a separate context\n",
" 3. Return results to main Chief of Staff agent to continue processing"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Putting It All Together"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's now put everything we've seen together. We will ask our agent to determine the financial impact of hiring 3 senior engineers and write their insights to `output_reports/hiring_decision.md`. This demonstrates all the features seen above:\n",
"- **Bash Tool**: Used to execute the `hiring_impact.py` script to determine the impact of hiring new engineers\n",
"- **Memory**: Reads `CLAUDE.md` in directory as context to understand the current budgets, runway, revenue and other relevant information\n",
"- **Output style**: Different output styles, defined in `chief_of_staff_agent/.claude/output-styles`\n",
"- **Custom Slash Commands**: Uses the shortcut `/budget-impact` that expands to full prompt defined in `chief_of_staff_agent/.claude/commands`\n",
"- **Subagents**: Our `/budget_impact` command guides the chief of staff agent to invoke the financial-analyst subagent defined in `chief_of_staff_agent/.claude/agents` \n",
"- **Hooks**: Hooks are defined in `chief_of_staff_agent/.claude/hooks` and configured in `chief_of_staff_agent/.claude/settings.local.json`\n",
" - If one of our agents is updating the financial report, the hook should log this edit/write activity in the `chief_of_staff_agent/audit/report_history.json` logfile\n",
" - If the financial analyst subagent will invoke the `hiring_impact.py` script, this will be logged in `chief_of_staff_agent/audit/tool_usage_log.json` logfile\n",
"\n",
"- **Plan Mode**: If you want the chief of staff to come up with a plan for you to approve before taking any action, uncomment the commented line below\n",
"\n",
"To have this ready to go, we have encapsulated the agent loop in a python file, similar to what we did in the previous notebook. Check out the agent.py file in the `chief_of_staff_agent` subdirectory. \n",
"\n",
"All in all, our `send_query()` function takes in 4 parameters (prompt, continue_conversation, permission_mode, and output_style), everything else is set up in the agent file, namely: system prompt, max turns, allowed tools, and the working directory.\n",
"\n",
"To better visualize how this all comes together, check out these [flow and architecture diagrams that Claude made for us :)](./chief_of_staff_agent/flow_diagram.md)\n"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"🤖 Thinking...\n",
"🤖 Using: Task()\n",
"🤖 Using: Bash()\n",
"✓ Tool completed\n",
"🤖 Using: Read()\n",
"🤖 Using: Read()\n",
"🤖 Using: Read()\n",
"✓ Tool completed\n",
"✓ Tool completed\n",
"✓ Tool completed\n",
"✓ Tool completed\n",
"🤖 Thinking...\n",
"🤖 Using: Write()\n",
"✓ Tool completed\n",
"🤖 Thinking...\n"
]
}
],
"source": [
"from chief_of_staff_agent.agent import send_query\n",
"\n",
"result, messages = await send_query(\n",
" \"/budget-impact hiring 3 senior engineers. Save your insights by updating the 'hiring_decision.md' file in /output_reports or creating a new file there\",\n",
" # permission_mode=\"plan\", # Enable this to use planning mode\n",
" output_style=\"executive\",\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"visualize_conversation(messages)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Conclusion\n",
"\n",
"We've demonstrated how the Claude Code SDK enables you to build sophisticated multi-agent systems with enterprise-grade features. Starting from basic script execution with the Bash tool, we progressively introduced advanced capabilities including persistent memory with CLAUDE.md, custom output styles for different audiences, strategic planning mode, slash commands for user convenience, compliance hooks for guardrailing, and subagent coordination for specialized tasks.\n",
"\n",
"By combining these features, we created an AI Chief of Staff capable of handling complex executive decision-making workflows. The system delegates financial analysis to specialized subagents, maintains audit trails through hooks, adapts communication styles for different stakeholders, and provides actionable insights backed by data-driven analysis.\n",
"\n",
"This foundation in advanced agentic patterns and multi-agent orchestration prepares you for building production-ready enterprise systems. In the next notebook, we'll explore how to connect our agents to external services through Model Context Protocol (MCP) servers, dramatically expanding their capabilities beyond the built-in tools.\n",
"\n",
"Next: [02_Connecting_to_MCP_servers.ipynb](02_Connecting_to_MCP_servers.ipynb) - Learn how to extend your agents with custom integrations and external data sources through MCP."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python (cc-sdk-tutorial)",
"language": "python",
"name": "cc-sdk-tutorial"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.13"
}
},
"nbformat": 4,
"nbformat_minor": 4
}