← Alle Playbooks
Playbook· build

Vom Skript zum eigenen Agent: der Claude Agent SDK in 90 Minuten

Du kennst Claude Code als CLI. Mit dem Agent SDK baust du denselben agentischen Loop in deinen eigenen Code ein, mit Tool-Kontrolle, Budget-Limit und MCP-Anbindung. Schritt für Schritt.

Claude Code kennst du als das Ding im Terminal. Du tippst, es liest Files, schreibt Code, fragt nach. Was viele nicht wissen, genau dieser agentische Loop steckt in einem npm-Package das du in dein eigenes Projekt ziehen kannst. Der Claude Agent SDK. Damit baust du keinen Chatbot der nur Text zurückgibt, sondern einen Agent der Tools benutzt, Files anfasst, mehrere Schritte plant und am Ende ein Ergebnis liefert. In diesem Playbook bauen wir Schritt für Schritt einen kleinen Agent der eine Datei auf Bugs prüft und sie selbst fixt. Danach weißt du wie du Tools erlaubst, Kosten deckelst und einen MCP-Server anhängst. Du brauchst Node 20 oder neuer und einen Anthropic-API-Key.

1. Wann sich der SDK lohnt, und wann nicht

Bevor du installierst, eine ehrliche Einordnung. Der SDK ist nicht "Claude Code aber als Library zum Chatten". Er ist der agentische Loop ohne das Terminal-UI drumherum. Du nimmst ihn wenn du Agent-Verhalten in etwas Eigenes einbauen willst, einen CI-Job der PRs reviewt, einen nightly Cron der Logs durchgeht, ein internes Tool das Tickets abarbeitet. Wenn du nur ein einzelnes Prompt abschicken und eine Antwort willst, ohne Tools, ohne mehrere Schritte, dann ist das normale Messages-API von Anthropic die einfachere Wahl. Der SDK glänzt erst wenn der Agent mehr als einmal nachdenken und dabei was tun soll. Mir fällt auf dass die meisten Leute den SDK zu früh ziehen, für Sachen die ein simpler API-Call auch könnte.

2. Installieren und der erste Lebenszeichen-Call

Leg ein leeres Projekt an und installier das Package. Der aktuelle Stand ist Version 0.3.162.

npm install @anthropic-ai/claude-agent-sdk
export ANTHROPIC_API_KEY=sk-ant-...

Dann der kürzeste Agent der existiert. Eine Datei agent.mjs:

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

for await (const message of query({
  prompt: "Erklaer mir in zwei Saetzen was diese Codebase macht.",
  options: {
    maxTurns: 1,
    allowedTools: ["Read", "Grep"]
  }
})) {
  if (message.type === "result") {
    console.log(message.result);
  }
}

query() ist kein normaler Funktionsaufruf der ein Objekt zurückgibt. Es ist ein async Iterator. Du läufst mit for await durch einen Strom von Nachrichten, während der Agent arbeitet. Genau das macht ihn zum Agent und nicht zum Chat-Endpoint.

3. Den agentischen Loop wirklich verstehen

Jede Nachricht aus dem Iterator hat einen type. Drei davon brauchst du am Anfang. assistant ist Claude der denkt oder ein Tool aufruft. result ist das Endergebnis am Schluss. Dazwischen können viele assistant-Nachrichten kommen, jede ein Schritt im Loop. So liest du beides mit:

for await (const message of query({ prompt, options })) {
  if (message.type === "assistant" && message.message?.content) {
    for (const block of message.message.content) {
      if ("text" in block) {
        console.log(block.text);          // Claudes Begruendung
      } else if ("name" in block) {
        console.log(`Tool: ${block.name}`); // welches Tool gerade laeuft
      }
    }
  } else if (message.type === "result") {
    console.log(`Fertig: ${message.subtype}`);
  }
}

Wenn du das einmal laufen siehst, verstehst du den ganzen SDK. Claude denkt, ruft ein Tool, kriegt das Ergebnis zurück, denkt weiter, bis er fertig ist. Du schaust nur zu und entscheidest was er anfassen darf.

4. Tools erlauben und sperren

Der wichtigste Hebel ist allowedTools. Lass ihn weg und Claude darf alle eingebauten Tools nutzen, auch Bash und Write. Das willst du am Anfang nicht. Gib explizit an was erlaubt ist:

options: {
  allowedTools: ["Read", "Edit", "Glob", "Grep"],
  disallowedTools: ["Bash"]
}

Die eingebauten Tool-Namen sind dieselben wie in Claude Code, Read, Write, Edit, Glob, Grep, Bash. Eine Faustregel die sich bewährt, fang mit nur lesenden Tools an, Read, Grep, Glob, und schau dem Agent erst zu. Erst wenn das Verhalten passt, gibst du Edit dazu. Bash gibst du als Letztes und nur wenn du wirklich musst, weil damit der Agent beliebige Kommandos fahren kann.

5. Permission-Mode, die Sicherheitsschraube

Tools erlauben ist die eine Hälfte, die andere ist wer den Klick macht. Dafür gibt es permissionMode. Default ist 'default', da fragt der Agent bei heiklen Aktionen nach, was in einem Skript ohne Mensch davor zum Hängen führt. Für unbeaufsichtigte Läufe nimmst du 'acceptEdits', dann werden File-Edits automatisch durchgewunken, der Rest bleibt kontrolliert:

options: {
  allowedTools: ["Read", "Edit", "Glob"],
  permissionMode: "acceptEdits"
}

Es gibt auch 'bypassPermissions', das winkt wirklich alles durch. Dafür musst du zusätzlich allowDangerouslySkipPermissions: true setzen, und der Name ist Programm. Nimm das nur in einer Sandbox oder einem Wegwerf-Container, nie auf deinem echten Rechner mit echten Files. Ich hab das einmal lokal laufen lassen und mir einen Git-Branch zerschossen, seitdem nur noch in Docker.

6. System-Prompt steuern

Standardmäßig läuft der SDK mit leerem System-Prompt, dein Agent ist also ein unbeschriebenes Blatt. Zwei Wege das zu ändern. Entweder du gibst einen eigenen String und kontrollierst alles selbst:

options: {
  systemPrompt: "Du bist ein Python-Spezialist. Schreib Type-Hints, kurze Docstrings, keine Kommentare die das Offensichtliche erklaeren."
}

Oder du nimmst das Verhalten von Claude Code als Basis und hängst nur deine Ergänzung dran:

options: {
  systemPrompt: {
    type: "preset",
    preset: "claude_code",
    append: "Halt dich an unsere ESLint-Config und committe nie direkt auf main."
  }
}

Das Preset gibt dir das gesamte Claude-Code-Verhalten, Datei-Konventionen, Vorsicht bei destruktiven Aktionen, das Ganze. Für die meisten Build-Agents ist das Preset plus append der bessere Start als ein leerer eigener Prompt.

7. Budget und Turns deckeln

Ein Agent der in einer Schleife denkt kann teuer werden wenn er sich verrennt. Zwei Limits ziehst du immer ein. maxTurns begrenzt wie oft der Loop durchläuft, maxBudgetUsd stoppt bei einem Dollar-Betrag:

options: {
  maxTurns: 12,
  maxBudgetUsd: 0.50
}

Bei einem nightly Job der über 30 Files läuft macht der Unterschied zwischen "kostet 40 Cent" und "kostet aus Versehen 12 Dollar" genau diese zwei Zeilen. Setz sie immer, auch beim Rumprobieren. Wenn du Opus mit langem Reasoning für schwere Aufgaben willst, kannst du über model und fallbackModel ein günstigeres Backup definieren falls das Hauptmodell ausfällt.

8. Einen MCP-Server anhängen

Hier wird es interessant. Dein Agent kann nicht nur die eingebauten Tools nutzen, sondern auch jeden MCP-Server den du anbindest. Damit gibst du ihm Zugriff auf eure Datenbank, euer Memory, eure interne API. Du reichst die Server-Configs über mcpServers rein:

options: {
  mcpServers: {
    memory: {
      command: "npx",
      args: ["-y", "@modelcontextprotocol/server-memory"]
    }
  },
  allowedTools: ["Read", "Grep", "mcp__memory__search"]
}

Wichtig, die Tools eines MCP-Servers heißen mcp__<servername>__<toolname> und müssen genauso in allowedTools stehen, sonst darf der Agent sie nicht anfassen. Wenn du noch keinen eigenen MCP-Server hast, bau erst den, wir haben dafür ein eigenes Playbook (siehe unten). Mit MCP wird aus dem generischen Code-Agent ein Agent der euren Stack kennt.

9. Subagents programmatisch definieren

Für größere Aufgaben willst du nicht einen Agent der alles macht, sondern mehrere mit klaren Rollen. Der SDK lässt dich Subagents direkt im Code definieren, über die agents-Option. Jeder kriegt seine eigene Beschreibung und seine eigenen Tools:

options: {
  agents: {
    reviewer: {
      description: "Liest Code und findet Bugs, schreibt aber nie selbst.",
      tools: ["Read", "Grep", "Glob"]
    },
    fixer: {
      description: "Behebt die Bugs die der Reviewer gemeldet hat.",
      tools: ["Read", "Edit"]
    }
  }
}

Das ist dasselbe Muster das du aus dem CEO-Worker-Pattern kennst, nur eben in Code gegossen statt als Markdown-Dateien. Der Haupt-Agent delegiert an die Subagents, jeder bleibt in seiner Spur. Ein lesender Reviewer und ein schreibender Fixer getrennt zu halten verhindert dass dir ein Agent in einem Rutsch falsch analysiert und gleich falsch fixt.

10. Aus dem Skript einen echten Job machen

Der letzte Schritt macht aus dem Spielzeug einen Service. Drei Dinge brauchst du dafür. Erstens Fehlerbehandlung, der result-Type hat ein subtype das dir sagt ob es geklappt hat oder ob der Agent in ein Limit gelaufen ist, das musst du auswerten und nicht einfach ignorieren. Zweitens eine AbortController falls du den Lauf von außen abbrechen können willst. Drittens, für einen nightly Job, ein dünner Wrapper der den Output loggt und bei Fehlern eine Nachricht schickt. Wenn dein Agent regelmäßig laufen soll, kombinier ihn mit Scheduled Agents, dann hast du einen Agent der jede Nacht von selbst arbeitet. Und wenn du 1M-Kontext brauchst weil dein Agent große Codebases liest, aktivierst du das über betas: ["context-1m-2025-08-07"] in den Options.

Damit hast du alles was du brauchst, Tool-Kontrolle, Permission-Mode, Budget-Limit, MCP-Anbindung und Subagents. Der Rest ist Feintuning für deinen konkreten Anwendungsfall.

Was als nächstes

Wenn du den ersten Agent laufen hast, fehlt dir wahrscheinlich ein eigener MCP-Server der deinen Stack kennt. Dafür ist Erster MCP-Server in 90 Minuten der nächste Schritt. Für die Kostenseite lohnt Claude Code Cost-Controls für Daily Driver, die Prinzipien gelten eins zu eins für SDK-Agents. Und wenn dein Agent von selbst laufen soll, schau in Scheduled Agents mit Routines. Die Grundlagen zum Agent-Begriff stehen in Level 5, Was ist ein Agent, das CEO-Worker-Muster aus Schritt 9 vertieft CEO-Worker-Pattern.

Source

Die hier genutzten Optionen und Beispiele stammen aus der offiziellen Agent-SDK-Doku, https://docs.claude.com/en/api/agent-sdk/typescript und https://docs.claude.com/en/api/agent-sdk/overview. Package-Version 0.3.162 verifiziert über npm, npm view @anthropic-ai/claude-agent-sdk version. Die Python-Variante heißt claude_agent_sdk mit query, ClaudeAgentOptions, AssistantMessage und ResultMessage.