
# API de Agentes de IA

Um **Agente de IA** é o cérebro por detrás do seu bot: as suas instruções, personalidade, idioma, conhecimentos e ferramentas. Cria um Agente uma vez e depois direciona o tráfego para ele. Este guia abrange tudo o que pode fazer com um Agente através da API — criá-lo, configurá-lo, fornecer-lhe conhecimentos e ferramentas, rever os seus rascunhos e encaminhar conversas para ele.

- **URL Base** — `https://api.youraiconnector.com/v1`
- **Autenticação** — a sua chave de API (ver [Autenticação](authentication.md))
- **Erros e paginação** — ver [Erros e Paginação](errors-and-pagination.md)

Todos os exemplos abaixo mostram o formato de consulta `?apiKey=` em cURL e o cabeçalho `X-API-Key` em JavaScript e Python — qualquer um funciona em todos os endpoints.

Se é novo no conceito de Agentes, leia primeiro [Agentes de IA](../ai-agents/ai-agents.md).


---

## Como um Agente é estruturado

Quatro elementos são geridos separadamente, e é útil saber qual é qual antes de começar:

| Elemento | O que é | Onde o configura |
|---|---|---|
| **Configuração** | Instruções, regras, objetivo, personalidade, idioma, nível de IA, comportamento de marcação e seguimento | `PUT /agents/{agentId}` ou o `PUT /agents/{agentId}/bot-config` mais restrito |
| **Conhecimento** | FAQs e fontes de conhecimento (páginas e documentos que a plataforma leu para si) | [API de FAQs](faqs.md) e `POST /agents/{agentId}/kb-sources` |
| **Ferramentas** | Funções personalizadas e servidores MCP que o Agente pode chamar durante a conversa | `POST /agents/{agentId}/custom-functions` e `POST /agents/{agentId}/mcp-servers` |
| **Encaminhamento** | Que canais e conversas chegam efetivamente a este Agente | Pontos de Entrada — `PUT /entry-points/channel-defaults` e `POST /agents/{agentId}/entry-points` |

> **Um novo Agente não responde a ninguém até que encaminhe conversas para ele.** Criar um Agente não o coloca num canal. Esse é o passo que a maioria das integrações falha — consulte [Encaminhar conversas para um Agente](#routing-conversations-to-an-agent) no final desta página.

---

## O objeto Agente

Um documento completo de Agente é grande — várias centenas de kilobytes, principalmente a sua lista de FAQs, as suas fontes de conhecimento e qualquer conteúdo de página lido a partir do seu site. Por isso, a listagem devolve uma **linha de resumo** curta por Agente quando a solicita:

```json
{
  "id": "ag7HkQ2ZpLxR3mNb",
  "name": "Listing assistant",
  "active": true,
  "language": "en",
  "goal": "Book a viewing",
  "tags": [],
  "anthropic_model": "standard",
  "ai_speed": "balanced",
  "enable_bookings": false,
  "enable_follow_ups": true,
  "faq_refs_count": 42,
  "kb_source_refs_count": 3,
  "created_at": 1700000000000,
  "last_modified_at": 1700000000000
}
```

| Campo | Tipo | Descrição |
|---|---|---|
| `id` | string | O identificador único do Agente. |
| `name` | string \| null | Nome do Agente, conforme apresentado no painel. |
| `active` | boolean \| null | Se o Agente tem permissão para responder atualmente. |
| `language` | string \| null | Idioma em que o Agente responde. |
| `goal` | string \| null | O objetivo do Agente, encurtado para os primeiros 200 caracteres (reticências no final significam que foi encurtado). |
| `tags` | array \| null | As regras de etiquetagem do Agente. |
| `anthropic_model` | string \| null | Nível de qualidade da IA: `standard`, `economy`, `max` ou `mini`. |
| `ai_speed` | string \| null | Quanto raciocínio o Agente aplica antes de responder: `fast`, `fast_thinker`, `balanced` ou `thorough`. |
| `enable_bookings` | boolean \| null | Se o Agente pode marcar reuniões. |
| `enable_follow_ups` | boolean \| null | Se o Agente envia mensagens de seguimento. |
| `faq_refs_count` | integer | Quantas FAQs existem na base de conhecimento deste Agente. |
| `kb_source_refs_count` | integer | Quantas fontes de conhecimento estão ligadas a ele. |
| `created_at` | integer \| null | Hora de criação, milissegundos da época. |
| `last_modified_at` | integer \| null | Última alteração, milissegundos da época. |

O documento completo adiciona tudo o resto: `instructions`, `rules`, `personality`, `availability`, `follow_up_config`, as listas de FAQs e fontes de conhecimento ligadas, os blocos de texto gerados e qualquer estado de execução (`tag_generation`, `optimize_run`).

> Algumas respostas também contêm `substrate_campaign_id`. É um registo interno mantido em contas mais antigas; nunca precisa de agir sobre ele e, em contas mais recentes, é `null` ou inexistente.

---

## Listar Agentes

`GET /agents` — todos os Agentes na conta, do mais recente para o mais antigo.

Este endpoint **não é paginado**. Por predefinição, cada Agente é devolvido com a sua configuração completa, o que é pesado: um único Agente pode atingir 580 KB e uma conta com 64 Agentes mais de 3 MB. Passe `view=summary` para obter uma linha curta por Agente e, em seguida, leia o que pretende com [Obter um Agente](#get-an-agent).

**Parâmetros de consulta**

| Parâmetro | Descrição |
|---|---|
| `view` | Defina como `summary` para linhas curtas. Qualquer outro valor devolve `400`. Omitir para documentos completos. |
| `fields` | Aplica-se apenas em conjunto com `view=summary`. Chaves de resumo separadas por vírgulas a manter, por exemplo `id,name,active`. `id` é sempre incluído; nomes desconhecidos são ignorados. |

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/agents?apiKey=YOUR_API_KEY&view=summary&fields=id,name,active"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/agents?view=summary", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const { agents } = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/agents",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"view": "summary"},
)
agents = res.json()["agents"]
```

**Resposta** (`200`)

```json
{
  "success": true,
  "agents": [
    { "id": "ag7HkQ2ZpLxR3mNb", "name": "Listing assistant", "active": true }
  ]
}
```

---

## Criar um Agente

`POST /agents` — apenas `name` é realmente necessário; envie qualquer configuração que já conheça juntamente com o mesmo. Um novo Agente está ativo por predefinição.

**Campos do pedido** (todos opcionais, exceto `name`)

| Campo | Tipo | Descrição |
|---|---|---|
| `name` | string | Nome do Agente. |
| `active` | boolean | Se pode responder imediatamente. O valor predefinido é `true`. |
| `language` | string | Idioma em que o Agente responde. |
| `instructions` | string | Instruções principais que orientam a forma como fala com os contactos. |
| `rules` | string | Regras rígidas que deve seguir sempre. |
| `goal` | string | O resultado para o qual deve trabalhar. |
| `personality` | string | Tom de voz e personalidade. |
| `availability` | object | Horas de atividade por dia da semana — ver [Definir horas de atividade](#set-active-hours). |
| `ai_speed` | string | `fast`, `fast_thinker`, `balanced` ou `thorough`. |
| `anthropic_model` | string | `standard`, `economy`, `max` ou `mini`. |
| `scrape_urls` | string[] | Páginas a ler para criar as instruções do Agente. |

**Criar um Agente a partir do seu website.** Inclua `scrape_urls` e a plataforma lê essas páginas e escreve as instruções por si. A resposta indica se essa geração foi iniciada, para que saiba se deve consultar o Agente para verificar o progresso.

**cURL**

```bash
curl -X POST "https://api.youraiconnector.com/v1/agents?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Listing assistant",
    "language": "en",
    "instructions": "Answer questions about our listings and book viewings.",
    "goal": "Book a viewing"
  }'
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/agents", {
  method: "POST",
  headers: { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({
    name: "Listing assistant",
    scrape_urls: ["https://example.com", "https://example.com/faq"],
  }),
});
const data = await res.json();
console.log(data.agent_id);
```

**Python**

```python
res = requests.post(
    "https://api.youraiconnector.com/v1/agents",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"name": "Listing assistant", "scrape_urls": ["https://example.com"]},
)
print(res.json()["agent_id"])
```

**Resposta** (`201`)

```json
{
  "success": true,
  "agent_id": "ag7HkQ2ZpLxR3mNb",
  "substrate_campaign_id": null,
  "agent_generation_queued": true
}
```

`agent_generation_queued` é `true` quando a plataforma começou a escrever as instruções a partir das páginas que forneceu.

Um `400` significa que o corpo não era um objeto JSON, um campo foi rejeitado ou o Agente excede o tamanho de configuração permitido pelo seu plano. Um `403` significa que a conta não tem permissão para utilizar uma das definições que enviou — por exemplo, um nível de IA que o fornecedor da conta não concedeu.

---

## Obter um Agente

`GET /agents/{agentId}`

Passe `fields` com uma lista separada por vírgulas para obter apenas o que precisa, por exemplo `fields=name,active,goal`. O `id` é sempre incluído e os nomes que não existem no Agente são ignorados em vez de rejeitados. Omitir para obter o documento completo.

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb?apiKey=YOUR_API_KEY&fields=name,active,goal"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb?fields=name,active", {
  headers: { "X-API-Key": "YOUR_API_KEY" },
});
const { agent } = await res.json();
```

**Python**

```python
res = requests.get(
    "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"fields": "name,active"},
)
agent = res.json()["agent"]
```

Um Agente que não existe na sua conta devolve `404`.

---

## Atualizar um Agente

`PUT /agents/{agentId}` — envie apenas os campos que pretende alterar; tudo o resto permanece inalterado.

As definições aninhadas podem ser endereçadas folha a folha com uma chave pontuada, pelo que `"availability.monday"` altera apenas a segunda-feira e deixa o resto da semana inalterado.

**Notas**

- Para alterar o tipo de evento reservável em que o Agente efetua reservas, envie `event_id` (o id do evento, ou `null` para o limpar). Envie `event_ids` com uma matriz para associar vários de uma vez — o primeiro torna-se o principal e `[]` desassocia tudo. `event_id` e `event_ids` são mutuamente exclusivos, e o campo `event` em si não pode ser escrito diretamente.
- `enable_bookings` tem de ser um booleano real, e `booking_provider` tem de ser um de `default`, `zenchef`, `formitable`.
- Os campos de propriedade e identidade são ignorados, tal como o estado de execução interno (progresso da geração e otimização).
- **O encaminhamento não é definido aqui.** Utilize `PUT /entry-points/channel-defaults` para tornar o Agente o responsável por responder a um canal, `POST /agents/{agentId}/entry-points` para regras de palavras-chave e comentários, e `PATCH /agents/{agentId}/active` para o pausar ou retomar.

**cURL**

```bash
curl -X PUT "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "instructions": "Answer questions about our listings and always offer a viewing.",
    "anthropic_model": "standard"
  }'
```

**JavaScript**

```javascript
await fetch("https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb", {
  method: "PUT",
  headers: { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({ "availability.monday": { start_time: "09:00", end_time: "17:00" } }),
});
```

**Python**

```python
requests.put(
    "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"goal": "Book a viewing within three messages"},
)
```

**Resposta** (`200`)

```json
{ "success": true, "agent_id": "ag7HkQ2ZpLxR3mNb" }
```

Um corpo vazio devolve `400` com `"No fields to update"`.

---

## Atualizar definições do bot

`PUT /agents/{agentId}/bot-config` — a forma restrita de alterar apenas as definições de conversação.

Um Agente não tem uma secção de bot separada: as suas definições residem diretamente no Agente, pelo que os nomes dos campos aqui são os mesmos que enviaria para `PUT /agents/{agentId}`. Este endpoint existe como a forma segura e focada de alterar alguns deles. É necessário pelo menos um campo.

| Campo | Descrição |
|---|---|
| `instructions` | Instruções principais que orientam a forma como o Agente fala com os contactos. |
| `rules` | Regras rígidas que deve seguir sempre. |
| `goal` | O resultado para o qual deve trabalhar em cada conversação. |
| `personality` | Descrição do tom de voz e da personalidade. |
| `language` | Idioma em que o Agente responde. |
| `ai_speed` | `fast`, `fast_thinker`, `balanced` ou `thorough`. |
| `anthropic_model` | `standard`, `economy`, `max` ou `mini`. |
| `max_messages` | Número máximo de mensagens do Agente por conversação. |
| `alert_human_when` | Quando o Agente deve alertar um colega humano. |
| `ai_transparency` | Se o Agente revela que é uma IA. |

> **Os nomes dos campos devem ser nomes simples aqui** — letras, números, sublinhados e hífenes. Os caminhos pontuados não são aceites neste endpoint (ao contrário de `PUT /agents/{agentId}`), pelo que `bot.goal` é rejeitado com um `400`.

```bash
curl -X PUT "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/bot-config?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "goal": "Book a viewing within three messages", "ai_speed": "thorough" }'
```

O texto longo conta para o tamanho de configuração permitido pelo seu plano, pelo que um conjunto de instruções muito grande pode ser recusado com um `400`.

---

## Definir horas ativas

`PUT /agents/{agentId}/active-hours` — as horas durante as quais o Agente responde automaticamente. Fora dessas janelas, permanece em silêncio.

Envie um objeto `availability` com chaves por dia da semana (`monday` a `sunday`). Cada dia aceita uma única janela temporal ou uma lista de janelas, no formato `HH:MM` de 24 horas. Os dias que omitir mantêm o que tinham, e qualquer chave que não seja um dia da semana é rejeitada — para que um erro de digitação não resulte silenciosamente em nada.

```bash
curl -X PUT "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/active-hours?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "availability": {
      "monday": { "start_time": "09:00", "end_time": "17:00" },
      "tuesday": [
        { "start_time": "09:00", "end_time": "12:00" },
        { "start_time": "13:00", "end_time": "17:00" }
      ]
    }
  }'
```

**Resposta** (`200`)

```json
{ "success": true, "agent_id": "ag7HkQ2ZpLxR3mNb" }
```

Uma chave de dia da semana incorreta devolve `400`: `"Invalid availability keys: funday. Allowed keys: monday through sunday."`

---

## Pausar ou retomar um Agente

`PATCH /agents/{agentId}/active` — liga ou desliga o Agente. Um Agente em pausa mantém toda a sua configuração, mas deixa de responder imediatamente; a retoma tem efeito imediato.

```bash
curl -X PATCH "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/active?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "active": false }'
```

```javascript
await fetch("https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/active", {
  method: "PATCH",
  headers: { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({ active: false }),
});
```

**Resposta** (`200`)

```json
{ "success": true, "agent_id": "ag7HkQ2ZpLxR3mNb", "active": false }
```

`active` tem de ser um booleano real — qualquer outro valor devolve `400` com `"active (boolean) is required"`.

---

## Duplicar um Agente

`POST /agents/{agentId}/duplicate` — cria uma cópia com a sua configuração preservada. A cópia não envia nada até que lhe aponte um canal ou um Ponto de Entrada.

```bash
curl -X POST "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/duplicate?apiKey=YOUR_API_KEY"
```

**Resposta** (`201`)

```json
{ "success": true, "agent_id": "ag9WsX3cRfV6tGyH", "source_agent_id": "ag7HkQ2ZpLxR3mNb" }
```

Uma duplicação conta para o limite de Agentes do seu plano exatamente como a criação de um de raiz, pelo que é recusada com `403` quando a conta atinge o limite.

---

## Eliminar um Agente

`DELETE /agents/{agentId}`

A eliminação é recusada enquanto o Agente estiver ligado a algo que deixaria de funcionar sem ele — uma transmissão, um Ponto de Entrada ou (em contas mais antigas) uma campanha. A resposta lista o que o está a reter para que possa primeiro desligar esses elementos e tentar novamente.

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb?apiKey=YOUR_API_KEY"
```

**Resposta** (`200`)

```json
{ "success": true, "agent_id": "ag7HkQ2ZpLxR3mNb" }
```

**Bloqueado** (`409`)

```json
{
  "success": false,
  "error": "Agent is still attached to one or more broadcast(s). Detach it first.",
  "blocking_campaign_ids": [],
  "blocking_broadcast_ids": ["bc5TgYhUj8IkOlPm"],
  "blocking_entry_point_ids": []
}
```

---

## Rascunhos: reveja as alterações antes de serem publicadas

As edições feitas no editor, e qualquer reescrita produzida por [Otimizar com IA](#optimize-an-agent-with-ai), são guardadas como um **rascunho não publicado** até que as publique. O Agente ativo continua a responder com a sua configuração atual até lá.

### Publicar o rascunho

`POST /agents/{agentId}/publish-draft` — move o rascunho para a configuração ativa e limpa o rascunho no mesmo passo.

```bash
curl -X POST "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/publish-draft?apiKey=YOUR_API_KEY"
```

**Resposta** (`200`)

```json
{ "success": true, "agent_id": "ag7HkQ2ZpLxR3mNb", "published_keys": ["instructions", "goal"] }
```

`published_keys` lista as definições que foram movidas do rascunho para o Agente ativo, para que possa mostrar o que mudou.

> **Verifique se existe um rascunho antes de efetuar esta chamada.** Publicar um Agente que não tem rascunho não é uma chamada suportada e, atualmente, é devolvida como um `500` com uma mensagem genérica, não específica. Para descartar um rascunho, utilize a opção de descartar abaixo.

### Eliminar o rascunho

`POST /agents/{agentId}/discard-draft` — descarta o rascunho e deixa a configuração ativa exatamente como está. É seguro chamar quando não existe nenhum rascunho; nada acontece.

```bash
curl -X POST "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/discard-draft?apiKey=YOUR_API_KEY"
```

---

## Otimizar um Agente com IA

`POST /agents/{agentId}/optimize` — reescreve a configuração do Agente a partir do seu feedback ("continua a oferecer descontos", "as respostas são demasiado longas") e guarda a reescrita **como um rascunho** em vez de a colocar ativa.

Envie `user_feedback` (uma instrução simples) ou, ao reagir a uma resposta incorreta específica, `thumbs_down_feedback` juntamente com a `thumbs_down_message` ofensiva. Pelo menos um dos dois deve conter texto.

```bash
curl -X POST "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/optimize?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "user_feedback": "Keep replies under three sentences." }'
```

**Resposta** (`202`)

```json
{ "success": true, "agent_id": "ag7HkQ2ZpLxR3mNb" }
```

O trabalho é executado em segundo plano e a chamada retorna imediatamente. Leia o Agente com `GET /agents/{agentId}` e observe `optimize_run.status`; assim que voltar a `Draft`, a reescrita estará à espera como rascunho do Agente. Reveja-a e, em seguida, publique-a ou elimine-a.

Apenas uma execução de cada vez por Agente — uma segunda chamada enquanto uma está em curso retorna `409`. Isto utiliza créditos de IA.

---

## Regras de etiquetagem

Uma regra de etiquetagem é uma etiqueta mais uma descrição de quando se aplica. Durante uma conversa, o Agente lê essa descrição e etiqueta o contacto quando esta se adequa, que é a forma como as automatizações baseadas em etiquetas são acionadas.

**O objeto de regra**

| Campo | Obrigatório | Descrição |
|---|---|---|
| `name` | Sim | A etiqueta a aplicar, por exemplo `hot-lead`. |
| `description` | Não | Quando o Agente a deve aplicar, escrita como uma instrução que ele segue. |
| `webhook` | Não | URL chamado quando o Agente aplica esta etiqueta. |
| `ai_can_remove` | Não | Se o Agente também pode remover a etiqueta novamente. O padrão é `false`. |
| `tag_id` | Não | Id de uma etiqueta existente na sua conta para associar a regra. Sem isto, a regra associa-se à etiqueta com o mesmo nome, criando-a se não existir — para que cada regra possa ser endereçada pelo id da etiqueta posteriormente. |

### Adicionar uma regra de etiquetagem

`POST /agents/{agentId}/tags`

```bash
curl -X POST "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/tags?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tag": {
      "name": "hot-lead",
      "description": "Apply when the contact asks about pricing or wants to book a call.",
      "ai_can_remove": false
    }
  }'
```

**Resposta** (`200`)

```json
{ "success": true, "agent_id": "ag7HkQ2ZpLxR3mNb", "tag": { "name": "hot-lead", "...": "..." } }
```

### Substituir uma regra de etiquetagem

`PUT /agents/{agentId}/tags/{tagId}` — a regra é encontrada pelo ID da etiqueta no caminho e **substituída na totalidade**, não fundida, por isso envie a regra completa em vez de apenas a parte que está a alterar. A etiqueta para a qual aponta é preservada mesmo que omita `tag_id`, pelo que uma edição não pode desassociar a regra da sua etiqueta.

```bash
curl -X PUT "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/tags/tg8YuIoP2aSdF3gH?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "tag": { "name": "hot-lead", "description": "Apply only when the contact asks to book a call." } }'
```

### Remover uma regra de etiquetagem

`DELETE /agents/{agentId}/tags/{tagId}` — o Agente deixa de aplicar essa etiqueta. A etiqueta em si, e quaisquer contactos que já a possuam, permanecem inalterados.

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/tags/tg8YuIoP2aSdF3gH?apiKey=YOUR_API_KEY"
```

Ambos os endpoints devolvem `404` quando o Agente não existe **ou** quando não tem nenhuma regra para essa etiqueta.

### Gerar um conjunto de etiquetas com IA

`POST /agents/{agentId}/tags/generate` — concebe um conjunto completo de regras (os nomes das etiquetas e a formulação "aplicar quando…" por trás de cada uma) ao ler as instruções e o objetivo do próprio Agente.

| Campo | Descrição |
|---|---|
| `mode` | `merge` (o predefinido) mantém as regras já existentes no Agente e adiciona-lhes novas. `replace` concebe o conjunto de raiz. |

```bash
curl -X POST "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/tags/generate?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "mode": "merge" }'
```

**Resposta** (`202`)

```json
{ "success": true, "agent_id": "ag7HkQ2ZpLxR3mNb", "mode": "merge" }
```

O trabalho é executado em segundo plano. Leia o Agente e observe `tag_generation.status`; as regras em si são colocadas no `tags` do Agente. Apenas uma execução de cada vez por Agente (`409` caso contrário), e utiliza créditos de IA.

---

## Fontes de conhecimento

As fontes de conhecimento são as páginas e documentos que a plataforma leu para si. Anexar uma a um Agente permite-lhe responder a partir desse conteúdo.

**De onde vêm os IDs das fontes.** Adicione conteúdo com os endpoints da base de conhecimento — `POST /kb-sources/url` para uma página, `POST /kb-sources/file` para um documento, `POST /kb-sources/bulk-import` para um site inteiro. Estes devolvem um `source_id` que consulta com `GET /kb-sources/{sourceId}` até estar pronto. `POST /kb-sources/url` também aceita `autoLinkToAgentId`, que anexa a fonte a um Agente assim que a importação termina, para que possa ignorar a chamada de anexação abaixo.

### Anexar fontes de conhecimento

`POST /agents/{agentId}/kb-sources` — envie `kb_source_ids` com uma lista para anexar um conjunto completo numa única chamada (o que pretende após rastrear um site), ou `kb_source_id` para uma única fonte. Envie uma ou outra. Anexar algo que já está anexado não altera nada.

```bash
curl -X POST "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/kb-sources?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "kb_source_ids": ["kb2QwErTyUi9OpAs", "kb6ZxCvBnM4kLjHg"] }'
```

**Resposta** (`200`)

```json
{
  "success": true,
  "agent_id": "ag7HkQ2ZpLxR3mNb",
  "kb_source_id": "kb2QwErTyUi9OpAs",
  "kb_source_ids": ["kb2QwErTyUi9OpAs", "kb6ZxCvBnM4kLjHg"]
}
```

### Desanexar fontes de conhecimento

`DELETE /agents/{agentId}/kb-sources/{kbSourceId}` para um, ou `POST /agents/{agentId}/kb-sources/bulk-remove` com `kb_source_ids` para vários. A remoção em massa é um `POST` porque a lista de IDs é enviada no corpo do pedido.

```bash
curl -X POST "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/kb-sources/bulk-remove?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "kb_source_ids": ["kb2QwErTyUi9OpAs"] }'
```

As fontes em si não são eliminadas e permanecem disponíveis para os seus outros Agentes. Desanexar algo que não está anexado não altera nada.

### Perguntas Frequentes (FAQs)

As FAQs são geridas nos seus próprios endpoints e ligadas a um Agente a partir daí: `POST /faqs/{faqId}/link` com `{ "agent_id": "ag7HkQ2ZpLxR3mNb" }`, e `POST /faqs/{faqId}/unlink` para a remover novamente. Uma FAQ pode ser partilhada por qualquer número de Agentes. Consulte a [API de FAQs](faqs.md).

> Uma FAQ só é utilizada pelos Agentes aos quais está ligada — criá-la não é suficiente por si só.

---

## Ferramentas

### Funções personalizadas

`POST /agents/{agentId}/custom-functions` permite que o Agente chame uma das suas funções personalizadas durante as conversas. Apenas funções pertencentes à mesma conta podem ser anexadas, e anexar uma que já esteja anexada não altera nada.

```bash
curl -X POST "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/custom-functions?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "custom_function_id": "cf7Hk2ZpLxR3mNbV" }'
```

`DELETE /agents/{agentId}/custom-functions/{customFunctionId}` desanexa-a. A função em si não é eliminada e permanece disponível para os seus outros Agentes.

Faça a gestão das funções em `/custom-functions` — consulte [Funções Personalizadas](../ai-automation/custom-functions.md) para saber o que são.

### Servidores MCP

Um servidor MCP é um conjunto pronto a usar de ferramentas que o seu Agente pode descobrir e chamar autonomamente — consulte [Ligar Servidores MCP ao seu Bot](../ai-automation/mcp-servers.md). Os servidores são registados uma vez na conta e, em seguida, anexados aos Agentes que os devem utilizar.

> Os servidores MCP requerem a funcionalidade de **funções personalizadas** no seu plano. Sem ela, os endpoints `/mcp-servers` ao nível da conta devolvem `403`. Anexar um servidor já registado a um Agente não está restringido.

#### Registar um servidor

`POST /mcp-servers`

| Campo | Obrigatório | Descrição |
|---|---|---|
| `name` | Sim | Uma etiqueta para o servidor. |
| `url` | Sim | O endereço do servidor. Deve ser acessível através da internet pública. |
| `auth_type` | Não | `header` (o predefinido) para um cabeçalho de autenticação estático, ou `oauth2`. |
| `auth_header_name` | Não | Cabeçalho para enviar a credencial. O predefinido é `Authorization`. |
| `auth_header_value` | Não | A própria credencial. Nunca é devolvida em nenhuma resposta. |
| `enabled` | Não | Se o servidor está disponível para os Agentes. O predefinido é `true`. |
| `enabled_tools` | Não | Lista de permissões de nomes de ferramentas. `null` significa que todas as ferramentas que o servidor oferece estão ativas. |
| `tool_policies` | Não | Limites por ferramenta, indexados pelo nome da ferramenta — com que frequência uma ferramenta pode ser executada, colocação de resultados em cache e uma substituição de apenas leitura. Passe `null` para limpar todos. |

```bash
curl -X POST "https://api.youraiconnector.com/v1/mcp-servers?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Inventory",
    "url": "https://tools.example.com/mcp",
    "auth_header_value": "Bearer sk_live_xxx"
  }'
```

**Resposta** (`201`)

```json
{
  "success": true,
  "server_id": "ms4TgBnH7yUj2kLp",
  "tools": [{ "name": "check_stock", "description": "Look up stock for a SKU." }],
  "last_error": null,
  "server": { "server_id": "ms4TgBnH7yUj2kLp", "name": "Inventory", "...": "..." }
}
```

Ao guardar, a plataforma liga-se ao servidor e coloca em cache a lista de ferramentas que este oferece. **Um servidor que não pode ser alcançado é guardado na mesma**, com o motivo em `last_error` e uma lista de ferramentas vazia — para que possa registar primeiro e corrigir a conectividade depois.

Um `auth_type` de `oauth2` guarda o registo com `oauth_connected: false` e sem ferramentas: ainda não existe nenhum token. A autorização de um servidor OAuth requer um início de sessão no navegador e é feita a partir do painel de controlo, não através da API.

#### Listar, atualizar e eliminar servidores

- `GET /mcp-servers` — todos os servidores registados, do mais recente para o mais antigo, em `servers`.
- `PUT /mcp-servers/{serverId}` — envie apenas o que pretende alterar. Alterar o URL ou os campos de autenticação testa novamente a ligação e atualiza a lista de ferramentas em cache.
- `DELETE /mcp-servers/{serverId}` — remove o registo e desassocia-o de todos os Agentes e campanhas que o tinham ativado.

```bash
curl "https://api.youraiconnector.com/v1/mcp-servers?apiKey=YOUR_API_KEY"
```

**Os segredos nunca são devolvidos.** As respostas transportam `auth_header_value_set` (um sinalizador `true`/`false` que indica que um valor está armazenado) em vez da credencial, e os tokens OAuth e segredos de cliente permanecem no lado do servidor. Tudo o resto é devolvido: `name`, `url`, `enabled`, `auth_type`, `auth_header_name`, `tools`, `enabled_tools`, `tool_policies`, `oauth_connected`, `tools_cached_at`, `last_connected_at`, `last_error`, `created_at`, `updated_at`.

#### Testar uma ligação

`POST /mcp-servers/test-connection` — liga-se a um servidor e lista as suas ferramentas. Duas formas de a chamar:

- com `server_id` — testa a configuração **guardada** e atualiza a sua lista de ferramentas em cache;
- com um `url` em linha (mais `auth_header_name` / `auth_header_value`) — um teste pré-gravação que não armazena nada.

```bash
curl -X POST "https://api.youraiconnector.com/v1/mcp-servers/test-connection?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://tools.example.com/mcp", "auth_header_value": "Bearer sk_live_xxx" }'
```

**Resposta** (`200`)

```json
{
  "success": true,
  "server_name": "Inventory tools",
  "tools": [{ "name": "check_stock", "description": "Look up stock for a SKU." }]
}
```

Uma falha de ligação **não** é um erro HTTP — obtém um `200` com `success: false` e um `error` que descreve o que correu mal, para que o possa mostrar junto ao campo que o operador está a editar.

#### Associar um servidor a um Agente

Registar um servidor não dá a nenhum Agente acesso ao mesmo. Associe-o:

```bash
curl -X POST "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/mcp-servers?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "mcp_server_id": "ms4TgBnH7yUj2kLp" }'
```

**Resposta** (`200`)

```json
{ "success": true, "agent_id": "ag7HkQ2ZpLxR3mNb", "mcp_server_id": "ms4TgBnH7yUj2kLp" }
```

`DELETE /agents/{agentId}/mcp-servers/{mcpServerId}` desassocia-o novamente. O servidor em si não é eliminado e permanece disponível para os seus outros Agentes. Associar ou desassociar algo que já se encontra nesse estado não altera nada.

---

## Biblioteca de multimédia

A biblioteca de multimédia contém os ficheiros que um Agente pode enviar durante uma conversa — um menu, uma lista de preços, uma fotografia de produto. Um Agente pode ter no máximo **50 itens**.

### Listar multimédia

`GET /agents/{agentId}/media-library`

```bash
curl "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/media-library?apiKey=YOUR_API_KEY"
```

**Resposta** (`200`)

```json
{
  "success": true,
  "agent_id": "ag7HkQ2ZpLxR3mNb",
  "media_items": [
    {
      "id": "mi4RtY7uIoP1aSdF",
      "item_id": "mi4RtY7uIoP1aSdF",
      "media_home": "agent",
      "title": "Spring menu",
      "description": "Send when someone asks what is on the menu.",
      "ai_description": "A one-page menu listing seasonal dishes and prices.",
      "type": "document",
      "media_content_type": "application/pdf",
      "media_url": "https://storage.googleapis.com/...",
      "max_sends_per_conversation": 1,
      "created_at": 1700000000000
    }
  ]
}
```

Os itens armazenados no Agente aparecem primeiro, seguidos de quaisquer itens mais antigos ainda armazenados na campanha a partir da qual o Agente foi criado; `media_home` (`agent` ou `campaign`) indica qual é qual. Dentro de cada grupo, o mais recente aparece primeiro.

> **`media_url` expira após 7 dias.** É a ligação de transferência criada quando o ficheiro foi carregado — trate uma ligação antiga como obsoleta em vez de danificada e volte a ler a lista para obter uma ligação atualizada.

### Carregar multimédia

`POST /agents/{agentId}/media-library` — o ficheiro é carregado inline como base64, até **10 MB**. A chamada termina assim que o ficheiro é armazenado, por isso, aguarde um pouco mais do que num pedido normal. Note que este corpo utiliza nomes de campos em camelCase.

| Campo | Obrigatório | Descrição |
|---|---|---|
| `base64Data` | Sim | Conteúdo do ficheiro, codificado em base64, sem um prefixo data-URL. |
| `mimeType` | Sim | Tipo MIME do ficheiro. |
| `fileName` | Sim | Nome original do ficheiro, utilizado para nomear o ficheiro armazenado. |
| `title` | Não | Etiqueta curta apresentada na biblioteca. |
| `description` | Não | A instrução "quando deve o Agente enviar isto". |
| `sendMessage` | Não | Texto preferencial que o Agente diz quando envia o item. Limitado a 500 caracteres. |
| `maxSendsPerConversation` | Não | Quantas vezes pode ser enviado para o mesmo contacto numa conversa. O valor predefinido é `1`. |
| `sendAsVoiceNote` | Não | Apenas carregamentos de áudio — armazena o ficheiro como uma nota de voz do WhatsApp. Ignorado para outros tipos de ficheiro. |

```bash
curl -X POST "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/media-library?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "base64Data": "JVBERi0xLjQKJcfs...",
    "mimeType": "application/pdf",
    "fileName": "spring-menu.pdf",
    "title": "Spring menu",
    "description": "Send when someone asks what is on the menu.",
    "maxSendsPerConversation": 1
  }'
```

Duas coisas acontecem automaticamente: um GIF animado é convertido em vídeo para que seja reproduzido em todos os canais, e a plataforma escreve um breve resumo do que está realmente no ficheiro para que o Agente saiba quando este é adequado.

Um `400` cobre campos em falta, um tipo de ficheiro não suportado, um ficheiro vazio ou demasiado grande, e atingir o limite de 50 itens. Um `403` significa que a biblioteca de multimédia está desativada para a conta.

### Atualizar um item de multimédia

`PATCH /agents/{agentId}/media-library/{itemId}` — apenas metadados. O ficheiro em si não pode ser substituído; carregue um novo item e elimine o antigo. Este corpo utiliza snake_case: `title`, `description`, `send_message`, `max_sends_per_conversation` (um número inteiro não negativo, ou `null` para limpar o limite).

```bash
curl -X PATCH "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/media-library/mi4RtY7uIoP1aSdF?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "title": "Summer menu", "max_sends_per_conversation": 2 }'
```

**Resposta** (`200`)

```json
{
  "success": true,
  "agent_id": "ag7HkQ2ZpLxR3mNb",
  "item_id": "mi4RtY7uIoP1aSdF",
  "campaign_id": "",
  "media_home": "agent"
}
```

### Eliminar um item de multimédia

`DELETE /agents/{agentId}/media-library/{itemId}` — remove o item e o seu ficheiro armazenado. Eliminar um item que já não existe é bem-sucedido e reporta `deleted: false`, pelo que a chamada é segura para repetir.

```bash
curl -X DELETE "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/media-library/mi4RtY7uIoP1aSdF?apiKey=YOUR_API_KEY"
```

---

## Gerar mensagens de seguimento

`POST /agents/{agentId}/template-generation` — escreve as mensagens de seguimento do Agente por si (os lembretes que este envia quando uma conversa fica inativa), com base na finalidade do Agente.

| Campo | Descrição |
|---|---|
| `type` | `all` (a predefinição) escreve todo o conjunto. `cold_only` escreve apenas as mensagens para contactos que nunca responderam. |

```bash
curl -X POST "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/template-generation?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "type": "all" }'
```

Existem duas formas de isto ser devolvido, e o campo `target` indica-lhe qual:

- **`target: "agent"` com um `200`** — as mensagens foram escritas durante a chamada e o resultado encontra-se em `data`. Leia-as a partir do `follow_up_config` do Agente. Este é o caso habitual.
- **`target: "campaign"` com um `202`** — o trabalho foi colocado na fila de espera da campanha nomeada em `campaign_id`. Monitorize o `template_generation_status` dessa campanha até que termine.

O `cold_only` necessita de uma campanha de saída e é recusado com `409` (`reason: "cold_only_requires_campaign"`) num Agente que não tenha nenhuma. Um `403` significa que os seguimentos automáticos não estão ligados para a conta. Isto utiliza créditos de IA, e um `400` com `"Insufficient credits."` significa que a conta não tem saldo.

---

## Encaminhar conversas para um Agente

Um Agente apenas responde às conversas que um **Ponto de Entrada** lhe envia. Até que um canal tenha um, uma primeira mensagem de alguém com quem nunca falou continua a ser guardada, mas nada a recolhe e nenhum assistente responde.

| O que pretende fazer | Chamada |
|---|---|
| Tornar um Agente o responsável pelas respostas de um canal inteiro | `PUT /entry-points/channel-defaults` com `{ "channel": "instagram", "agent_id": "AGENT_ID" }` |
| Adicionar uma regra mais específica (palavras-chave, comentários, novos seguidores) | `POST /agents/{agentId}/entry-points` |
| Ver as regras que apontam para um Agente | `GET /agents/{agentId}/entry-points` |
| Deixar um canal sem ninguém a responder | `DELETE /entry-points/channel-defaults?channel=instagram` |

### Listar os Pontos de Entrada de um Agente

`GET /agents/{agentId}/entry-points` — as regras de encaminhamento que enviam conversas para este Agente, da mais recente para a mais antiga. São devolvidas tanto as regras atuais como as retiradas; uma regra retirada tem `enabled: false`.

```bash
curl "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/entry-points?apiKey=YOUR_API_KEY"
```

Para as predefinições de canal de toda a conta, incluindo um canal deliberadamente definido para ninguém, leia `GET /entry-points/channel-defaults` em vez disso.

### Criar um Ponto de Entrada

`POST /agents/{agentId}/entry-points` — o Agente no caminho ganha sempre, pelo que nunca pode ser criada uma regra para um Agente diferente daquele que consta no URL.

| `type` | O que faz |
|---|---|
| `channel_default` | O Agente responde a cada novo contacto nos canais listados. Prefira `PUT /entry-points/channel-defaults` para isto — retira o responsável anterior por si, o que a criação de uma segunda predefinição aqui não faz. |
| `keyword` | O Agente assume o controlo quando a primeira mensagem contém uma das `match_config.keywords`. É necessária pelo menos uma palavra-chave. |
| `instagram_comment` / `facebook_comment` | O Agente responde a comentários nas suas publicações. O canal correspondente deve estar listado em `channels`. |
| `instagram_follower` | O Agente saúda novos seguidores. |

`channels` é obrigatório e indica quais os canais que a regra abrange — por exemplo `whatsapp`, `whatsapp_web`, `instagram`, `messenger`, `telegram`, `sms`, `email`, `chat_widget` ou `custom_channel`. As novas regras são ativadas, a menos que indique o contrário.

```bash
curl -X POST "https://api.youraiconnector.com/v1/agents/ag7HkQ2ZpLxR3mNb/entry-points?apiKey=YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "keyword",
    "channels": ["whatsapp", "instagram"],
    "match_config": { "keywords": ["pricing", "quote"] }
  }'
```

**Resposta** (`201`)

```json
{ "success": true, "entry_point_id": "ep3KmQ8vTzXr5nWd" }
```

**Que regra ganha quando várias podem ser aplicadas:** uma conversa em curso ou uma atribuição manual mantém o Agente que já tem; caso contrário, as regras de palavra-chave superam as regras de comentário, que superam as regras de seguidor, e uma predefinição de canal é o último recurso. Se estas regras decidem algo numa conta é algo reportado por `GET /entry-points/routing-status`.

Esta é a versão curta. O guia da [Entry Points API](entry-points.md) cobre todas as regras de ladder, comentários e seguidores, um Agente por número de WhatsApp, e a alteração ou eliminação de uma regra. Consulte [Entry Points](../ai-agents/entry-points.md) para o conceito, e a [Channels API](channels.md) para ligar o próprio canal.

---

## Erros da API de Agentes de IA

Os endpoints de Agente devolvem o envelope de erro padrão:

```json
{
  "success": false,
  "error": "Agent not found"
}
```

| Estado | Quando ocorre num endpoint de Agente |
|---|---|
| `400` | Falta um campo obrigatório ou este é inválido — um corpo de atualização vazio, um valor fora de uma lista permitida (`ai_speed`, `anthropic_model`, `booking_provider`, `mode`, `type`), uma chave que não é um dia da semana em `availability`, um nome de campo com pontos em `bot-config`, ou um id mal formatado no caminho. |
| `403` | A conta não tem permissão para utilizar uma definição que enviou, atingiu o limite de Agentes do seu plano, ou uma funcionalidade de que este endpoint necessita (biblioteca de multimédia, seguimentos, funções personalizadas para servidores MCP) está desativada. Uma alteração que exceda o tamanho de configuração permitido pelo seu plano é recusada com `400`. |
| `404` | O Agente, regra de etiqueta, item de multimédia ou servidor MCP não foi encontrado — ou não existe ou pertence a outra conta. |
| `409` | Algo já está em curso ou a bloquear: uma otimização ou geração de etiquetas está a ser executada, o Agente ainda está associado a uma difusão, Ponto de Entrada ou campanha, ou `cold_only` foi solicitado sem uma campanha de saída. |

Os códigos partilhados que qualquer endpoint pode devolver — `401`, `403` (o seu plano não inclui acesso à API), `429` (limite de taxa) e `500` — estão listados com orientações de repetição em [Erros e Paginação](errors-and-pagination.md).

> **Uma nota sobre o explorador.** Os endpoints `/agents` estão na especificação OpenAPI publicada, pelo que pode consultar os seus campos exatos e executar pedidos em tempo real na [Referência da API](reference.md). Os endpoints `/mcp-servers` ao nível da conta também estão na especificação, pelo que também os pode explorar aí.


---

## Relacionado

- [Agentes de IA](../ai-agents/ai-agents.md) — o que é um Agente, em linguagem simples.
- [Pontos de Entrada](../ai-agents/entry-points.md) — como as conversas são encaminhadas para um Agente.
- [API de FAQs](faqs.md) — crie e ligue o conhecimento a partir do qual o seu Agente responde.
- [API de Canais](channels.md) — ligue os canais nos quais um Agente responde.
- [Ligar Servidores MCP ao Seu Bot](../ai-automation/mcp-servers.md) · [Funções Personalizadas](../ai-automation/custom-functions.md)
- [Referência da API](reference.md) — o explorador de endpoints interativo completo.
