Wird geladen

Was ist Tool-Nutzung?

Lektion 58 Min.
Wird geladen

Was ist Tool-Nutzung?

Deine bestehenden Workflows verlassen sich auf viele verschiedene Technologien — Projektmanagement-Software, Datenbanken, Dateien. Claude kann diese Dinge nicht einfach selbst überprüfen. Stattdessen verlässt es sich auf Tools, die Claude Zugriff auf externe Daten und Aktionen geben.

Was ein Tool ist

Einfach ausgedrückt ist ein Tool eine Funktion, die du definierst und Claude zur Verfügung stellst. Du beschreibst, was sie tut und welche Eingaben sie benötigt, und Claude entscheidet, wann es sie aufruft.

Hier ist der entscheidende Punkt, den du verinnerlichen solltest: Claude führt das Tool nicht aus — dein Code tut das. Der Ablauf sieht so aus:

  1. Claude fordert einen Tool-Aufruf an.
  2. Dein Code führt die Funktion aus.
  3. Das Ergebnis geht zurück an Claude, und es macht weiter.

Wie Tools definiert werden

Tools sind JSON-Schemas mit drei Teilen: einem Namen, einer Beschreibung und einem Input-Schema. Du übergibst sie Claude im Request-Body als ein tools-Array.

Die Beschreibung ist das, was Claude liest, um zu entscheiden, ob es das Tool aufruft. Wenn du eine vage Beschreibung schreibst, bekommst du schlechte Tool-Nutzung. Das ist der Hauptgrund, warum Agenten fehlzünden oder die verfügbaren Tools nicht nutzen. Sei spezifisch.

So sieht eine Tool-Definition aus:

json
{
  "name": "lookup_building_code",
  "description": "Look up a specific building code section by its identifier. Returns the full text of that code section.",
  "input_schema": {
    "type": "object",
    "properties": {
      "section": {
        "type": "string",
        "description": "The building code section to look up"
      }
    },
    "required": ["section"]
  }
}

Was passiert also, wenn wir das verwenden? Angenommen, wir senden einem Agenten einen Compliance-Bericht. In der ersten Runde kommt Claude mit stop_reason: "tool_use" zurück — das ist unser Signal. So sieht diese Antwort aus:

Eine API-Antwort mit stop_reason auf tool_use gesetzt, die einen tool_use-Content-Block enthält, der das Tool benennt und die Eingabe, mit der Claude es aufrufen möchte

Unsere Schleife ruft lookup_building_code mit dem von Claude angeforderten Parameter auf und gibt das Ergebnis dann als Tool-Ergebnis zurück — eine Benutzernachricht, die einen tool_result-Block enthält, der an die ID des Tool-Aufrufs gebunden ist:

Eine Benutzernachricht, die einen tool_result-Block mit der tool_use_id und dem nachgeschlagenen Bautext als Inhalt enthält

Und Claude macht weiter. An diesem Punkt können wir weiterhin Tools aufrufen und Ergebnisse an Claude zurückgeben, bis es hat, was es braucht.

Mehrere Tools: Claude auswählen lassen

Ein Tool ist nützlich, aber der interessante Teil ist, Claude mehrere Tools zu geben und zu beobachten, welches es auswählt und in welcher Reihenfolge.

Stell dir folgendes Szenario vor: Du packst für eine dreitägige Reise nach Denver und möchtest sowohl das heutige Wetter als auch die Vorhersage für die nächsten Tage. Also deklarieren wir zwei Tools statt eines:

typescript
const tools = [
  {
    name: "get_weather",
    description: "Get today's current weather for a city.",
    input_schema: {
      type: "object",
      properties: {
        city: { type: "string", description: "The city to check" }
      },
      required: ["city"]
    }
  },
  {
    name: "get_forecast",
    description: "Get the weather forecast for the next few days for a city.",
    input_schema: {
      type: "object",
      properties: {
        city: { type: "string", description: "The city to check" }
      },
      required: ["city"]
    }
  }
];

Die Schleife ist identisch mit den Agenten-Schleifen, die wir bereits gesehen haben. Das einzig Neue ist eine runTool-Funktion, die anhand des Tool-Namens mit einer switch-Anweisung verteilt — dieser Codeblock ist genau der Ort, an dem dein Code tatsächlich ausgeführt wird:

typescript
function runTool(name, input) {
  switch (name) {
    case "get_weather":
      return getWeather(input.city);
    case "get_forecast":
      return getForecast(input.city);
  }
}

while (true) {
  const response = await client.messages.create({
    model: "claude-sonnet-5",
    max_tokens: 1024,
    messages,
    tools,
  });

  if (response.stop_reason !== "tool_use") {
    // Claude ist fertig – das ist die endgültige Antwort
    break;
  }

  messages.push({ role: "assistant", content: response.content });

  const toolResults = response.content
    .filter((block) => block.type === "tool_use")
    .map((block) => ({
      type: "tool_result",
      tool_use_id: block.id,
      content: runTool(block.name, block.input),
    }));

  messages.push({ role: "user", content: toolResults });
}

Und das ist das ganze Muster. Willst du ein drittes Tool? Füge es dem Array hinzu, füge einen Case zum switch hinzu, und du bist fertig.

Führe das aus, und du wirst sehen, dass Claude get_weather und dann get_forecast aufruft — manchmal in derselben Runde, manchmal nacheinander. Dann antwortet es: Schichten packen, heute Schneeschauer erwarten, im Laufe der Woche wärmer werdend.

Beachte nun, wie Claude gewählt hat. Es hat die Beschreibungen gelesen, deinen Prompt auf „heutiges Wetter" und „die nächsten Tage" abgebildet und für jedes das richtige Tool ausgewählt. Deshalb sind deine Tool-Beschreibungen wirklich wichtig.

Der Tool-Runner: Boilerplate überspringen

Du hast wahrscheinlich schon zwei Warnsignale bei dem bemerkt, was wir gerade geschrieben haben:

  • Das ist eine Menge Code für zwei einfache Abfragen.
  • In einer echten Codebasis möchtest du nicht für jede Funktion, die du hast, JSON-Schemas handschriftlich schreiben. Es ist, als würdest du deinen Code zweimal schreiben.

Hier kommt der Tool-Runner ins Spiel. Er ist in Beta in den Claude SDKs verfügbar: TypeScript, Python, Ruby, C#, Go, Java und PHP. Du definierst jedes Tool einmal, und der Runner übernimmt intern die gesamte Tool-Nutzung/Tool-Ergebnis-Schleife.

In TypeScript beschreibt der empfohlene Helfer des Runners, betaZodTool(), jedes Tool mit einem kurzen Schema, das in Zod geschrieben ist, einer TypeScript-Bibliothek zum Deklarieren und Validieren der Form von Daten. Der Helfer benötigt Zod 3.25.0 oder höher, was dir eine frische Installation liefert:

bash
npm install zod

Dein Code schrumpft auf: das Tool beschreiben, den Prompt senden, auf das Ergebnis warten. Hier ist dieselbe Zwei-Tool-Wetter-Demo, verdrahtet über den Tool-Runner:

typescript
import { betaZodTool } from "@anthropic-ai/sdk/helpers/beta/zod";
import { z } from "zod";

// Verpacke die beiden Lookups, die wir manuell ausgeführt haben, jeweils mit einem kurzen Zod-Schema
const weatherTool = betaZodTool({
  name: "get_weather",
  description: "Get today's current weather for a city.",
  inputSchema: z.object({
    city: z.string().describe("The city to check"),
  }),
  run: async ({ city }) => getWeather(city),
});

const forecastTool = betaZodTool({
  name: "get_forecast",
  description: "Get the weather forecast for the next few days for a city.",
  inputSchema: z.object({
    city: z.string().describe("The city to check"),
  }),
  run: async ({ city }) => getForecast(city),
});

const runner = client.beta.messages.toolRunner({
  model: "claude-sonnet-5",
  max_tokens: 1024,
  messages: [
    {
      role: "user",
      content:
        "I'm packing for a three-day trip to Denver. What's the weather today and over the next few days?",
    },
  ],
  tools: [weatherTool, forecastTool],
});

// Warte auf den Runner, um die finale Nachricht zu erhalten, nachdem sich das Tool-Ping-Pong gelegt hat
const finalMessage = await runner;

Gleiches Szenario, ein Bruchteil des Codes:

  • Keine while-Schleife, kein stop-reason-switch, kein manuelles Zurückschieben von Tool-Ergebnissen in Nachrichten — der Runner übernimmt das alles.
  • Keine handschriftlichen JSON-Schemas, nur ein kurzes Zod-Schema pro Tool, das auch die Eingabe validiert, die Claude sendet.
  • Jede run-Funktion umschließt dieselbe Abfrage, die wir vor einer Minute von Hand ausgeführt haben.
  • Das Abwarten des Runners liefert die endgültige Assistant-Nachricht zurück, sobald sich alles geklärt hat.

Führe es aus, und du erhältst die gleiche Antwort.

Echte Tools umschließen deinen bestehenden Code

Im echten Leben wären deine Tools keine hartcodierten Wetterdaten. Sie würden tatsächliche Funktionen umschließen, die du bereits in deiner Anwendung hast.

Nimm einen Compliance-Review-Agenten: Seine Tools sind dünne Wrapper um lookup_building_code- und search_building_code-Funktionen, die bereits in der Codebasis existieren. Mit dem Tool-Runner umschließt du jede dieser Funktionen in einer kurzen Tool-Definition mit ihrem eigenen Zod-Schema, und der Agent zitiert spezifische Code-Abschnitte in jedem Befund, den er schreibt:

Eine Compliance-Review-App, die einen strukturellen Bericht neben Agenten-Befunden zeigt, wobei jeder markierte Punkt den spezifischen Bauvorschriftsabschnitt zitiert, den er überprüft hat

Zusammenfassung

  • Tools geben Claude Zugriff auf deine Systeme. Ein Tool ist eine Funktion, die du definierst und zur Verfügung stellst; Claude entscheidet, wann es sie aufruft, und dein Code führt sie aus.
  • Tools sind JSON-Schemas mit einem Namen, einer Beschreibung und einem Input-Schema, die im Request als ein tools-Array übergeben werden.
  • Schreibe spezifische Beschreibungen. Vage Beschreibungen sind der Hauptgrund, warum Agenten fehlzünden.
  • stop_reason: "tool_use" ist dein Signal, das Tool auszuführen und das Ergebnis als Tool-Ergebnis zurückzugeben.
  • Bei mehreren Tools verteile anhand des Tool-Namens. Ein Tool hinzuzufügen bedeutet, es dem Array hinzuzufügen und einen Case hinzuzufügen.
  • Der Tool-Runner des SDK (in Beta über die Claude SDKs verfügbar) übernimmt die gesamte Schleife, und in TypeScript ist jedes Tool eine kurze Definition mit einem Zod-Schema. Oder du kannst die Schleife selbst ausführen.
  • Du führst aus, oder du delegierst die Schleife. Am äußersten Ende dieses Spektrums delegieren verwaltete Agenten den gesamten Agenten an Anthropic.