Mindket

Claude Agent SDK tutorial: build your own agent in TypeScript or Python

A black banner titled "Claude Code advanced" over the line "Settings, headless runs, CI and the Agent SDK".

The Claude Agent SDK is Claude Code as a library. Install @anthropic-ai/claude-agent-sdk for TypeScript or claude-agent-sdk for Python, call query() with a prompt and options, and read the stream of messages until a result arrives. Built-in tools, permissions, sessions and MCP support come with it. Use it when you want that agent loop inside your own program.

In this lesson

  • query() returns an async stream that ends in a result message. Its subtype says whether the run succeeded or hit a limit, so check it before you read result.
  • allowedTools pre-approves the tools you list and does not restrict the rest. Pair it with permissionMode: "dontAsk" for a locked-down agent, or use disallowedTools to remove a tool.
  • The SDK loads your user, project and local settings by default, so the deny rules from the settings lesson apply to your agent. Pass settingSources: [] to switch that off.
  • Cap every production agent with maxTurns and maxBudgetUsd. A single-shot call raises after an error result, so keep the loop inside try and catch.
All courses
On this page
  1. The Agent SDK next to the other ways to run Claude
  2. Install it and run a first agent
  3. Read the stream, then check the result
  4. Permissions: what runs without asking
  5. Approvals in your own code
  6. Give Claude a tool of your own
  7. Attach MCP servers other people wrote
  8. Sessions: continue, resume and fork
  9. What the SDK reads from disk
  10. Errors before the first message
  11. Boris Cherny used Lean to find bugs in the Agent SDK itself
  12. Try it yourself
  13. Next course: Open-weight models
  14. Check yourself
  15. Frequently asked questions
  16. Sources

The Agent SDK next to the other ways to run Claude

The Agent SDK puts the loop behind Claude Code into a library: the same built-in tools, permission system, sessions, hooks and MCP support, driven from your own Python or TypeScript code. The GitHub Actions lesson already used it, since the action is built on the SDK, and claude -p from the headless lesson is its command-line form. Anthropic's overview sorts the four options by who runs the agent.

The library runs in Python and TypeScript only. From another language, start the CLI as a subprocess with -p and --output-format json. For a single step in a script, claude -p is the smaller tool. Reach for the SDK when your own code has to answer approval prompts, define tools that run inside your process or keep sessions for several users.

Each language has its own repository on GitHub, where the changelog and issues live. On GitHub, the Python one has the larger following.

The two SDK repositories on GitHub

8.4k

stars on claude-agent-sdk-python

Source: anthropics/claude-agent-sdk-python on GitHub (read November 5, 2026)

1.4k

forks of the Python SDK

Source: anthropics/claude-agent-sdk-python on GitHub (read November 5, 2026)

1.9k

stars on claude-agent-sdk-typescript

Source: anthropics/claude-agent-sdk-typescript on GitHub (read November 5, 2026)

246

forks of the TypeScript SDK

Source: anthropics/claude-agent-sdk-typescript on GitHub (read November 5, 2026)

Which Claude tool fits, from the Agent SDK overview
You want toUseWhat you get
Run Claude Code's agent inside your own app, in a process you operateAgent SDKA library with Claude Code's tools, permissions, sessions and hooks
Work interactively or run one-off tasks in a terminalClaude Code CLIThe terminal interface built for daily use
Call the Claude API from your own codeClient SDKDirect API access. You write the tool loop, or let the beta tool runner drive it
Have Anthropic host the agentManaged AgentsAnthropic runs the agent loop for you, with sessions in its cloud sandbox or your own self-hosted one

Install it and run a first agent

You need Node.js 18.14 or newer, or Python 3.10 or newer, and an API key from the Claude Console. Both packages bundle a native Claude Code binary, so most installs need no separate Claude Code. Anthropic's quickstart builds an agent that fixes two crashing functions in a file named utils.py. This is that agent in TypeScript.

The prompt is the task, options is the configuration and query returns the stream. Claude picks the tools. Here allowedTools pre-approves three of them and acceptEdits approves the file changes. The steps after the script install it and run it.

import { query } from "@anthropic-ai/claude-agent-sdk";

// Agentic loop: streams messages as Claude works
for await (const message of query({
  prompt: "Review utils.py for bugs that would cause crashes. Fix any issues you find.",
  options: {
    allowedTools: ["Read", "Edit", "Glob"], // Auto-approve these tools
    permissionMode: "acceptEdits" // Auto-approve file edits
  }
})) {
  // Print human-readable output
  if (message.type === "assistant" && message.message?.content) {
    for (const block of message.message.content) {
      if ("text" in block) {
        console.log(block.text); // Claude's reasoning
      } else if ("name" in block) {
        console.log("Tool: " + block.name); // Tool being called
      }
    }
  } else if (message.type === "result") {
    console.log("Done: " + message.subtype); // Final result
  }
}
  1. Make a folder and install: npm init -y, npm pkg set type=module, npm install @anthropic-ai/claude-agent-sdk and npm install --save-dev tsx. For Python, create a virtual environment and run pip install claude-agent-sdk, or use uv add claude-agent-sdk.
  2. Export ANTHROPIC_API_KEY in the shell that runs the agent. The SDK reads the process environment and does not load .env files, so load one yourself with a package such as dotenv.
  3. Save the script as agent.ts beside a utils.py with a function that crashes on an empty list, then run npx tsx agent.ts. The agent prints its reasoning and each tool it calls, and ends with Done: success.
Option names in the two SDKs
ConceptTypeScriptPython
Options objectA plain objectClaudeAgentOptions
Pre-approved toolsallowedToolsallowed_tools
Permission modepermissionModepermission_mode
Approval callbackcanUseToolcan_use_tool
Turn and spend capsmaxTurns, maxBudgetUsdmax_turns, max_budget_usd
Settings to loadsettingSourcessetting_sources
Fork a sessionforkSessionfork_session
Spot the resultmessage.type === "result"isinstance(message, ResultMessage)

On Amazon Bedrock, Google Cloud's Agent Platform or Microsoft Foundry, set CLAUDE_CODE_USE_BEDROCK=1, CLAUDE_CODE_USE_VERTEX=1 or CLAUDE_CODE_USE_FOUNDRY=1 and configure that cloud's credentials. Claude Platform on AWS takes CLAUDE_CODE_USE_ANTHROPIC_AWS=1 and ANTHROPIC_AWS_WORKSPACE_ID, with AWS credentials.

Read the stream, then check the result

One query() call runs the whole loop. Claude answers or asks for a tool, the SDK runs it and feeds the output back, and this repeats until a reply has no tool calls. You receive a system message with the init data, an assistant message for each content block, a user message for each tool result and finally a result. Stream events join them only when you turn on partial messages. Anthropic's agent loop page has the full list.

Iterate to the end instead of breaking on the result, because a few trailing system events can still arrive after it. Then branch on subtype. The loop below prints the text and the tool calls, and says what stopped the run.

import { query } from "@anthropic-ai/claude-agent-sdk";

try {
  for await (const message of query({ prompt: "Summarize this project" })) {
    if (message.type === "assistant") {
      // Each assistant message carries one content block
      for (const block of message.message.content) {
        if (block.type === "text") {
          console.log("Claude: " + block.text);
        } else if (block.type === "tool_use") {
          console.log("Tool call: " + block.name);
        }
      }
    }
    if (message.type === "result") {
      if (message.subtype === "success") {
        console.log(message.result);
      } else {
        console.log("Stopped: " + message.subtype);
      }
    }
  }
} catch (error) {
  // A single-shot query() throws after yielding an error result.
  console.log("Session ended with an error: " + error);
}
  • Every result carries total_cost_usd, usage, num_turns and session_id, even an error one, so you can log spend and resume. usage covers the main loop only. modelUsage covers the whole tree, subagents included.
  • maxTurns counts each turn that calls tools plus one for the final text-only reply. With a cap of 2, the four-turn test fix in Anthropic's example would stop before the edit.
  • maxBudgetUsd is checked after each response arrives, so spend can pass the cap by one response plus any subagents still running. Subagent spend counts toward it, and spawning another one after the cap fails with Budget limit reached. Those cap behaviors need Claude Code v2.1.217 or later.
  • A single-shot query() yields the error result and then raises, so the try and catch above is the normal shape. To catch a refusal, test stop_reason for refusal.
Result subtypes, from the agent loop page
SubtypeWhat happenedresult present
successClaude finished the taskYes
error_max_turnsThe maxTurns limit came firstNo
error_max_budget_usdThe maxBudgetUsd limit came firstNo
error_during_executionAn error interrupted the loop, such as a cancelled requestNo
error_max_structured_output_retriesNo valid structured output arrived within the retry limitNo

Permissions: what runs without asking

With Claude Code v2.1.302 or later, an SDK app starts in default mode unless you set a mode or its settings files do. In default, a call that needs approval is denied unless an allow rule, a hook or your callback approves it. A tool call that comes back denied in a headless run usually traces back to this.

Two options do most of the work. allowedTools auto-approves what it lists, and the other tools still exist: an unlisted tool falls through to the mode. disallowedTools is the block. A bare name such as Bash removes the tool from Claude's context, while Bash(rm *) leaves it available and denies matching calls in every mode as written, so /bin/rm slips past it. A scoped allow entry such as Bash(npm test *) works the same way in reverse and approves only matching calls.

For a locked-down agent, list the read tools and set dontAsk, so every call that would prompt is denied. Behind both options sits one fixed order, which the permissions page lists and the steps below repeat.

const options = {
  allowedTools: ["Read", "Glob", "Grep"],
  permissionMode: "dontAsk"
};
  1. Hooks run first. A hook can deny a call, and a hook that allows it does not skip the deny and ask rules after it.
  2. Deny rules, from disallowedTools or settings files. A match denies the call in every mode, bypassPermissions included.
  3. Ask rules from settings files. A match sends the call to your callback, again even in bypassPermissions.
  4. The permission mode. acceptEdits approves file edits and filesystem commands such as mkdir, mv and cp inside the working directory, and bypassPermissions approves what reaches it.
  5. Allow rules, from allowedTools and settings files. A match approves the call.
  6. Your canUseTool callback decides whatever is left. In dontAsk mode this step is skipped and the call is denied.

allowedTools does not constrain bypassPermissions. With allowedTools: ["Read"] and that mode, every tool is approved, Bash included. TypeScript also needs allowDangerouslySkipPermissions: true for the mode, and on Linux and macOS it will not start as root outside a recognized sandbox.

Approvals in your own code

Your callback fires when nothing earlier resolved the call, and when Claude uses the AskUserQuestion tool to put a question to the person. It receives the tool name and its input. It returns an allow, with optional edited input, or a deny with a message that Claude reads as the tool result. Execution waits until you answer. The full contract is on the user input page.

Auto-approved tools never reach canUseTool.

Anthropic, Agent SDK documentation · Agent SDK docs: Configure permissions (read November 4, 2026)
import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const message of query({
  prompt: "Create a test file in /tmp and then delete it",
  options: {
    canUseTool: async (toolName, input) => {
      // Display the tool request
      console.log("Tool: " + toolName, input);

      // Ask the user with your own prompt helper
      const response = await prompt("Allow this action? (y/n): ");

      if (response.toLowerCase() === "y") {
        // Allow: the tool runs with the original (or modified) input
        return { behavior: "allow", updatedInput: input };
      }
      // Deny: the tool does not run, and Claude sees the message
      return { behavior: "deny", message: "User denied this action" };
    }
  }
})) {
  if ("result" in message) console.log(message.result);
}
  • Put checks that must see every call in a PreToolUse hook. Hooks run before every other step, and a hook deny holds even in bypassPermissions.
  • A callback can stay pending indefinitely. If a person may take longer than your process can live, return the defer decision from a PreToolUse hook, let the process exit and resume the saved session later.
  • In Python the callback has a catch that the docs call a required workaround. Pass the prompt as an async generator that yields user messages, and add a PreToolUse hook that returns {"continue_": True} so the stream stays open.
  • The TypeScript SDK prints a process warning with the code CLAUDE_SDK_CAN_USE_TOOL_SHADOWED once per query when canUseTool sits beside bypassPermissions or a bare tool name in allowedTools, because the callback will not see those calls.

Give Claude a tool of your own

A custom tool has four parts: a unique name, a description Claude reads to decide when to call it, an input schema and an async handler. The schema is a Zod schema in TypeScript and a dict of types in Python. The handler returns a content array of result blocks. You wrap tools in an in-process MCP server, so nothing runs as a separate process. The custom tools page has the Python version.

Pass the server in mcpServers and list each tool by its full name in allowedTools, here mcp__weather__get_temperature. That name joins the server key and the tool name with double underscores.

import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
import { z } from "zod";

// Define a tool: name, description, input schema, handler
const getTemperature = tool(
  "get_temperature",
  "Get the current temperature at a location",
  {
    latitude: z.number().describe("Latitude coordinate"),
    longitude: z.number().describe("Longitude coordinate")
  },
  async (args) => {
    const response = await fetch(
      "https://api.open-meteo.com/v1/forecast?latitude=" + args.latitude +
        "&longitude=" + args.longitude +
        "&current=temperature_2m&temperature_unit=fahrenheit"
    );
    const data: any = await response.json();

    // Return a content array: Claude sees this as the tool result
    return {
      content: [{ type: "text", text: "Temperature: " + data.current.temperature_2m + " F" }]
    };
  }
);

// Wrap the tool in an in-process MCP server
const weatherServer = createSdkMcpServer({
  name: "weather",
  version: "1.0.0",
  tools: [getTemperature]
});

for await (const message of query({
  prompt: "What's the temperature in San Francisco?",
  options: {
    mcpServers: { weather: weatherServer },
    allowedTools: ["mcp__weather__get_temperature"]
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}
  • An uncaught exception inside a handler does not stop the loop. The server turns it into an error result carrying the raw message, and Claude can retry or explain. Catch it yourself and return isError: true when Claude needs a message it can act on, such as which request failed.
  • Custom tools run one at a time by default. Set readOnlyHint: true in a tool's annotations to let Claude call it in parallel with other read-only tools.

Attach MCP servers other people wrote

Servers you did not write go in the same mcpServers option. A stdio server takes a command and args and runs as a local process. A remote one takes type: "http" and a url, as in this example that connects Anthropic's documentation server. You can also keep the list in a .mcp.json at the project root, which loads through the project setting source. The MCP page covers authentication and errors.

import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const message of query({
  prompt: "Use the docs MCP server to explain what hooks are in Claude Code",
  options: {
    mcpServers: {
      "claude-code-docs": {
        type: "http",
        url: "https://code.claude.com/docs/mcp"
      }
    },
    allowedTools: ["mcp__claude-code-docs__*"]
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}
  • MCP tools need explicit permission. Without it Claude sees them and cannot call them. acceptEdits does not cover them, and bypassPermissions does but also drops most other prompts, so list the tools in allowedTools.
  • A wildcard works only after a literal mcp__ and a server name. mcp__github__* approves that server's tools, while ["*"] or ["mcp__*"] in an allow list is ignored.
  • A stdio server, or a remote one without a cached tool list, holds up the first turn until it connects, for 30 seconds by default (MCP_TIMEOUT). When tools seem missing, read each server's status in the init message.
  • A dot or a space in a server key becomes an underscore in tool names, so my.server gives mcp__my_server__list_issues.

Sessions: continue, resume and fork

A session is the conversation history, the prompt, every tool call and result and the replies, and the SDK writes it to disk without being asked. It stores the conversation and not your files, so use file checkpointing when you need to revert edits. Within one query() call the agent already takes as many turns as it needs, and approval prompts are handled in the loop. Sessions matter once separate prompts should share context, as the sessions page describes.

import { query } from "@anthropic-ai/claude-agent-sdk";

let sessionId: string | undefined;

// First run: read the session ID off the result message
for await (const message of query({
  prompt: "Analyze the auth module and suggest improvements",
  options: { allowedTools: ["Read", "Glob", "Grep"] }
})) {
  if (message.type === "result") sessionId = message.session_id;
}

// Later run: resume it, and the agent keeps the earlier analysis
for await (const message of query({
  prompt: "Now implement the refactoring you suggested",
  options: {
    resume: sessionId,
    allowedTools: ["Read", "Edit", "Write", "Glob", "Grep"]
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}
  • Forking copies the history into a new session and leaves the original untouched. It does not copy files, so a forked agent's edits are real for every session in that directory.
  • Session files are local to the machine that wrote them, under ~/.claude/projects in a folder named from the working directory. To resume on another host, attach a sessionStore adapter, or pass the results you need into a fresh session's prompt.
  • After error_max_turns or error_max_budget_usd, resume the session with a higher limit.
  • The experimental TypeScript V2 session API, createSession(), was removed in SDK 0.3.142. A tutorial that calls it needs query() with continue or resume instead.
Which session option fits which app
What you buildWhat to use
A one-shot taskOne query() call and nothing else
A chat in one processPython ClaudeSDKClient, or continue: true in TypeScript
Pick up after a restartcontinue_conversation=True or continue: true, which resumes the newest session in the directory
One session per userCapture the session ID and pass it to resume
Try another approach and keep the originalFork it with fork_session or forkSession
Nothing written to diskpersistSession: false in TypeScript, or CLAUDE_CODE_SKIP_PROMPT_HISTORY in Python's env

What the SDK reads from disk

The SDK starts the Claude Code binary, so the files that shape Claude Code shape your agent unless you opt out.

  • With settingSources omitted, query() loads user, project and local settings, the same as the CLI. Your .claude/settings.json allow, ask and deny rules and a .mcp.json apply, which is why the settings lesson matters here. CLAUDE.md files load when project is among the sources. Python narrows the default to user and project when you set skills and leave setting_sources unset.
  • Pass settingSources: [] for an agent that ignores all three. Managed policy settings still load, because they are not a source you can switch off.
  • In TypeScript the default system prompt is minimal. Pass { type: "preset", preset: "claude_code" } as systemPrompt, or system_prompt in Python, to use Claude Code's own, with an optional append.
  • The env option replaces the subprocess environment in TypeScript, so pass { ...process.env, YOUR_VAR: "value" } to keep PATH. In Python it merges on top of the inherited environment.
  • For several tenants in one service, give each its own settingSources, env and cwd.

Errors before the first message

  • CLINotFoundError in Python means the SDK launched the CLI as a subprocess and found none. Platform wheels bundle it, but a source install, for example on ARM64 Windows, does not. Install Claude Code natively, confirm claude --version works where your app runs, or set cli_path. A service started outside your shell often has a different PATH.
  • Refusing to execute batch script on Windows means the SDK will not run an npm claude.cmd shim, because cmd.exe re-parses arguments and could run injected commands. Point cli_path at a claude.exe or remove it so the bundled binary is used. The check arrived in claude-agent-sdk 0.2.124.
  • In TypeScript, a message that the native CLI binary for your platform was not found means the install skipped optional dependencies, as npm ci --omit=optional does. Reinstall without skipping them, or set pathToClaudeCodeExecutable.
  • A bare ProcessError in Python prints "Error output: Check stderr output for details", which is fixed text. Pass a stderr callback in the options to capture what the CLI wrote.
  • Calling a ClaudeSDKClient method before it connects raises Not connected. Call connect() first. Open the client with async with, which connects on entry.
  • Not logged in or Invalid API key usually means ANTHROPIC_API_KEY is not set in the environment of the process that runs the agent. Check that process, not your shell history.

Boris Cherny used Lean to find bugs in the Agent SDK itself

Boris Cherny, who created Claude Code, posted on X in September that he had used Opus 5.5 to formally verify the Agent SDK with Lean, a language for machine-checked proofs. A couple of short prompts produced 16 pull requests that fixed bugs and race conditions. He added that TLA+ works well too, and that he sometimes combines the two to look at data flow, concurrency and state. He said he knows neither language well.

Fixes like these ship in new SDK releases, so keep the package current with npm update @anthropic-ai/claude-agent-sdk or pip install -U claude-agent-sdk, and read the changelog first. The method also works on your own code: ask Claude to model the part of your agent that handles sessions or parallel tool calls, then look for the states your tests never reach.

For a longer walkthrough, Thariq Shihipar of Anthropic gave a workshop on the SDK, recorded by the AI Engineer channel.

I used Opus 5.5 to formally verify the Claude Agent SDK using Lean. A couple short prompts = 16 PRs fixing various bugs and race conditions.

Boris Cherny, Creator of Claude Code, at Anthropic · X (read November 5, 2026)
Boris Cherny (@bcherny) on X, 22 September 2026: he used Opus 5.5 to formally verify the Claude Agent SDK using Lean, and a couple of short prompts gave 16 PRs fixing bugs and race conditions. TLA+ also works well.
Boris Cherny on X, 22 September 2026
Claude Agent SDK [Full Workshop] by Thariq Shihipar of Anthropic, on the AI Engineer channel on YouTube.

A screenshot of X's own embed of the post, taken on 5 November 2026, with the time in UTC. X cuts the post short with Show more. Select it to open the post on X.

Try it yourself

  • Run the quickstart agent, then set maxTurns to 2 and read the result subtype. Raise it and compare.
  • Switch to permissionMode: "dontAsk" with only Read allowed and ask for an edit. Watch the denial come back as a tool result and see what Claude does next.
  • Add the weather tool, rename its server key to my.weather and work out the allowed tool name you now need.
  • Capture a session_id from a result, resume it with a follow-up prompt, then fork it and compare the two IDs.

Next course: Open-weight models

This lesson ran the agent on Claude in the cloud. The next course, Open-weight models, explains the models you can download and run yourself, and the Local AI course after it runs one with Ollama. The MCP course comes later. Build an MCP server in Python writes a server that any agent can connect to, including one you run with this SDK.

Subagents work through the same options. The SDK takes an agents option that defines them in code, and the subagents guide covers when to split work that way.

Check yourself

  1. You set allowedTools to ["Read"] together with permissionMode "bypassPermissions". Which tools run without a prompt?

    Show answer

    C. Every tool, Bash and Edit included allowedTools only pre-approves what it lists, and bypassPermissions approves every call that reaches the mode step, so it does not constrain that mode.

  2. What do you check on the final message of a query() loop before you read its result field?

    Show answer

    A. That its subtype is success Only the success variant carries result. The error subtypes, such as error_max_turns, have none.

  3. In Python you set can_use_tool and pass a plain string as the prompt. What does the docs' pattern ask for instead?

    Show answer

    D. Pass the prompt as an async generator and add a PreToolUse hook that keeps the stream open The docs call the streaming prompt with a dummy PreToolUse hook a required workaround for can_use_tool in Python.

  4. A custom tool get_temperature lives in an in-process server keyed weather. Which allowedTools entry pre-approves it?

    Show answer

    B. mcp__weather__get_temperature MCP tool names join the server key and the tool name with double underscores after an mcp prefix.

Frequently asked questions

Is the Agent SDK the same as the Claude Code SDK?

The Agent SDK is the package you move to. Anthropic has a migration guide for the older Claude Code SDK packages, so a tutorial that imports those needs the guide first.

How do I choose the model?

Set the model option to an alias such as sonnet, opus or haiku, or to a full model name. Without it the default from the CLI applies. A subagent can override it with the model field on its definition, and inherit uses the main model.

Can my app sign users in with their Claude subscription?

Unless Anthropic has approved it in advance, third party developers may not offer claude.ai login or its rate limits in their products, and that includes agents built on the Agent SDK. Use API key authentication, or Bedrock, Vertex or Foundry credentials.

What is the difference between query() and ClaudeSDKClient in Python?

query() starts a new session for each call and handles one exchange, without interrupts. ClaudeSDKClient keeps one session across exchanges and supports interrupts. That suits chat interfaces and work where the next step depends on Claude's answer. TypeScript has no client object and uses continue: true.

How do I stream text as Claude writes it?

Partial messages do it. Once they are on, the stream adds StreamEvent messages that carry the raw API streaming events, such as text deltas. The option is includePartialMessages in TypeScript and include_partial_messages in Python.

Can I call my product Claude Code?

No. Anthropic's branding guidelines allow "Claude Agent", or your own agent name followed by "Powered by Claude", and they do not permit "Claude Code" or "Claude Code Agent". Your product keeps its own branding.

When is the Client SDK a better choice?

When you need one model call, or want to own the tool loop. It gives direct access to the Claude API, and you write the loop or use the beta tool runner. The Agent SDK ships the loop, so your time goes into tools and permissions instead.

Sources

  1. Claude Code docs: Agent SDK overview (read November 5, 2026)https://code.claude.com/docs/en/agent-sdk/overview
  2. Claude Code docs: Agent SDK quickstart (read November 5, 2026)https://code.claude.com/docs/en/agent-sdk/quickstart
  3. Claude Code docs: How the agent loop works (read November 4, 2026)https://code.claude.com/docs/en/agent-sdk/agent-loop
  4. Claude Code docs: Configure permissions (read November 4, 2026)https://code.claude.com/docs/en/agent-sdk/permissions
  5. Claude Code docs: Handle approvals and user input (read November 4, 2026)https://code.claude.com/docs/en/agent-sdk/user-input
  6. Claude Code docs: Give Claude custom tools (read November 4, 2026)https://code.claude.com/docs/en/agent-sdk/custom-tools
  7. Claude Code docs: Connect to external tools with MCP (read November 4, 2026)https://code.claude.com/docs/en/agent-sdk/mcp
  8. Claude Code docs: Work with sessions (read November 4, 2026)https://code.claude.com/docs/en/agent-sdk/sessions
  9. Claude Code docs: Agent SDK reference, TypeScript (read November 4, 2026)https://code.claude.com/docs/en/agent-sdk/typescript
  10. Claude Code docs: Agent SDK reference, Python (read November 4, 2026)https://code.claude.com/docs/en/agent-sdk/python
  11. anthropics/claude-agent-sdk-python on GitHub (read November 5, 2026)https://github.com/anthropics/claude-agent-sdk-python
  12. anthropics/claude-agent-sdk-typescript on GitHub (read November 5, 2026)https://github.com/anthropics/claude-agent-sdk-typescript
  13. Boris Cherny on X: formally verifying the Claude Agent SDK with Lean (read November 5, 2026)https://x.com/bcherny/status/2102543349102338309
  14. AI Engineer on YouTube: Claude Agent SDK [Full Workshop], Thariq Shihipar (read November 5, 2026)https://www.youtube.com/watch?v=TqC1qOfiVcQ

Share this lesson

Skills your agent can load

An agent built on the SDK loads skills from the project's .claude folder like Claude Code does. Browse the skills on Mindket.

Browse skills

This lesson as Markdown · Claude Code advanced course · All courses