Imperative API · für Entwicklung

Tools in JavaScript anmelden

Die imperative API meldet Werkzeuge über navigator.modelContext.registerTool() an. Jedes Werkzeug hat einen Namen, eine Beschreibung, ein JSON Schema für seine Eingabe und eine execute-Funktion, die den Aufruf ausführt und ein Ergebnis zurückgibt. Sie ist der Weg für alles, was kein Formular ist.

Alle Beispiele auf dieser Seite entsprechen dem Stand vom . Was sich zuletzt geändert hat, steht im Changelog.

Ein Werkzeug anmelden

Das Grundmuster. Mehr braucht ein funktionierendes Werkzeug nicht.

JavaScript
navigator.modelContext.registerTool({
  name: "addTodo",
  description: "Add a new item to the todo list. Returns the created todo with its ID.",
  inputSchema: {
    type: "object",
    properties: {
      text: {
        type: "string",
        description: "The text content of the todo item"
      }
    },
    required: ["text"]
  },
  execute: ({ text }) => {
    const todo = { id: nextId++, text, done: false };
    todos.push(todo);
    renderTodos();
    return { content: [{ type: "text", text: JSON.stringify(todo) }] };
  }
});

Die vier Bestandteile, und was jeder bewirkt:

FeldRolleWirkung
name Pflicht Technischer Bezeichner. Darüber wird das Werkzeug später auch wieder abgemeldet.
description Pflicht Entscheidet, ob der Agent das Werkzeug wählt. Beschreiben Sie, was es kann, nicht was es nicht soll.
inputSchema Pflicht JSON Schema. Beschreibt Felder, Typen und Pflichtangaben der Eingabe.
execute Pflicht Führt den Aufruf aus. Gibt ein Ergebnis mit content-Liste zurück.
annotations Empfohlen Hinweise zum Verhalten, siehe unten. Teilweise Pflicht.

execute bekommt immer ein AbortSignal

Seit Chrome 153.0.8009.0 erhält execute als zweites Argument ein Objekt mit einem signal. Reichen Sie es an alles weiter, was abbrechbar ist, vor allem an fetch.

JavaScript
navigator.modelContext.registerTool({
  name: "searchProducts",
  description: "Search the product catalogue and return matching items.",
  inputSchema: {
    type: "object",
    properties: {
      query: { type: "string", description: "Free-text search query" }
    },
    required: ["query"]
  },
  execute: async ({ query }, { signal }) => {
    // Das Signal weiterreichen: dann bricht auch der laufende Request ab.
    const antwort = await fetch(`/api/search?q=${encodeURIComponent(query)}`, { signal });
    const treffer = await antwort.json();
    return { content: [{ type: "text", text: JSON.stringify(treffer) }] };
  }
});

inputSchema: String oder Objekt

Hier lohnt sich Vorsicht. Mit Chrome 154.0.8014.0 sollte RegisteredTool#inputSchema vom String zum Objekt wechseln. Die Änderung wurde ausgeliefert und kurz darauf zurückgenommen. Wer getTools() auswertet, sollte deshalb beide Formen vertragen.

JavaScript
// inputSchema kann String oder Objekt sein. Beides vertragen:
function schemaLesen(schema) {
  return typeof schema === "string" ? JSON.parse(schema) : schema;
}

const werkzeuge = await navigator.modelContext.getTools();
for (const werkzeug of werkzeuge) {
  const felder = schemaLesen(werkzeug.inputSchema).properties;
  console.log(werkzeug.name, Object.keys(felder));
}

Der Generator im Playground baut Ihnen ein passendes Schema aus einem ausgefüllten Formular, samt fertigem registerTool-Aufruf zum Kopieren.

Beleg: PR #241 im Spec-Repo

Annotations: was der Agent über das Werkzeug wissen muss

Annotations beschreiben nicht die Eingabe, sondern das Verhalten. Zwei davon sind wichtig.

JavaScript
navigator.modelContext.registerTool({
  name: "listComments",
  description: "List the comments below the current article.",
  inputSchema: { type: "object", properties: {} },
  annotations: {
    // Liest nur, verändert nichts: der Agent darf ohne Rückfrage aufrufen.
    readOnlyHint: true,
    // Gibt fremden Text zurück. Ohne diese Angabe wäre die Rückgabe
    // eine Einfallstür für Prompt Injection.
    untrustedContentHint: true
  },
  execute: () => ({
    content: [{ type: "text", text: JSON.stringify(kommentareLesen()) }]
  })
});

getTools und executeTool

Beide kamen mit dem Origin Trial dazu. getTools() liefert die aktuell angemeldeten Werkzeuge, executeTool() ruft eines davon auf. Für die eigene Seite ist beides vor allem zum Testen nützlich: Sie können prüfen, was ein Agent sehen würde, ohne einen Agenten zu haben.

Fürs Debuggen im Browser gibt es zusätzlich die Erweiterung Model Context Tool Inspector. Sie zeigt registrierte Werkzeuge an und führt sie auf Zuruf aus.

Lifecycle in Single-Page-Anwendungen

In einer SPA gehören Werkzeuge zu einer Ansicht, nicht zur ganzen Anwendung. Ein Werkzeug addToCart ergibt auf der Produktseite Sinn und im Impressum nicht. Melden Sie es beim Betreten an und beim Verlassen ab.

JavaScript
// In einer SPA gehören Tools zur Ansicht, nicht zur Anwendung.
function ansichtBetreten() {
  navigator.modelContext.registerTool(warenkorbWerkzeug);
}

function ansichtVerlassen() {
  navigator.modelContext.unregisterTool("addToCart");
  // Achtung: unregisterTool beendet keine laufende Ausführung mehr.
  // Wer das braucht, bricht selbst ab, siehe AbortSignal oben.
}

Was sich in der Praxis bewährt

Sollen wir das an Ihrer Anwendung durchgehen?

Welche Funktionen sich als Werkzeug lohnen, welche eine Bestätigung brauchen und wie der Lifecycle in Ihrem Frontend aussieht: das klären wir am besten an Ihrem Code.

Zu den Seminaren oder direkt: post@alinr.com