# Strumenti

Un modulo di strumenti funziona con ogni harness per agenti. beeuni.yaml elenca gli strumenti Beeuni e quelli del progetto, mentre l’elenco degli strumenti di ciascun agente stabilisce chi può usarli.

Canonical page: https://beeuni.ai/docs/it/project/tools

Uno strumento è una funzione che il modello chiama durante un turno. Una
[sessione](/docs/it/work/sessions) ha tre tipi di strumenti, su entrambi gli
[harness](/docs/it/work/harnesses), harness standard e harness sperimentale:

| Tipo | Nomi | Implementato da |
| --- | --- | --- |
| Strumenti dell'harness | `bash`, `read`, `write`, `edit`, `glob`, `grep`, `task`, `question`, … | L'harness. |
| Strumenti Beeuni | `web_search`, `image_search`, `scrape_webpage`, `memory`, `show` | Beeuni. `beeuni.yaml` elenca ciascuno come `<name>: beeuni:<name>`. Un progetto senza la chiave `tools:` li riceve tutti e cinque. |
| Strumenti del progetto | Qualsiasi nome dichiari | Il progetto: un modulo dichiarato sotto `tools:` in `beeuni.yaml`. |

Gli strumenti Beeuni e quelli del progetto sono indipendenti dall'harness. Il daemon della sandbox carica un modulo per ogni strumento e lo esegue su entrambi gli harness, con lo stesso nome, gli stessi argomenti e lo stesso output. harness sperimentale chiama il modulo nel processo del daemon. harness standard lo chiama tramite un plugin scritto dal daemon, che inoltra ogni chiamata al daemon. Un modulo non importa mai un pacchetto dell'harness.

<a id="beeuni-tools-in-beeuniyaml"></a>

## Strumenti Beeuni in beeuni.yaml

Un nuovo progetto elenca i cinque strumenti Beeuni sotto `tools:`:

```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>` significa che lo strumento è gestito da Beeuni. Una correzione viene applicata a ogni progetto che lo elenca, senza modifiche al progetto.

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

### Quali strumenti Beeuni riceve una sessione

| `beeuni.yaml` | Strumenti ricevuti dalla sessione |
| --- | --- |
| Nesbeeuni chiave `tools:`, nel file radice o in qualsiasi file [importato](/docs/it/project/manifest#imports) | Tutti e cinque gli strumenti Beeuni. Un progetto creato prima che esistesse questo elenco li mantiene tutti. |
| Una chiave `tools:`, anche vuota (`tools: {}` oppure `tools:` con tutte le righe eliminate) | Solo gli strumenti Beeuni elencati, come `beeuni:<name>` o come modulo che sostituisce lo strumento. |

Gli strumenti propri del progetto vengono caricati in entrambi i casi.

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

### Vedere quali strumenti riceve una sessione

`beeuni tools ls` legge `beeuni.yaml` e i file importati, quindi stampa ogni strumento ricevuto da una sessione e gli strumenti Beeuni rimossi dal progetto:

```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.
```

| Tipo | Significato |
| --- | --- |
| `beeuni` | Uno strumento Beeuni, elencato come `beeuni:<name>` (o tutti, se manca la chiave `tools:`). |
| `beeuni (overridden)` | Nome di uno strumento Beeuni con il percorso di un modulo: viene eseguito il modulo del progetto. |
| `project` | Uno strumento del progetto. |

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

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

### Rimuovere uno strumento Beeuni

Elimina la relativa riga sotto `tools:`. Tutti gli agenti del progetto perdono lo strumento, su entrambi gli harness, in ogni sessione avviata dopo l'unione della richiesta di modifica. Per impedire a un solo agente di usare uno strumento, usa [`agents.<name>.tools`](#who-may-use-which-tool).

In una sessione di un progetto che ha rimosso uno strumento:

- **harness standard** non offre lo strumento al modello.
- **harness sperimentale** non offre lo strumento. Una chiamata non riuscita restituisce `Tool show not found` (per `show`).
- **Il daemon** risponde a `POST /beeuni/tools/<name>` con `404` e `no tool named <name> is loaded`.
- **Una skill che nomina lo strumento viene comunque caricata.** Per esempio, `beeuni-memory` nomina `memory`. Il modello legge la skill, non trova lo strumento e ne usa altri: senza `memory` legge e modifica i file sotto `memory/` con gli strumenti per i file.

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

### Modificare uno strumento Beeuni: eject

`beeuni tools eject <name>` crea una copia di uno strumento Beeuni nel progetto:

```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.
```

- Scrive in `tools/<name>.ts` il sorgente Beeuni, gli stessi byte eseguiti dalla sandbox. Il file importa solo moduli `node:*` e legge `BEEUNI_API_URL`, `BEEUNI_TOKEN` e le chiavi del provider da `context.env`, quindi è subito eseguibile.
- Imposta `<name>: tools/<name>.ts` in `beeuni.yaml`, nel file che dichiara la voce (il file radice o un file importato). Tutte le altre righe e i commenti restano invariati. La riga modificata termina con `# ejected from beeuni:<name>`.
- Se manca la chiave `tools:`, la crea ed elenca gli altri quattro strumenti Beeuni come `beeuni:<name>`, così l'eject non rimuove nulla.
- Si rifiuta di procedere se esiste `tools/<name>.ts` o se lo strumento rimanda già a un altro modulo. `--force` sovrascrive.
- Si rifiuta di usare un nome che non sia quello di uno strumento Beeuni.

La copia è tua. Beeuni non la aggiorna harness sperimentaleù. Per tornare allo strumento gestito, reimposta la riga su `<name>: beeuni:<name>` ed elimina il file.

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

### Sovrascrivere senza eject

Un nome di strumento Beeuni associato al percorso di un modulo sostituisce lo strumento Beeuni su ogni harness:

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

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

### Le viste dell'interfaccia web

L'interfaccia web ha una vista per ogni strumento Beeuni, selezionata in base al nome dello strumento. Le viste `show` e `memory` leggono gli argomenti della chiamata (`type`, `path`, `url`, `content`, `items`; `command`, `path`). Le viste `web_search`, `image_search` e `scrape_webpage` leggono il JSON di output. Una copia modificata che mantiene lo stesso nome deve mantenere gli stessi argomenti e la stessa struttura dell'output, altrimenti l'interfaccia mostra l'output grezzo.

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

### Convalida

`beeuni validate` controlla l'elenco:

- `<name>` in `beeuni:<name>` deve essere uno strumento Beeuni e la chiave deve corrispondere. `web_search: beeuni:image_search` è un errore:
  ``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.``
- Una chiave `tools:` che non elenca alcuno strumento Beeuni genera un avviso:
  ``Sessions of this project get no Beeuni tool (web_search, image_search, scrape_webpage, memory, show). Add `<name>: beeuni:<name>` to keep one.``
  Serve a rilevare un progetto che aggiunge il primo strumento proprio ed elimina per errore i cinque strumenti predefiniti.
- Un agente il cui `tools` nomina uno strumento Beeuni che il progetto non carica genera un avviso: ``"show" is a Beeuni tool this project does not load: add `show: beeuni:show` under the top-level `tools`, or remove it here.``

Il [riferimento del manifest](/docs/it/project/manifest#tools) contiene tutte le regole.

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

## Scrivere uno strumento del progetto

```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
```

L'esportazione predefinita è un semplice oggetto:

| Campo | Regola |
| --- | --- |
| `description` | Stringa non vuota. Il modello la legge per decidere quando chiamare lo strumento. |
| `parameters` | [JSON Schema](https://json-schema.org) degli argomenti, `type: 'object'`. Il modello lo riceve così com'è, quindi elenca gli argomenti obbligatori in `required`. Beeuni non convalida gli argomenti rispetto allo schema. |
| `execute(args, context)` | Restituisce una stringa o un qualsiasi valore JSON (inviato come JSON indentato). Può essere `async`. Un errore generato è l'errore dello strumento e il modello ne legge il messaggio. |

`context` contiene:

| Campo | Descrizione |
| --- | --- |
| `sessionId` | La sessione Beeuni a cui appartiene la chiamata. |
| `agent` | L'agente che ha effettuato la chiamata. |
| `directory` | Il checkout del progetto, `/workspace`. Risolvi i percorsi relativi rispetto a esso. |
| `env` | L'ambiente del box e i [segreti](/docs/it/project/secrets) che questo agente riceve, nello stato attuale. Leggi un segreto come `context.env.NAME`: un segreto modificato dopo l'avvio del box si trova in `context.env`, non in `process.env`. |
| `signal` | Un `AbortSignal` che interrompe l'esecuzione quando l'utente ferma il turno. Passalo a `fetch`. |

- **Dimensione dell'output.** Un output superiore a 50 KB o 2.000 righe viene salvato per intero in un file nella directory temporanea della sandbox. Il modello riceve l'inizio, le dimensioni e il percorso del file. Restituisci ciò che serve al modello, non un dump grezzo.
- **Errori.** Un errore generato termina la chiamata e il modello ne legge il messaggio. Genera un messaggio che spieghi cosa modificare.
- **Importazioni.** Un modulo può importare moduli `node:*`, API Bun e file relativi. Un pacchetto viene risolto a partire da un `node_modules` accanto al modulo o in una directory superiore. La sandbox non installa pacchetti per uno strumento e una [release di configurazione](/docs/it/work/runtime#config-convergence) contiene solo i file tracciati da Git. Usa `fetch` per le API HTTP. TypeScript viene eseguito senza passaggi di build.
- **Errori di caricamento.** Un modulo che non viene caricato (file mancante, nesbeeuni esportazione predefinita, uno `parameters` che non è uno schema a oggetto, un errore durante l'importazione o un pacchetto non risolvibile) viene escluso, ma gli altri strumenti continuano a caricarsi. Per ogni strumento il daemon registra `[tools] project tools that did not load` con il motivo.

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

### `parameters` con zod

zod 4 produce lo stesso 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`
  },
}
```

Questo modulo viene caricato solo se `zod` è risolvibile a partire da un `node_modules` nel checkout in cui viene eseguita la sessione. In caso contrario, restituisce `Cannot find package 'zod'`.
Per scrivere lo schema con zod e distribuire un JSON Schema semplice, stampalo una volta e incolla l'output in `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>

### Esempio: chiamare un'API HTTP con un segreto del progetto

Salva la chiave come segreto del progetto. Il comando legge il valore dallo standard input:

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

Concedi il segreto agli agenti che chiamano lo strumento. L'agente `beeuni` del modello iniziale dispone di `secrets: all`. Un agente con autorizzazioni limitate lo elenca: `secrets: [WEATHER_API_KEY]`.

Scrivi il modulo:

```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 }
  },
}
```

Dichiaralo:

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

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

### Esempio: sostituire `web_search`

`beeuni tools eject web_search` scrive `tools/web_search.ts` e imposta `web_search: tools/web_search.ts`. Poi modifica la copia. Per esempio, per mantenere i risultati di un solo sito, aggiungi il sito a ogni query in `execute`, prima della richiesta:

```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}`)
```

Mantieni il nome, gli argomenti e il JSON di output, così le skill che nominano `web_search` e la vista dell'interfaccia web continuano a funzionare.

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

### Testare uno strumento

`beeuni validate` controlla il nome, il percorso, l'eventuale assenza del file e i valori `beeuni:`. `beeuni tools ls` mostra quali strumenti riceve una sessione.

Quindi esegui commit e push e apri una richiesta di modifica. Dopo l'unione, avvia una sessione e chiedi una chiamata con argomenti reali:

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

Uno strumento che non viene caricato non viene offerto al modello. Uno strumento che genera un errore risponde con il relativo messaggio. `beeuni sessions log <id>` stampa i messaggi della sessione, con ogni chiamata allo strumento e il relativo stato.

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

## Dichiarare gli strumenti

`tools:` associa ogni nome di strumento al relativo modulo, oppure un nome di strumento Beeuni a `beeuni:<name>`. Puoi scegliere liberamente la cartella del modulo.

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

- Un nome deve essere in snake_case e contenere al massimo 64 caratteri: `^[a-z][a-z0-9_]{0,63}$`.
- Un nome di strumento dell'harness è un errore. Un nome di strumento Beeuni accetta `beeuni:<name>` o un percorso di modulo; il modulo sostituisce lo strumento Beeuni su ogni harness.
- Un percorso è relativo alla repo e termina in `.ts`, `.js`, `.mts`, `.mjs`, `.cts` o `.cjs`.
- Un file elencato sotto [`imports:`](/docs/it/project/manifest#imports) può dichiarare strumenti. Dichiarare lo stesso nome in due file è un errore. Una chiave `tools:` in un file importato viene considerata una chiave `tools:` ai fini della regola di selezione.

Il [riferimento del manifest](/docs/it/project/manifest#tools) contiene tutte le regole.

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

## Chi può usare quali strumenti

`agents.<name>.tools` determina quali strumenti vede il modello di un agente. Include gli strumenti dell'harness, Beeuni e del progetto.

```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
```

| Valore | Strumenti ricevuti dall'agente |
| --- | --- |
| omesso oppure `all` | Tutti gli strumenti. |
| `none` | Nessuno strumento. |
| un elenco | Solo gli strumenti elencati. Un elenco con `*` è `all`. |
| `{ exclude: [...] }` | Tutti gli strumenti tranne quelli elencati. |
| `{ bash: false, … }` | La precedente forma a mappa: `false` rimuove uno strumento. |

- `tools` determina la visibilità. Le regole `permission` dell'agente stabiliscono comunque se una chiamata è consentita, richiede conferma o viene negata. Uno strumento non incluso nell'elenco è nascosto al modello e la sua chiamata viene negata.
- Un elenco di un agente non può aggiungere uno strumento Beeuni che il progetto non carica. Elencalo prima in `tools:` a livello principale.
- Un subagente avviato con lo strumento `task`: su harness sperimentale riceve solo gli strumenti consentiti sia dal proprio elenco sia da quello dell'agente della sessione. Su harness standard riceve gli strumenti del proprio elenco: harness standard applica le regole di un agente solo a quell'agente. Per impedire a un agente di delegare, non includere `task` nel suo elenco.
- Gli strumenti [Connector](/docs/it/connect/connectors) seguono `agents.<name>.connectors`, non questo elenco.
- `beeuni validate` avvisa se un nome non corrisponde a uno strumento dell'harness, Beeuni o del progetto, o a uno strumento Beeuni non caricato dal progetto. Un nome errato in un elenco `exclude` lascia attivo lo strumento corretto.

Su harness standard, `bash` comprende anche gli strumenti `pty_*` del plugin terminale, mentre `write`, `edit` e `apply_patch` condividono un'autorizzazione: elencarne uno li mostra tutti e tre, escluderne uno li nasconde tutti e tre. harness sperimentale ha strumenti `write` e `edit` separati.

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

## Quando entra in vigore una modifica

Una sessione carica gli strumenti all'avvio del runtime. Una modifica si applica dopo l'unione della richiesta: le nuove sessioni la caricano e, con le [release di configurazione](/docs/it/work/runtime#config-convergence), una sessione in esecuzione la carica alla successiva convergenza. Su harness sperimentale, una modifica a uno strumento del progetto o all'elenco degli strumenti Beeuni riavvia il runtime sul posto quando non è in corso un turno; la conversazione continua.

<a id="tools-in-harnessesopencodetools"></a>

## Strumenti in `harnesses/opencode/tools/`

harness standard continua a caricare gli strumenti personalizzati dalla propria directory di configurazione. harness sperimentale non lo fa. I progetti creati prima degli strumenti ospitati contengono copie degli strumenti Beeuni (`web_search.ts`, `memory.ts`, …).

- Su harness standard, uno strumento in quella cartella prevale sullo strumento ospitato con lo stesso nome, quindi il progetto conserva la propria copia finché non la elimina. Elimina le copie degli strumenti Beeuni: il daemon ospita quelli elencati in `beeuni.yaml`, su entrambi gli harness.
- Per fare in modo che uno strumento harness standard venga eseguito su entrambi gli harness, spostalo fuori dalla cartella, sostituisci `tool({ description, args, execute })` con un semplice oggetto il cui `parameters` sia JSON Schema, leggi i segreti da `context.env` e dichiaralo sotto `tools:`.
