Lesson 03 Claude Agent SDK Intro
Theme:

Claude Agent SDK Intro

Lesson 03 · Building Your Own Agents · ~12 min read

What the Claude Agent SDK is — and what it isn’t

The most common confusion in 2026: someone hears about the “Claude Agent SDK,” opens PyPI, types pip install claude-agent-sdk, and finds nothing useful. That’s because the SDK isn’t a separate distribution. It’s a set of higher-level primitives shipped inside the official anthropic Python package — the same package Lesson 02 used for the hand-rolled loop. One pip install anthropic gives you both the low-level Anthropic() Messages client and the agent-loop primitives this lesson introduces. They live in a different namespace (anthropic.agents) but ship in the same wheel.

Contrast briefly with the three other framework SDKs the course covers in Module 3. LangGraph is an independent package (pip install langgraph) that depends on langchain-core. CrewAI is its own package too (pip install crewai), with its own runtime. OpenAI’s agent framework lives in a separate openai-agents distribution alongside the base openai client. Anthropic took a different shape on purpose: same package, additional namespace, no extra dependency to keep current. If your project already imports anthropic, the SDK is already on disk.

The rebrand from Computer Use

Short history, because tutorials and blog posts older than mid-2025 still use the old name. In late 2024 Anthropic released “Computer Use” as a public beta. The framing was narrow: an SDK focused on letting Claude drive a desktop — capture the screen, click, type, scroll — using a small family of pre-defined tools. The interesting parts of that release weren’t actually about desktops; they were about the agent loop, the tool-definition format, and the stop-condition machinery that all of it ran on top of.

In 2025 the scope broadened. General-purpose agent primitives — the loop, the @tool decorator, the typed stop conditions — became the headline. The computer-use tools (screen, mouse, keyboard) were repositioned as one of several built-in tool families alongside web search, code execution, and file editing. The name moved to “Claude Agent SDK.” 2026 Q2 is the first GA-stable cut and the version this course pins: anthropic>=0.39,<0.40 in agents/requirements.txt.

The practical implication for you: if you Google something and land on a 2024 Computer Use tutorial, the imports and shapes are largely the same, but the namespace and entry points moved. Treat anything older than mid-2025 as a hint, not a recipe.

The five primitives you’ll actually use

A small inventory you can hold in your head. Slide 5 has the same list with arrows; this is the prose version.

That’s the whole surface area you need for now. Modules 11 and 12 (Plan F) will revisit more advanced primitives — guardrails, sub-agents, structured-output helpers — when the cross-framework comparison demands them. For Lessons 03 and 04 these five are enough.

Same loop, less code

The headline of this lesson is a line-count delta. The L02 weather agent — the one you wrote by hand — is around 80 lines of Python. The same agent built on the SDK is around 12. Same model calls, same tools, same answer, same cost ballpark. The difference is pure boilerplate.

It is worth walking through what disappeared when you switch:

  1. The for turn in range(MAX_TURNS): loop body now lives inside Agent.run(). You don’t see it.
  2. The branch on response.stop_reason — end_turn, tool_use, max_tokens — is internal.
  3. The “append the assistant’s content, then append a user message containing tool_result blocks” dance is internal too. You don’t mutate a messages list any more.
  4. Cost tracking is automatic. result.usage.total_cost_usd for the total, max_cost_usd= for the cap. The manual total_in / total_out accumulators and the per-model price constants go away.
  5. The turn cap is max_turns= and raises a typed exception (MaxTurnsExceeded) instead of a generic RuntimeError.
  6. The tool-error path — catching the tool function’s exception and surfacing is_error: True back to the LLM — is wrapped by the @tool decorator.

What you still own: writing the tool functions themselves, picking the model, writing the system prompt, deciding budgets, handling KeyboardInterrupt at the outer scope. The interesting parts of agent design didn’t go away — only the loop boilerplate did. That’s the trade you’re making in every framework chapter for the rest of the course.

The @tool decorator and Python introspection

Concretely, the decorator turns this:

from anthropic.agents import tool

@tool
def search_notes(query: str) -> str:
    """Search the user's notes by substring and return up to 5 matches."""
    ...

into the JSON Schema the LLM needs. Type hints become the property types (str → "type": "string", int → "type": "integer", bool → "type": "boolean", list[X] → "type": "array", and so on). A parameter is required if it has no default; otherwise it’s optional. The docstring becomes the tool description, which is what the LLM actually reads when deciding whether to call the tool.

Docstrings matter more than function names

A vague docstring — or none at all — means the LLM doesn’t know when to call your tool. The agent stalls, asks the user clarifying questions it shouldn’t need to, or hallucinates an answer instead of calling the tool. A specific docstring with an example input and the exact format of the return value is dramatically more reliable. The hand-rolled L02 schema dict had a description field that played the same role; the SDK just makes the docstring the canonical place for it. Homework Task 1 will have you observe this failure mode first-hand.

Pydantic models also work as parameter types — useful when one tool argument is a structured object rather than a primitive. The decorator reads the model’s field definitions and inlines them into the schema. We’ll lean on this in L04 for a write_report(sections: list[Section]) tool, and Homework Task 2 introduces it with a smaller TravelQuery model.

Built-in stop conditions and the on_step hook

Lesson 01 enumerated four stop conditions for an agent loop: natural exit, turn cap, cost cap, and caller interrupt. Lesson 02 wired three of them by hand (the cost cap was an if branch on accumulated usage; the turn cap was the range() in the for loop; the interrupt was KeyboardInterrupt). The SDK collapses all of that to constructor arguments:

from anthropic import Anthropic
from anthropic.agents import Agent

agent = Agent(
    client=Anthropic(),
    model="claude-3-5-sonnet-latest",
    system="You are a helpful weather assistant.",
    tools=[get_weather, get_clothing_advice],
    max_turns=10,             # turn cap
    max_cost_usd=0.50,        # cost cap
    on_step=my_step_handler,  # caller hook
)

Pricing comes from the model registry inside the anthropic package. If you use a custom or fine-tuned model whose price isn’t in the registry, supply pricing=ModelPricing(input_per_million=..., output_per_million=...) on the Agent constructor. In L02 these prices were a manual pair of module-level constants; here they’re a structured argument the SDK uses internally.

When to pick Claude Agent SDK (and when not to)

A short decision matrix you’ll revisit in Module 6 once you’ve seen LangGraph, CrewAI, and the OpenAI Agents SDK side by side. For now, the rules of thumb:

Pick the Claude Agent SDK when:

Don’t pick the Claude Agent SDK when:

This is the framing L04 builds on: the tool-heavy research assistant is the canonical sweet-spot demo for the Claude Agent SDK, and it’s exactly the shape you’ll build next.

References