---
title: "Werkzeuge"
description: "Ein Tool-Modul läuft auf jedem Agent-Harness. beeuni.yaml listet die Beeuni-Tools und die projektspezifischen Tools auf, und die tools-Liste jedes Agents legt fest, wer sie aufrufen darf."
---

Ein Tool ist eine Funktion, die das Modell während eines Turns aufruft. Eine
[Session](/docs/de/work/sessions) hat drei Arten von Tools, auf beiden
[Harnesses](/docs/de/work/harnesses), Standard-Harness und Experimental-Harness:

| Art | Namen | Implementiert von |
| --- | --- | --- |
| Harness-Tools | `bash`, `read`, `write`, `edit`, `glob`, `grep`, `task`, `question`, … | Dem Harness. |
| Beeuni-Tools | `web_search`, `image_search`, `scrape_webpage`, `memory`, `show` | Beeuni. `beeuni.yaml` führt jedes als `<name>: beeuni:<name>` auf. Ein Projekt ohne Schlüssel `tools:` erhält alle fünf. |
| Projekt-Tools | Jeder von dir deklarierte Name | Deinem Projekt: ein Modul, deklariert unter `tools:` in `beeuni.yaml`. |

Beeuni-Tools und Projekt-Tools sind harness-unabhängig. Der Sandbox-Daemon lädt
für jedes Tool ein Modul und führt es für beide Harnesses mit demselben Namen,
denselben Argumenten und derselben Ausgabe aus. Experimental-Harness ruft das Modul im Prozess des Daemons auf. Standard-Harness
ruft es über ein vom Daemon geschriebenes Plugin auf, das jeden Aufruf an den Daemon weiterleitet. Ein Modul importiert niemals ein Harness-Paket.

## Beeuni-Tools in beeuni.yaml

Ein neues Projekt führt die fünf Beeuni-Tools unter `tools:` auf:

```yaml
tools:
  web_search: beeuni:web_search      # maintained by Beeuni, updated automatically
  image_search: beeuni:image_search
  scrape_webpage: beeuni:scrape_webpage
  memory: beeuni:memory
  show: beeuni:show
  # lookup_order: tools/lookup_order.ts   # your own tool: a module in your repo
```

`beeuni:<name>` bedeutet: das von Beeuni gepflegte Tool. Eine Korrektur daran erreicht jedes
Projekt, das es aufführt, ohne dass das Projekt geändert werden muss.

<a id="which-beeuni-tools-a-session-gets"></a>

### Welche Beeuni-Tools eine Session erhält

| `beeuni.yaml` | Die Session erhält |
| --- | --- |
| Kein Schlüssel `tools:`, weder in der Stammdatei noch in einer [importierten](/docs/de/project/manifest#imports) Datei | Alle fünf Beeuni-Tools. Ein Projekt, das vor Einführung dieser Liste erstellt wurde, behält sie alle. |
| Einen Schlüssel `tools:`, auch einen leeren (`tools: {}` oder `tools:`, wenn alle Zeilen gelöscht wurden) | Nur die Beeuni-Tools, die darin als `beeuni:<name>` oder als Modul aufgeführt sind, das das Tool ersetzt. |

Die projektspezifischen Tools werden in beiden Fällen geladen.

<a id="see-what-a-session-gets"></a>

### Anzeigen, welche Tools eine Session erhält

`beeuni tools ls` liest `beeuni.yaml` und seine Importe und gibt jedes Tool aus, das eine
Session erhält, gefolgt von den Beeuni-Tools, die das Projekt entfernt hat:

```text
$ beeuni tools ls
NAME            KIND                 SOURCE
web_search      beeuni (overridden)  tools/web_search.ts
scrape_webpage  beeuni               beeuni:scrape_webpage
memory          beeuni               beeuni:memory
show            beeuni               beeuni:show
lookup_order    project              tools/lookup_order.ts

Removed Beeuni tools: image_search
Add `<name>: beeuni:<name>` under `tools:` to get one back.
```

| Art | Bedeutung |
| --- | --- |
| `beeuni` | Ein Beeuni-Tool, aufgeführt als `beeuni:<name>` (oder alle, wenn kein Schlüssel `tools:` vorhanden ist). |
| `beeuni (overridden)` | Ein Beeuni-Toolname mit Modulpfad: Stattdessen wird das Modul des Projekts ausgeführt. |
| `project` | Ein projektspezifisches Tool. |

`beeuni tools ls --json` gibt `{ manifest, tools_key, tools: [{ name, kind, source }], removed }` aus.

<a id="remove-a-beeuni-tool"></a>

### Ein Beeuni-Tool entfernen

Lösche seine Zeile unter `tools:`. Jeder Agent des Projekts verliert das Tool,
auf beiden Harnesses und in jeder Session, die nach dem Mergen des Änderungsauftrags startet.
Wenn du ein Tool nur für einen Agent entfernen willst, verwende stattdessen
[`agents.<name>.tools`](#who-may-use-which-tool).

In einer Session eines Projekts, das ein Tool entfernt hat:

- **Standard-Harness** bietet dem Modell das Tool nicht an.
- **Experimental-Harness** bietet das Tool nicht an. Ein Aufruf schlägt mit `Tool show not found` fehl
  (für `show`).
- **Der Daemon** antwortet auf `POST /beeuni/tools/<name>` mit `404` und
  `no tool named <name> is loaded`.
- **Ein Skill, der das Tool nennt, wird weiterhin geladen.** Zum Beispiel nennt `beeuni-memory`
  `memory`. Das Modell liest den Skill, findet kein solches Tool und verwendet
  andere Tools: Ohne `memory` liest und bearbeitet es mit den Datei-Tools die Dateien unter `memory/`.

<a id="change-a-beeuni-tool-eject"></a>

### Ein Beeuni-Tool ändern: auskoppeln

`beeuni tools eject <name>` erstellt eine eigene Kopie eines Beeuni-Tools im Projekt:

```text
$ beeuni tools eject web_search
  ✓  Ejected web_search
  wrote   tools/web_search.ts (the Beeuni source, now the project's to change)
  set     beeuni.yaml: tools.web_search: tools/web_search.ts

Next:
  1. Edit tools/web_search.ts. Keep the default export: { description, parameters, execute(args, context) }.
  2. beeuni validate
  3. git add tools/web_search.ts beeuni.yaml && git commit -m "Own the web_search tool"
  4. Open a change request: git push origin HEAD && beeuni cr open --title "Own the web_search tool"
Sessions load the copy after the change request merges.
```

- Es schreibt den Beeuni-Quellcode – dieselben Bytes, die die Sandbox ausführt – nach
  `tools/<name>.ts`. Die Datei importiert nur `node:*`-Module und liest
  `BEEUNI_API_URL`, `BEEUNI_TOKEN` sowie Provider-Schlüssel aus `context.env`, sodass sie
  direkt ausführbar ist.
- Es setzt `<name>: tools/<name>.ts` in `beeuni.yaml`, und zwar in der Datei,
  die den Eintrag deklariert (der Stammdatei oder einer importierten Datei). Alle anderen Zeilen und
  Kommentare bleiben erhalten. Die geänderte Zeile endet mit `# ejected from beeuni:<name>`.
- Wenn kein Schlüssel `tools:` vorhanden ist, wird einer erstellt und die übrigen vier Beeuni-Tools werden als `beeuni:<name>` aufgeführt, sodass durch das Auskoppeln nichts entfernt wird.
- Der Vorgang wird abgebrochen, wenn `tools/<name>.ts` vorhanden ist oder das Tool bereits auf ein anderes Modul verweist. `--force` überschreibt.
- Ein Name, der kein Beeuni-Tool ist, wird abgelehnt.

Die Kopie gehört dir. Beeuni aktualisiert sie nicht mehr. Um zum gepflegten Tool zurückzukehren,
setze die Zeile wieder auf `<name>: beeuni:<name>` und lösche die Datei.

<a id="override-without-eject"></a>

### Ohne Auskoppeln überschreiben

Ein Beeuni-Toolname mit Modulpfad ersetzt das Beeuni-Tool auf jedem
Harness:

```yaml
tools:
  web_search: integrations/search/web_search.ts
```

<a id="the-web-ui-views"></a>

### Ansichten der Web-UI

Die Web-UI hat für jedes Beeuni-Tool eine Ansicht, die anhand des Toolnamens ausgewählt wird. Die
Ansichten `show` und `memory` lesen die Argumente des Aufrufs (`type`, `path`, `url`,
`content`, `items`; `command`, `path`). Die Ansichten `web_search`, `image_search` und
`scrape_webpage` lesen das Ausgabe-JSON. Eine geänderte Kopie mit demselben
Namen muss diese Argumente und diese Ausgabeform beibehalten, sonst zeigt die UI die unverarbeitete
Ausgabe.

<a id="validation"></a>

### Validierung

`beeuni validate` prüft die Liste:

- `<name>` in `beeuni:<name>` muss ein Beeuni-Tool sein, und der Schlüssel muss mit
  ihm übereinstimmen. `web_search: beeuni:image_search` ist ein Fehler:
  ``must be `beeuni:web_search` (the Beeuni tool) or a repo-relative path to a .ts or .js module (e.g. `tools/web_search.ts`) that replaces it.``
- Ein Schlüssel `tools:`, der kein Beeuni-Tool aufführt, löst eine Warnung aus:
  ``Sessions of this project get no Beeuni tool (web_search, image_search, scrape_webpage, memory, show). Add `<name>: beeuni:<name>` to keep one.``
  Sie weist auf ein Projekt hin, das sein erstes eigenes Tool hinzugefügt und versehentlich die fünf Beeuni-Tools entfernt hat.
- Wenn `tools` eines Agents ein Beeuni-Tool nennt, das das Projekt nicht lädt, wird eine
  Warnung ausgegeben: ``"show" is a Beeuni tool this project does not load: add `show: beeuni:show` under the top-level `tools`, or remove it here.``

Die [Manifest-Referenz](/docs/de/project/manifest#tools) enthält alle Regeln.

<a id="write-a-project-tool"></a>

## Ein Projekt-Tool schreiben

```ts
// tools/lookup_order.ts
export default {
  description: 'Look up an order by id. Returns its status and carrier.',
  parameters: {
    type: 'object',
    properties: {
      id: { type: 'string', description: 'The order id, e.g. "A-1042"' },
      include_items: { type: 'boolean', description: 'Also list the items' },
    },
    required: ['id'],
  },
  async execute(args, context) {
    const response = await fetch(`https://orders.example.com/v1/orders/${args.id}`, {
      headers: { authorization: `Bearer ${context.env.ORDERS_API_KEY}` },
      signal: context.signal,
    })
    if (!response.ok) throw new Error(`orders API answered ${response.status}`)
    return await response.json()
  },
}
```

```yaml
# beeuni.yaml
tools:
  web_search: beeuni:web_search
  # … the other Beeuni tools you keep
  lookup_order: tools/lookup_order.ts
```

Der Standardexport ist ein einfaches Objekt:

| Feld | Regel |
| --- | --- |
| `description` | Nichtleere Zeichenfolge. Das Modell liest sie, um zu entscheiden, wann das Tool aufgerufen werden soll. |
| `parameters` | [JSON Schema](https://json-schema.org) der Argumente, `type: 'object'`. Das Modell erhält es unverändert; führe erforderliche Argumente also unter `required` auf. Beeuni validiert die Argumente nicht dagegen. |
| `execute(args, context)` | Gibt eine Zeichenfolge oder einen beliebigen JSON-Wert zurück (als eingerücktes JSON gesendet). Darf `async` sein. Ein ausgelöster Fehler ist der Fehler des Tools; das Modell liest seine Meldung. |

`context` enthält:

| Feld | Beschreibung |
| --- | --- |
| `sessionId` | Die Beeuni-Session, zu der der Aufruf gehört. |
| `agent` | Der Agent, der den Aufruf getätigt hat. |
| `directory` | Der Checkout des Projekts, `/workspace`. Löse relative Pfade relativ dazu auf. |
| `env` | Die Umgebung der Box sowie die [Geheimnisse](/docs/de/project/secrets), die dieser Agent aktuell erhält. Ein Geheimnis liest du mit `context.env.NAME`: Ein Geheimnis, das nach dem Start der Box geändert wurde, ist in `context.env` enthalten, nicht in `process.env`. |
| `signal` | Ein `AbortSignal`, das abgebrochen wird, wenn der Nutzer den Turn beendet. Übergib es an `fetch`. |

- **Ausgabegröße.** Eine Ausgabe mit mehr als 50 KB oder 2.000 Zeilen wird vollständig in einer Datei im temporären Verzeichnis der Sandbox gespeichert. Das Modell erhält den Anfang, die Größe und den Dateipfad. Gib zurück, was das Modell benötigt, keinen unbearbeiteten Dump.
- **Fehler.** Ein ausgelöster Fehler beendet den Aufruf, und das Modell liest die Fehlermeldung. Formuliere eine Meldung, aus der hervorgeht, was geändert werden muss.
- **Importe.** Ein Modul darf `node:*`-Module, Bun-APIs und relative Dateien importieren. Ein Paket wird aus einem `node_modules` neben oder oberhalb des Moduls aufgelöst. Die Sandbox installiert keine Pakete für ein Tool, und ein
  [Config-Release](/docs/de/work/runtime#config-convergence) enthält nur Dateien, die Git verfolgt. Verwende `fetch` für HTTP-APIs. TypeScript wird ohne Build-Schritt ausgeführt.
- **Fehler beim Laden.** Ein Modul, das nicht geladen werden kann (fehlende Datei, kein Standardexport, ein `parameters`, das kein Objektschema ist, ein Fehler beim Import oder ein nicht auflösbares Paket), wird ausgelassen; die übrigen Tools werden weiterhin geladen.
  Der Daemon protokolliert `[tools] project tools that did not load` mit dem Grund für jedes Tool.

<a id="parameters-with-zod"></a>

### `parameters` mit zod

zod 4 erzeugt dasselbe JSON Schema:

```ts
import { z } from 'zod'

export default {
  description: 'Look up an order by id.',
  parameters: z.toJSONSchema(z.object({ id: z.string().describe('The order id') })),
  async execute(args) {
    return `order ${args.id}: shipped`
  },
}
```

Dieses Modul wird nur geladen, wenn `zod` aus einem `node_modules` im Checkout aufgelöst werden kann, in dem die Session läuft. Andernfalls schlägt es mit `Cannot find package 'zod'` fehl.
Um das Schema mit zod zu schreiben und als einfaches JSON Schema bereitzustellen, gib es einmal aus und kopiere die Ausgabe nach `parameters`:

```bash
bun -e "import { z } from 'zod'; console.log(JSON.stringify(z.toJSONSchema(z.object({ id: z.string() })), null, 2))"
```

<a id="example-call-an-http-api-with-a-project-secret"></a>

### Beispiel: Eine HTTP-API mit einem Projektgeheimnis aufrufen

Speichere den Schlüssel als Projektgeheimnis. Der Befehl liest den Wert von stdin:

```bash
beeuni secrets set WEATHER_API_KEY=-
```

Gewähre den Agents, die das Tool aufrufen, Zugriff auf das Geheimnis. Der `beeuni`-Agent des Startprojekts hat `secrets: all`. Ein Agent mit eingeschränktem Umfang führt es auf: `secrets: [WEATHER_API_KEY]`.

Schreibe das Modul:

```ts
// tools/weather_now.ts
export default {
  description: 'Current weather for a city: temperature in °C and conditions.',
  parameters: {
    type: 'object',
    properties: { city: { type: 'string', description: 'City name, e.g. "Berlin"' } },
    required: ['city'],
  },
  async execute(args, context) {
    const key = context.env.WEATHER_API_KEY
    if (!key) throw new Error('WEATHER_API_KEY is not set: run `beeuni secrets set WEATHER_API_KEY=-` and grant it to this agent.')
    const url = `https://api.weather.example.com/v1/current?city=${encodeURIComponent(args.city)}`
    const response = await fetch(url, { headers: { authorization: `Bearer ${key}` }, signal: context.signal })
    if (!response.ok) throw new Error(`weather API answered ${response.status}: ${await response.text()}`)
    const data = await response.json()
    return { city: args.city, temperature_c: data.temp_c, conditions: data.conditions }
  },
}
```

Deklariere es:

```yaml
tools:
  # … the Beeuni tools you keep
  weather_now: tools/weather_now.ts
```

<a id="example-override-websearch"></a>

### Beispiel: `web_search` überschreiben

`beeuni tools eject web_search` schreibt `tools/web_search.ts` und setzt
`web_search: tools/web_search.ts`. Ändere anschließend die Kopie. Um beispielsweise nur Ergebnisse von einer Website zu erhalten, füge die Website vor der Anfrage jeder Abfrage in `execute` hinzu:

```ts
// tools/web_search.ts, inside execute()
const queries = String(args.query ?? '').split('|||').map((query) => query.trim()).filter(Boolean)
  .map((query) => `site:docs.example.com ${query}`)
```

Behalte den Namen, die Argumente und das Ausgabe-JSON bei, damit Skills, die `web_search` nennen, und die Ansicht der Web-UI weiterhin funktionieren.

<a id="test-a-tool"></a>

### Ein Tool testen

`beeuni validate` prüft den Namen, den Pfad, eine fehlende Datei und die Werte von
`beeuni:`. `beeuni tools ls` zeigt, welche Tools eine Session erhält.

Führe anschließend einen Commit und Push durch und öffne einen Änderungsauftrag. Starte nach dem Mergen eine Session und fordere einen Aufruf mit echten Argumenten an:

```bash
beeuni sessions new --wait --prompt "Call the weather_now tool once with city Berlin and print its output."
```

Ein Tool, das nicht geladen wird, wird dem Modell nicht angeboten. Ein Tool, das einen Fehler auslöst,
antwortet mit seiner Fehlermeldung. `beeuni sessions log <id>` gibt die Nachrichten der Session aus, einschließlich jedes Tool-Aufrufs und seines Status.

<a id="declare-tools"></a>

## Tools deklarieren

`tools:` ordnet jeden Toolnamen seinem Modul zu oder einen Beeuni-Toolnamen `beeuni:<name>`. Du kannst den Ordner eines Moduls frei wählen.

```yaml
tools:
  web_search: beeuni:web_search
  memory: beeuni:memory
  lookup_order: tools/lookup_order.ts
  crm_note: integrations/crm/note.ts
```

- Ein Name muss in snake_case und höchstens 64 Zeichen lang sein: `^[a-z][a-z0-9_]{0,63}$`.
- Ein Harness-Toolname ist ein Fehler. Ein Beeuni-Toolname akzeptiert `beeuni:<name>` oder einen Modulpfad; das Modul ersetzt das Beeuni-Tool auf jedem Harness.
- Ein Pfad muss relativ zum Repository sein und mit `.ts`, `.js`, `.mts`, `.mjs`, `.cts` oder
  `.cjs` enden.
- Eine unter [`imports:`](/docs/de/project/manifest#imports) aufgeführte Datei darf Tools deklarieren. Wird ein Name in zwei Dateien deklariert, ist das ein Fehler. Ein Schlüssel `tools:` in einer importierten Datei zählt für die Auswahlregel als Schlüssel `tools:`.

[Die Manifest-Referenz](/docs/de/project/manifest#tools) enthält alle Regeln.

<a id="who-may-use-which-tool"></a>

## Wer welches Tool verwenden darf

`agents.<name>.tools` legt fest, welche Tools das Modell eines Agents sieht. Sie führt Harness-, Beeuni- und Projekt-Tools gleichermaßen auf.

```yaml
agents:
  beeuni:
    tools: all                                    # every tool (the default)
  researcher:
    tools: [read, grep, web_search, lookup_order] # only these
  support:
    tools:
      exclude: [bash, write, edit]                # every tool but these
  greeter:
    tools: none                                    # no tool
```

| Wert | Der Agent erhält |
| --- | --- |
| weggelassen oder `all` | Alle Tools. |
| `none` | Kein Tool. |
| eine Liste | Nur die aufgeführten Tools. Eine Liste mit `*` ist `all`. |
| `{ exclude: [...] }` | Alle Tools außer den aufgeführten. |
| `{ bash: false, … }` | Die frühere Map-Form: `false` entfernt ein Tool. |

- `tools` bestimmt die Sichtbarkeit. Die Regeln für `permission` des Agents entscheiden weiterhin, ob ein Aufruf erlaubt, nachzufragen oder abzulehnen ist. Ein Tool, das nicht in der Liste steht, wird dem Modell verborgen und bei einem Aufruf abgelehnt.
- Eine Agent-Liste kann kein Beeuni-Tool hinzufügen, das das Projekt nicht lädt. Führe es zuerst unter `tools:` auf oberster Ebene auf.
- Ein mit dem Tool `task` gestarteter Subagent erhält auf Experimental-Harness nur die Tools, die sowohl seine eigene Liste als auch die Liste des Session-Agents zulassen. Auf Standard-Harness erhält er die Tools aus seiner eigenen Liste: Standard-Harness wendet die Regeln eines Agents nur auf diesen Agent an.
  Damit ein Agent keine Delegation ausführen kann, lass `task` aus seiner Liste weg.
- [Connector](/docs/de/connect/connectors)-Tools folgen `agents.<name>.connectors`, nicht dieser Liste.
- `beeuni validate` warnt vor einem Namen, der weder ein Harness-, Beeuni- noch ein Projekt-Tool ist, und vor einem Beeuni-Tool, das das Projekt nicht lädt. Ein Tippfehler in einer `exclude`-Liste lässt das echte Tool aktiviert.

In Standard-Harness umfasst `bash` auch die Tools `pty_*` des Terminal-Plugins. Außerdem verwenden `write`, `edit` und `apply_patch` dieselbe Berechtigung: Wenn eines aufgeführt wird, werden alle drei angezeigt; wenn eines ausgeschlossen wird, werden alle drei verborgen. Experimental-Harness hat separate Tools `write` und `edit`.

<a id="when-a-change-takes-effect"></a>

## Wann eine Änderung wirksam wird

Eine Session lädt ihre Tools beim Start ihrer Laufzeitumgebung. Eine Änderung wird nach dem Mergen des Änderungsauftrags wirksam: Neue Sessions laden sie; bei [Config-Releases](/docs/de/work/runtime#config-convergence) lädt eine laufende Session sie bei der nächsten Konvergenz. Auf Experimental-Harness startet eine Änderung an einem Projekt-Tool oder an der Liste der Beeuni-Tools die Laufzeitumgebung direkt neu, sofern gerade kein Turn läuft; das Gespräch wird fortgesetzt.

## Tools in `harnesses/opencode/tools/`

Standard-Harness lädt weiterhin benutzerdefinierte Tools aus seinem Konfigurationsverzeichnis. Experimental-Harness tut das nicht.
Projekte, die vor den gehosteten Tools erstellt wurden, enthalten dort Kopien der Beeuni-Tools
(`web_search.ts`, `memory.ts`, …).

- In Standard-Harness hat ein Tool in diesem Ordner Vorrang vor dem gehosteten Tool mit demselben Namen. Daher behält ein Projekt seine Kopie, bis es sie löscht. Lösche die Kopien der Beeuni-Tools: Der Daemon stellt die Tools bereit, die `beeuni.yaml` aufführt, auf beiden Harnesses.
- Damit ein Standard-Harness-Tool auf beiden Harnesses ausgeführt wird, verschiebe es aus dem Ordner, ersetze `tool({ description, args, execute })` durch ein einfaches Objekt, dessen `parameters` JSON Schema ist, lies Geheimnisse aus `context.env` und deklariere es unter `tools:`.
