Stop Installing Claude Code Separately: This Python SDK Bundles It for You
If you've ever built a tool that wraps a CLI, you know the dance: install your package, then pray the user remembers to install the CLI dependency separately, then debug version mismatches when they don't. It's tedious. The Claude Agent SDK for Python sidesteps that entire problem by bundling the Claude Code CLI directly into the pip package. One pip install, and you're done.
This is a Python SDK for interacting with Claude Agent—the same agent that powers Claude Code—from your own applications. Whether you want a quick one-shot query or a full interactive session with custom tools, this library gives you a programmatic interface to Claude's agentic capabilities.
What It Does
At its core, the SDK provides two ways to talk to Claude Agent. The first is query(), an async function that sends a prompt and returns an AsyncIterator of response messages. Think of it as a fire-and-stream approach: you send a prompt, and you get back a stream of AssistantMessage objects you can iterate over and print or process.
The second is ClaudeSDKClient, which enables bidirectional, interactive conversations. This is where things get more interesting—it supports custom tools and hooks, both of which you can define as plain Python functions.
The architecture is straightforward. The package requires Python 3.10+ and uses anyio for async I/O (as shown in the quick start example). Under the hood, the Claude Code CLI is bundled with the package, so the SDK uses that by default. If you'd rather use a system-wide installation or a specific version, you have two escape hatches: install Claude Code separately via the official install script, or specify a custom path with ClaudeAgentOptions(cli_path="/path/to/claude").
Why It's Cool
The bundled CLI is a genuinely thoughtful design choice. Most SDKs that wrap external tools assume you'll install the dependency yourself. This one doesn't. You get a consistent, known version of the CLI with the SDK, which means fewer "it works on my machine" issues. And if you're a power user who wants a different version, the escape hatch is right there.
The tool permission model is nuanced and well-documented. By default, Claude has access to the full Claude Code toolset (Read, Write, Edit, Bash, and others). allowed_tools isn't a whitelist that removes tools—it's a permission allowlist. Tools you list there get auto-approved; everything else falls through to permission_mode and can_use_tool for a decision. If you want to actually block tools, you use disallowed_tools instead. That's a subtle but important distinction that shows careful thought about how agent permissions should work.
Custom tools run in-process as MCP servers. This is the killer feature. When you define a custom tool with the @tool decorator, it runs as an in-process MCP server directly within your Python application. No separate processes to manage, no socket juggling, no deployment complexity. You write a Python function, decorate it, and Claude can call it. The example in the README shows a simple greet tool that takes a name and returns a greeting—about as low-friction as custom tooling gets.
The ClaudeSDKClient opens up real application-building possibilities. With custom tools and hooks defined as Python functions, you're not just querying an agent—you're embedding one into your application with your own capabilities attached. That's the difference between a script that asks Claude a question and an application that uses Claude as a component.
How to Try It
Getting started is genuinely painless. First, install the package:
pip install claude-agent-sdk
That's it. No separate CLI installation, no environment variables, no configuration files.
Then try the simplest possible query:
import anyio
from claude_agent_sdk import query
async def main():
async for message in query(prompt="What is 2 + 2?"):
print(message)
anyio.run(main)
From there, you can start layering in options. Here's a query with a system prompt and a custom working directory:
from claude_agent_sdk import query, ClaudeAgentOptions
options = ClaudeAgentOptions(
system_prompt="You are a helpful assistant",
max_turns=1,
cwd="/path/to/project"
)
async for message in query(prompt="Tell me a joke", options=options):
print(message)
And if you want to try custom tools, the pattern is:
from claude_agent_sdk import tool, create_sdk_mcp_server, ClaudeAgentOptions
@tool("greet", "Greet a user", {"name": str})
async def greet_user(args):
return {
"content": [
{"type": "text", "text": f"Hello, {args['name']}!"}
]
}
server = create_sdk_mcp_server(
name="my-tools",
version="1.0.0",
tools=[greet_user]
)
You can find the full repository, including an end-to-end calculator example, at github.com/anthropics/claude-code-sdk-python. The official documentation link in the README points to the Claude Agent SDK docs for more depth.
Final Thoughts
This SDK is best for Python developers who want to build applications that leverage Claude's agentic capabilities without wrestling with CLI installation or subprocess management. The bundled CLI removes a whole class of setup friction, and the in-process MCP server approach for custom tools is a pragmatic choice that keeps things simple. It's not trying to be a full agent framework—it's a clean, focused SDK that does one thing well. If you've been eyeing Claude Code and wondering how to integrate it into your own tools, this is the path of least resistance.
Follow @githubprojects for more developer tools and open source projects.