# Ferramentas

Um módulo de ferramentas é executado em todos os ambientes de agente. beeuni.yaml lista as ferramentas do Beeuni e as ferramentas do próprio projeto, e a lista de ferramentas de cada agente determina quem pode chamá-las.

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

Uma ferramenta é uma função que o modelo chama durante um turno. Uma
[sessão](/docs/pt/work/sessions) tem três tipos, em ambos os
[harnesses](/docs/pt/work/harnesses), harness padrão e harness experimental:

| Tipo | Nomes | Implementado por |
| --- | --- | --- |
| Ferramentas do harness | `bash`, `read`, `write`, `edit`, `glob`, `grep`, `task`, `question`, … | O harness. |
| Ferramentas Beeuni | `web_search`, `image_search`, `scrape_webpage`, `memory`, `show` | Beeuni. `beeuni.yaml` lista cada uma como `<name>: beeuni:<name>`. Um projeto sem a chave `tools:` recebe as cinco. |
| Ferramentas do projeto | Qualquer nome que você declarar | Seu projeto: um módulo, declarado em `tools:` em `beeuni.yaml`. |

As ferramentas Beeuni e as ferramentas do projeto são independentes do harness. O daemon do sandbox carrega um módulo por ferramenta e o executa em qualquer um dos harnesses, com o mesmo nome, argumentos e saída. harness experimental chama o módulo no processo do daemon. harness padrão o chama por meio de um plugin escrito pelo daemon, que encaminha cada chamada ao daemon. Um módulo nunca importa um pacote do harness.

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

## Ferramentas Beeuni em beeuni.yaml

Um projeto novo lista as cinco ferramentas Beeuni em `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: a ferramenta mantida pela Beeuni. Uma correção nela chega a todos os projetos que a listam, sem alterações no projeto.

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

### Quais ferramentas Beeuni uma sessão recebe

| `beeuni.yaml` | A sessão recebe |
| --- | --- |
| Sem chave `tools:`, no arquivo raiz ou em qualquer arquivo [importado](/docs/pt/project/manifest#imports) | Todas as cinco ferramentas Beeuni. Um projeto criado antes da existência desta lista continua com todas elas. |
| Uma chave `tools:`, mesmo vazia (`tools: {}` ou `tools:` com todas as linhas removidas) | Apenas as ferramentas Beeuni que ela lista, como `beeuni:<name>` ou como um módulo que substitui a ferramenta. |

As ferramentas próprias do projeto são carregadas nos dois casos.

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

### Veja o que uma sessão recebe

`beeuni tools ls` lê `beeuni.yaml` e suas importações e imprime cada ferramenta que uma sessão recebe, seguida das ferramentas Beeuni removidas pelo projeto:

```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 | Significado |
| --- | --- |
| `beeuni` | Uma ferramenta Beeuni, listada como `beeuni:<name>` (ou todas, se não houver chave `tools:`). |
| `beeuni (overridden)` | Um nome de ferramenta Beeuni com um caminho de módulo: o módulo do projeto é executado no lugar dela. |
| `project` | Uma ferramenta própria do projeto. |

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

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

### Remover uma ferramenta Beeuni

Exclua a linha correspondente em `tools:`. Todos os agentes do projeto perdem a ferramenta, nos dois harnesses, em todas as sessões iniciadas depois da aprovação da solicitação de alteração. Para manter uma ferramenta disponível para apenas um agente, use
[`agents.<name>.tools`](#who-may-use-which-tool).

Em uma sessão de um projeto que removeu uma ferramenta:

- **harness padrão** não oferece a ferramenta ao modelo.
- **harness experimental** não oferece a ferramenta. Uma chamada a ela falha com `Tool show not found`
  (para `show`).
- **O daemon** responde `POST /beeuni/tools/<name>` com `404` e
  `no tool named <name> is loaded`.
- **Uma skill que menciona a ferramenta continua sendo carregada.** Por exemplo, `beeuni-memory`
  menciona `memory`. O modelo lê a skill, não encontra essa ferramenta e usa
  outras ferramentas: sem `memory`, ele lê e edita os arquivos em `memory/`
  usando as ferramentas de arquivos.

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

### Alterar uma ferramenta Beeuni: ejetar

`beeuni tools eject <name>` dá ao projeto uma cópia própria de uma ferramenta Beeuni:

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

- Ele grava o código-fonte da Beeuni — os mesmos bytes executados pelo sandbox — em
  `tools/<name>.ts`. O arquivo importa apenas módulos `node:*` e lê
  `BEEUNI_API_URL`, `BEEUNI_TOKEN` e as chaves do provedor de `context.env`, então é executado sem alterações.
- Ele define `<name>: tools/<name>.ts` em `beeuni.yaml`, no arquivo que declara a entrada (o arquivo raiz ou um arquivo importado). Todas as outras linhas e comentários são mantidos. A linha alterada termina com `# ejected from beeuni:<name>`.
- Se não houver uma chave `tools:`, ele a cria e lista as outras quatro ferramentas Beeuni como `beeuni:<name>`, então a ejeção não remove nada.
- Ele se recusa a prosseguir se `tools/<name>.ts` existir ou se a ferramenta já apontar para outro módulo. `--force` substitui o arquivo existente.
- Ele se recusa a aceitar um nome que não seja de uma ferramenta Beeuni.

A cópia é sua. A Beeuni não a atualizará mais. Para voltar à ferramenta mantida, altere a linha para `<name>: beeuni:<name>` e exclua o arquivo.

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

### Substituir sem ejetar

Um nome de ferramenta Beeuni com um caminho de módulo substitui a ferramenta Beeuni em todos os harnesses:

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

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

### As visualizações da interface web

A interface web tem uma visualização para cada ferramenta Beeuni, selecionada pelo nome da ferramenta. As visualizações `show` e `memory` leem os argumentos da chamada (`type`, `path`, `url`,
`content`, `items`; `command`, `path`). As visualizações `web_search`, `image_search` e
`scrape_webpage` leem o JSON da saída. Uma cópia alterada que mantenha o nome precisa manter esses argumentos e esse formato de saída, ou a interface exibirá a saída bruta.

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

### Validação

`beeuni validate` verifica a lista:

- `<name>` em `beeuni:<name>` precisa ser uma ferramenta Beeuni, e a chave deve ser igual a ela. `web_search: beeuni:image_search` é um erro:
  ``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.``
- Uma chave `tools:` que não lista nenhuma ferramenta Beeuni gera um aviso:
  ``Sessions of this project get no Beeuni tool (web_search, image_search, scrape_webpage, memory, show). Add `<name>: beeuni:<name>` to keep one.``
  Isso detecta um projeto que adiciona sua primeira ferramenta própria e remove as cinco por acidente.
- Um agente cujo `tools` menciona uma ferramenta Beeuni que o projeto não carrega gera um aviso: ``"show" is a Beeuni tool this project does not load: add `show: beeuni:show` under the top-level `tools`, or remove it here.``

A [referência do manifesto](/docs/pt/project/manifest#tools) contém todas as regras.

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

## Escrever uma ferramenta do projeto

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

A exportação padrão é um objeto simples:

| Campo | Regra |
| --- | --- |
| `description` | String não vazia. O modelo a lê para decidir quando chamar a ferramenta. |
| `parameters` | [JSON Schema](https://json-schema.org) dos argumentos, `type: 'object'`. O modelo o recebe como está, então liste os argumentos obrigatórios em `required`. A Beeuni não valida os argumentos de acordo com esse esquema. |
| `execute(args, context)` | Retorna uma string ou qualquer valor JSON (enviado como JSON indentado). Pode ser `async`. Um erro lançado é o erro da ferramenta, e o modelo lê a mensagem. |

`context` contém:

| Campo | O que é |
| --- | --- |
| `sessionId` | A sessão Beeuni à qual a chamada pertence. |
| `agent` | O agente que fez a chamada. |
| `directory` | O checkout do projeto, `/workspace`. Resolva um caminho relativo com base nele. |
| `env` | O ambiente da caixa mais os [segredos](/docs/pt/project/secrets) que este agente recebe, como estão agora. Leia um segredo como `context.env.NAME`: um segredo alterado depois que a caixa foi iniciada está em `context.env`, não em `process.env`. |
| `signal` | Um `AbortSignal` que aborta quando o usuário interrompe o turno. Passe-o para `fetch`. |

- **Tamanho da saída.** Uma saída com mais de 50 KB ou 2.000 linhas é salva integralmente em um arquivo no diretório temporário do sandbox. O modelo recebe o início, o tamanho e o caminho do arquivo. Retorne o que o modelo precisa, não um despejo bruto.
- **Erros.** Um erro lançado encerra a chamada, e o modelo lê a mensagem de erro. Lance uma mensagem que diga o que alterar.
- **Importações.** Um módulo pode importar módulos `node:*`, APIs do Bun e arquivos relativos. Um pacote é resolvido a partir de um `node_modules` ao lado do módulo ou acima dele. O sandbox não instala pacotes para uma ferramenta, e uma [versão de configuração](/docs/pt/work/runtime#config-convergence) contém apenas os arquivos rastreados pelo Git. Use `fetch` para APIs HTTP. O TypeScript é executado sem uma etapa de build.
- **Falhas.** Um módulo que não carrega (arquivo ausente, sem exportação padrão, `parameters` que não é um esquema de objeto, erro na importação ou pacote não resolvido) é ignorado, e as outras ferramentas continuam carregando. O daemon registra `[tools] project tools that did not load` com o motivo de cada ferramenta.

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

### `parameters` com zod

O zod 4 gera o mesmo 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`
  },
}
```

Este módulo só carrega onde `zod` pode ser resolvido a partir de um `node_modules` no checkout em que a sessão é executada. Caso contrário, falha com `Cannot find package 'zod'`.
Para escrever o esquema com zod e distribuir JSON Schema simples, imprima-o uma vez e cole a saída em `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>

### Exemplo: chamar uma API HTTP com um segredo do projeto

Armazene a chave como segredo do projeto. O comando lê o valor da entrada padrão:

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

Conceda acesso ao segredo aos agentes que chamam a ferramenta. O agente `beeuni` do projeto inicial tem `secrets: all`. Um agente com escopo definido o lista: `secrets: [WEATHER_API_KEY]`.

Escreva o módulo:

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

Declare-o:

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

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

### Exemplo: substituir `web_search`

`beeuni tools eject web_search` grava `tools/web_search.ts` e define
`web_search: tools/web_search.ts`. Em seguida, altere a cópia. Por exemplo, para manter
resultados de apenas um site, adicione o site a cada consulta em `execute`, antes da solicitação:

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

Mantenha o nome, os argumentos e o JSON da saída para que as skills que mencionam
`web_search` e a visualização da interface web continuem funcionando.

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

### Testar uma ferramenta

`beeuni validate` verifica o nome, o caminho, um arquivo ausente e os valores de `beeuni:`. `beeuni tools ls` mostra o que uma sessão recebe.

Depois, faça commit, push e abra uma solicitação de alteração. Após a aprovação, inicie uma sessão e solicite uma chamada com argumentos reais:

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

Uma ferramenta que não carrega não é oferecida ao modelo. Uma ferramenta que lança um erro responde com a mensagem de erro. `beeuni sessions log <id>` imprime as mensagens da sessão, com cada chamada de ferramenta e seu status.

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

## Declarar ferramentas

`tools:` mapeia cada nome de ferramenta para seu módulo, ou um nome de ferramenta Beeuni para `beeuni:<name>`. Você escolhe a pasta do módulo.

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

- Um nome deve estar em snake_case e ter no máximo 64 caracteres: `^[a-z][a-z0-9_]{0,63}$`.
- Um nome de ferramenta do harness é um erro. Um nome de ferramenta Beeuni aceita `beeuni:<name>` ou um caminho de módulo; o módulo substitui a ferramenta Beeuni em todos os harnesses.
- Um caminho deve ser relativo ao repositório e terminar em `.ts`, `.js`, `.mts`, `.mjs`, `.cts` ou `.cjs`.
- Um arquivo listado em [`imports:`](/docs/pt/project/manifest#imports) pode declarar ferramentas. Declarar um nome em dois arquivos é um erro. Uma chave `tools:` em um arquivo importado conta como uma chave `tools:` para a regra de seleção.

[A referência do manifesto](/docs/pt/project/manifest#tools) contém todas as regras.

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

## Quem pode usar cada ferramenta

`agents.<name>.tools` decide quais ferramentas o modelo de um agente vê. Ela inclui ferramentas do harness, Beeuni e do projeto.

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

| Valor | O agente recebe |
| --- | --- |
| omitido ou `all` | Todas as ferramentas. |
| `none` | Nenhuma ferramenta. |
| uma lista | Apenas as ferramentas listadas. Uma lista com `*` é `all`. |
| `{ exclude: [...] }` | Todas as ferramentas, exceto as listadas. |
| `{ bash: false, … }` | O formato de mapa anterior: `false` remove uma ferramenta. |

- `tools` decide a visibilidade. As regras `permission` do agente ainda determinam se uma chamada é permitida, precisa de confirmação ou é negada. Uma ferramenta que não está na lista fica oculta para o modelo e é negada se for chamada.
- Uma lista de agente não pode adicionar uma ferramenta Beeuni que o projeto não carrega. Liste-a primeiro em `tools:` no nível superior.
- Um subagente iniciado com a ferramenta `task`: no harness experimental, ele recebe apenas as ferramentas permitidas tanto pela própria lista quanto pela lista do agente da sessão. No harness padrão, ele recebe as ferramentas da própria lista: o harness padrão aplica as regras de um agente somente a esse agente. Para impedir que um agente delegue, deixe `task` fora da lista dele.
- As ferramentas do [Connector](/docs/pt/connect/connectors) seguem `agents.<name>.connectors`,
  não esta lista.
- `beeuni validate` avisa quando um nome não corresponde a uma ferramenta do harness, da Beeuni ou do projeto, e também quando o projeto não carrega uma ferramenta Beeuni. Um erro de digitação em uma lista `exclude` mantém a ferramenta real ativada.

No harness padrão, `bash` também abrange as ferramentas `pty_*` do plugin de terminal, e `write`, `edit` e `apply_patch` compartilham uma permissão: listar uma mostra as três, e excluir uma oculta as três. O harness experimental tem ferramentas `write` e `edit` separadas.

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

## Quando uma alteração entra em vigor

Uma sessão carrega suas ferramentas quando o runtime é iniciado. Uma alteração se aplica depois que a solicitação de alteração é aprovada: novas sessões carregam a alteração e, com [versões de configuração](/docs/pt/work/runtime#config-convergence), uma sessão em execução a carrega na próxima convergência. No harness experimental, uma alteração em uma ferramenta do projeto ou na lista de ferramentas Beeuni reinicia o runtime no mesmo lugar quando nenhum turno está em execução; a conversa continua.

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

## Ferramentas em `harnesses/opencode/tools/`

O harness padrão ainda carrega ferramentas personalizadas do diretório de configuração. O harness experimental não. Projetos criados antes da disponibilização de ferramentas hospedadas incluem cópias das ferramentas Beeuni nesse diretório
(`web_search.ts`, `memory.ts`, …).

- No harness padrão, uma ferramenta nessa pasta tem prioridade sobre a ferramenta hospedada de mesmo nome, então o projeto mantém sua cópia até removê-la. Exclua as cópias das ferramentas Beeuni: o daemon hospeda as que `beeuni.yaml` lista, nos dois harnesses.
- Para executar uma ferramenta do harness padrão nos dois harnesses, mova-a para fora da pasta, substitua `tool({ description, args, execute })` por um objeto simples cujo `parameters` seja JSON Schema, leia os segredos de `context.env` e declare a ferramenta em `tools:`.
