Esta é uma tradução automática do documento original em inglês. Em caso de conflito entre esta tradução e a versão original em inglês, a versão em inglês prevalecerá. Ler a versão original em inglês


API Pública

O Caiioo inclui uma API REST que permite controlar tudo programaticamente: executar agentes, gerenciar ferramentas, agendar tarefas e muito mais. A API reside no mesmo servidor local que alimenta o app de desktop e o bridge do navegador.

URL Base: http://localhost:3847/v1

Autenticação: Duas formas de autenticação, ambas controladas pela chave da API nas configurações:

Para consumidores externos (scripts, integrações, curl): Defina um token de acesso à API em Configurações > Acesso à API e use-o como um token Bearer:

curl -H \"Authorization: Bearer SEU_TOKEN_API\" http://localhost:3847/v1/providers

Para o app local (automático): O app de desktop Caiioo, extensões de navegador e apps móveis autenticam-se automaticamente via o cabeçalho de autenticação de relay existente (x-relay-auth; cabeçalhos HTTP não diferenciam maiúsculas de minúsculas). Nenhuma configuração manual é necessária — o app cuida disso nos bastidores. Requisições com relay-auth ignoram a chave Ativar API Pública, pois já são confiáveis; apenas requisições com token bearer são controladas pela chave.

Configuração:

  1. Abra Configurações do Caiioo > Acesso à API
  2. Ative Ativar API Pública
  3. Defina um token de acesso à API (qualquer string que você escolher — trate-a como uma senha)
  4. Use esse token em todas as requisições da API

A API está disponível em localhost e através do relay privado. Verifique GET /v1/auth/info (sem autenticação necessária) para o status atual e instruções de configuração.

Limites de taxa: cada requisição /v1/* é limitada por IP do cliente — 100 requisições GET por minuto para leitura e 30 requisições de escrita por minuto (POST / PATCH / DELETE) combinadas. Requisições acima do limite recebem 429. Entregas de webhooks (POST /v1/webhooks/:id) não são autenticadas por bearer e não estão sujeitas a esses limites.

Perfis

Um único dispositivo pode conter vários perfis de usuário (ex: pessoal + trabalho). A API permite que scripts externos inspecionem os perfis disponíveis e alternem o perfil ativo antes de realizar outras tarefas. A criação, atualização e exclusão de perfis não são deliberadamente expostas via API pública — esses fluxos pertencem à UI de integração (onboarding) do app.

Listar perfis:

GET /v1/profiles

Retorna { profiles: [...] } com uma entrada por perfil não excluído. Cada entrada inclui id, name, email, avatarUrl, tier, accessibleModes, license, organization, preferences, onboardingComplete, createdAt, lastAccessedAt. Campos que contêm tokens (serviceCredentials, oauthConnections) e internos de sincronização (vectorClock, lastModifiedBy) são removidos. Use /v1/connectors para inspecionar conexões OAuth.

Obter o perfil ativo:

GET /v1/profiles/active

Retorna { profile } para o perfil atualmente em uso por este servidor. Todos os recursos /v1/* vinculados a um perfil (threads, anexos, configurações, skills) operam contra este.

Alternar o perfil ativo:

PUT /v1/profiles/active
Content-Type: application/json

{ "profileId": "user-uuid-from-list" }

Retorna { profile } para o perfil recém-ativado. Retorna 404 se o ID não for um perfil conhecido.

Provedores & Modelos

Descubra quais provedores de LLM estão configurados e quais modelos estão disponíveis.

Listar provedores:

GET /v1/providers

Retorna todos os tipos de provedores suportados. Atualmente: anthropic, openai, google, openrouter, ollama, poe, mlx, perplexity, baseten, cloudflare. Cada entrada inclui type, displayName, icon, requiresApiKey, hasApiKey e um objeto capabilities com as flags abaixo.

Flag de capacidade Significado
supportsVision O provedor pode aceitar entradas de imagem
supportsPdfFile O provedor pode aceitar blocos de conteúdo de arquivos PDF nativamente
supportsToolCalling O provedor suporta chamada de funções/ferramentas (tool calling)
supportsStreaming O provedor transmite tokens de forma incremental
supportsExtendedThinking O provedor expõe um orçamento de raciocínio/pensamento
supportsPromptCaching O provedor suporta diretivas de cache de prompt
nativeReasoningBlocks O provedor emite o pensamento como blocos de mensagem nativos (em vez de texto)
requiresThoughtSignature O provedor exige que tokens de pensamento assinados sejam ecoados de volta

As flags de capacidade espelham o campo readonly capabilities de cada classe de provedor (consulte src/shared/providers/*-provider.ts) e são validadas por um teste sentinela de desvio — chame este endpoint em tempo de execução em vez de codificar a matriz de forma estática.

Notas para os provedores BYOK:

  • perplexity expõe uma lista selecionada de modelos Sonar (a Perplexity não possui um endpoint /models público).
  • cloudflare (AI Gateway) é BYOK + multi-vendedor; a lista de modelos é determinada pela configuração do seu gateway e é retornada como um array vazio por /v1/providers/cloudflare/models. Utilize o seu próprio catálogo de gateway.

Listar modelos de um provedor:

GET /v1/providers/openrouter/models

Retorna o catálogo de modelos para aquele provedor. Cada modelo inclui id, displayName e contextLength quando disponível. Retorna 503 quando o provedor não possui uma API key ou seu catálogo de origem está inacessível.

Catálogo unificado de todos os provedores:

GET /v1/models

Mescla modelos de todos os provedores configurados em uma única lista. Provedores sem API keys são ignorados e listados em warnings.

Agentes

Agentes são o núcleo do caiioo. Cada agente é um Modo — uma personalidade configurada com seu próprio prompt de sistema, ferramentas, variáveis e skills.

Listar todos os agentes:

GET /v1/agents

Retorna agentes integrados (Shopping, Workplace, Geral) e quaisquer agentes personalizados que você criou. Cada um é marcado com source: \"builtin\" ou source: \"custom\".

Criar um agente personalizado:

POST /v1/agents
Content-Type: application/json

{
  \"id\": \"meu-agente-de-pesquisa\",
  \"branding\": {
    \"name\": \"Agente de Pesquisa\",
    \"description\": \"Pesquisa na web e resume descobertas\"
  },
  \"defaultSettings\": {
    \"systemPrompt\": \"Você é um assistente de pesquisa. Sempre cite as fontes.\",
    \"enabledTools\": { \"web_browsing\": true, \"search_tools\": true }
  },
  \"settingLevels\": {}
}

Retorna 201 com o agente criado. Um vector clock é anexado automaticamente para sincronização.

Atualizar um agente:

PATCH /v1/agents/meu-agente-de-pesquisa
Content-Type: application/json

{ \"branding\": { \"name\": \"Agente de Pesquisa\", \"description\": \"Descrição atualizada\" } }

Mescla o patch no agente existente e incrementa o vector clock. Agentes integrados retornam 403 — eles são apenas leitura.

Deletar um agente:

DELETE /v1/agents/meu-agente-de-pesquisa

Exclusão lógica via tombstone (sincroniza entre dispositivos). Retorna 204.

Executando Agentes

Este é o evento principal — invocar um agente para processar uma mensagem.

Corpo da requisição — campos suportados

Campo Obrigatório Descrição
agentId sim ID do modo integrado (ex: general) ou um ID de agente personalizado
input.message sim Texto da mensagem do usuário
input.attachments não Array de IDs de anexos (já carregados via /v1/attachments) para anexar a este turno
input.variables não Substituições de variáveis por execução mescladas ao resolvedor de variáveis do agente
input.tabContext não String de formato livre injetada como contexto de página (usada pela ponte do navegador)
input.messageId não ID da mensagem fornecido pelo cliente — útil para deduplicação em caso de nova tentativa
threadId não Thread existente para continuar. Se omitido, uma nova thread é criada e retornada
mode não "sync" ou "async". O padrão é "async"

Modo Síncrono

Aguarde a resposta completa:

POST /v1/runs
Content-Type: application/json

{
  "agentId": "general",
  "input": { "message": "What's the weather in Paris today?" },
  "mode": "sync"
}

Retorna 200 com { content, usage, status: "completed" } após o agente terminar. Se o agente falhar, retorna 500 com { error, status: "error" }. Execuções síncronas expiram após 5 minutos com status: "error" se nenhum evento terminal for recebido — use async + SSE para qualquer tarefa que possa demorar mais.

Modo Assíncrono

Dispare e esqueça — útil para tarefas de longa duração:

POST /v1/runs
Content-Type: application/json

{
  "agentId": "my-research-agent",
  "input": { "message": "Write a 2000-word analysis of renewable energy trends" },
  "mode": "async"
}

Retorna 202 imediatamente com { runId, threadId, status: "running" }.

Consultar status (Poll):

GET /v1/runs/{runId}

Retorna { run: { runId, threadId, agentId, status, createdAt, content?, usage?, error? } }. O status é um entre running, completed, error ou cancelled.

Transmitir eventos em tempo real (SSE):

GET /v1/runs/{runId}/events

Retorna um text/event-stream com cada evento do agente conforme ele acontece: GENERATION_STARTED, STREAMING_CONTENT, chamadas de ferramentas, atividade de subagentes e o evento terminal (GENERATION_COMPLETE, GENERATION_ERROR ou GENERATION_CANCELLED).

Após o evento terminal, o servidor emite um quadro SSE final com event: terminal e um payload de dados vazio como uma sentinela explícita de fim de transmissão, e então fecha a conexão. Os clientes devem tratar o recebimento desse quadro (ou o fechamento da conexão) como o sinal para parar a leitura.

Se você se inscrever após a execução já ter terminado, o servidor reproduz um quadro do tipo RUN_SNAPSHOT contendo o record final completo, seguido pela sentinela event: terminal, e então fecha.

Cancelar uma execução:

POST /v1/runs/{runId}/cancel

Retorna { run: { ..., status: "cancelled" } }.

Threads

Threads são conversas. Cada execução de agente ocorre dentro de uma thread, e as threads persistem entre as sessões. A API permite listar, ler, criar e gerenciar threads programaticamente.

Listar todas as threads (apenas metadados):

GET /v1/threads

Retorna { threads: [...] } para o perfil atual com messages removidas (use o endpoint de detalhes quando precisar delas). Todos os outros campos são preservados — id, title, createdAt, updatedAt, modeId, archived, estatísticas de uso, além de subAgentHistories, anonymizerSnapshot, threadToolApprovals, threadVariables, threadToolOverrides, messagingBinding, scheduledTaskId quando definidos. (O payload mais rico é exclusivo da API — a transmissão da barra lateral via WebSocket usa uma redução maior para permanecer dentro dos limites de transporte.)

Obter uma thread com mensagens completas:

GET /v1/threads/{id}

Retorna a thread completa, incluindo seu array de messages — cada mensagem do usuário, resposta do assistente, chamada de ferramenta e resultado de ferramenta.

Obter apenas as mensagens:

GET /v1/threads/{id}/messages

Retorna apenas o array de messages — mais leve que o objeto de thread completo quando você precisa apenas da conversa.

Criar uma thread:

POST /v1/threads
Content-Type: application/json

{ "title": "Research project", "modeId": "general" }

Retorna 201 com { thread }. A nova thread aparece na barra lateral imediatamente (via transmissão WebSocket). A API nunca altera a thread ativa do app ao criar — chame PUT /v1/threads/active separadamente se desejar isso.

Atualizar uma thread:

PATCH /v1/threads/{id}
Content-Type: application/json

{ "title": "Renamed project", "archived": true }

Campos atualizáveis: title, modeId, archived, lastUsedModel. As alterações são transmitidas para a barra lateral em tempo real.

Excluir uma thread:

DELETE /v1/threads/{id}

Realiza a exclusão lógica (soft-delete) da thread (tombstone para sincronização). Retorna 204. Threads excluídas movem-se para a lixeira e podem ser recuperadas até que a lixeira seja esvaziada.

Thread ativa:

GET /v1/threads/active            # Retorna { threadId }
PUT /v1/threads/active            # Corpo: { "threadId": "..." }

Gerenciamento da lixeira:

GET /v1/threads/trash/count       # Retorna { count }
POST /v1/threads/trash/empty      # Retorna { deletedCount, protectedCount }

Threads protegidas (retidas via a opção de retenção de dados) são excluídas do esvaziamento da lixeira.

Continuando uma conversa via API: Para enviar uma mensagem de acompanhamento em uma thread existente, use POST /v1/runs com o ID da thread:

POST /v1/runs
Content-Type: application/json

{
  "agentId": "general",
  "threadId": "existing-thread-id",
  "input": { "message": "Follow up on that last point" },
  "mode": "sync"
}

O agente visualiza todo o histórico de conversa da thread.

Anexos

Anexos são arquivos vinculados a threads — capturas de tela, PDFs, documentos, imagens carregadas, artefatos gerados. A API permite listar, carregar, baixar e gerenciá-los.

Listar todos os anexos (apenas metadados):

GET /v1/attachments

Retorna metadados de anexos para o perfil atual. Campos pesados (dataUrl, extractedContent, extractedImages) são removidos — use os endpoints de detalhes ou conteúdo para esses.

Listar anexos para um thread específico:

GET /v1/threads/{threadId}/attachments

Obter metadados do anexo:

GET /v1/attachments/{id}

Retorna metadados completos, incluindo extractedContent (texto OCR, markdown analisado), contentType, fileName, size e um sinalizador hasContent. O binário bruto NÃO está incluído — use o endpoint /content para isso.

Baixar binário do anexo:

GET /v1/attachments/{id}/content

Retorna o arquivo bruto com os cabeçalhos Content-Type e Content-Disposition corretos. Direcione isso para um arquivo:

curl -o saida.pdf \
  -H "Authorization: Bearer $API_TOKEN" \
  http://localhost:3847/v1/attachments/{id}/content

Carregar um anexo:

POST /v1/attachments
Content-Type: application/json

{
  "threadId": "thread-id",
  "type": "user_upload",
  "contentType": "application/pdf",
  "fileName": "relatorio.pdf",
  "description": "Relatório trimestral",
  "dataUrl": "data:application/pdf;base64,JVBERi0xLjQ..."
}

A dataUrl é uma URL de dados codificada em base64. Retorna 201 com o novo ID do anexo. O anexo é vinculado ao thread especificado.

Atualizar metadados do anexo:

PATCH /v1/attachments/{id}
Content-Type: application/json

{ "description": "Descrição atualizada", "fileName": "novo-nome.pdf" }

Excluir um anexo:

DELETE /v1/attachments/{id}

Exclusão lógica via tombstone. Retorna 204.

Servidores MCP

Gerencie suas conexões de servidor MCP (Model Context Protocol) — os servidores que dão aos agentes acesso a ferramentas externas e fontes de dados.

Listar servidores configurados:

GET /v1/mcp-servers

Retorna todas as configurações de servidor MCP para o perfil atual. Campos sensíveis (authToken, env, credentialId) são removidos da resposta.

Obter a configuração de um servidor:

GET /v1/mcp-servers/{id}

Adicionar um novo servidor MCP:

POST /v1/mcp-servers
Content-Type: application/json

{
  "id": "my-server",
  "name": "My MCP Server",
  "command": "npx",
  "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/files"],
  "serverType": "local"
}

Para servidores HTTP remotos, use "url" em vez de "command":

{
  "id": "remote-server",
  "name": "Remote API",
  "url": "https://my-mcp-server.example.com/sse",
  "serverType": "remote"
}

Campos opcionais aceitos no POST: command, args, env, url, description, transportType, authType, authToken, authHeader, headers, specType, specPath, timeoutMs, credentialId, oauthConnectionId, approval. Campos gerenciados pelo servidor (customOAuth, hubPackageId, profileId, connectorId, teamPublished, teamOrgId, vectorClock, ...) não podem ser definidos via API.

Atualizar um servidor:

PATCH /v1/mcp-servers/{id}
Content-Type: application/json

{ "name": "Renamed Server", "args": ["-y", "@mcp/server-v2"] }

Os campos editáveis via PATCH espelham a lista de permissões do POST (incluindo credentialId e oauthConnectionId — útil para rotacionar uma conexão OAuth sem precisar excluir e recriar). Campos gerenciados pelo servidor permanecem somente leitura.

Ativar/desativar um servidor:

POST /v1/mcp-servers/{id}/toggle
Content-Type: application/json

{ "enabled": false }

Excluir um servidor:

DELETE /v1/mcp-servers/{id}

Gerenciamento de Processos

Para servidores MCP locais (stdio), você pode gerenciar o processo do servidor diretamente.

Listar processos em execução:

GET /v1/mcp-servers/processes

Retorna os processos do servidor em execução com pid, startedAt e status running.

Iniciar um servidor:

POST /v1/mcp-servers/{id}/start

Lê o comando/args/env da configuração do servidor e inicia o processo. Retorna o status do processo.

Parar um servidor:

POST /v1/mcp-servers/{id}/stop

Encerra graciosamente o processo do servidor (SIGTERM com fallback para SIGKILL).

Chamar um método JSON-RPC diretamente:

POST /v1/mcp-servers/{id}/call
Content-Type: application/json

{ "method": "tools/list", "params": {} }

Envia uma requisição JSON-RPC 2.0 bruta para o servidor e retorna o resultado. Útil para depuração ou para chamar métodos não expostos através da API de ferramentas.

Ferramentas e Toolkits

Navegue e invoque as ferramentas que os agentes utilizam — navegação web, busca, calendário, Gmail, Slate e muito mais.

Listar toolkits (agrupados):

GET /v1/toolkits

Retorna ferramentas incorporadas agrupadas por categoria (Produtividade, Busca, Utilitários, etc.) e quaisquer servidores MCP conectados como toolkits separados, cada um com suas ações listadas.

Listar todas as ferramentas (lista simples):

GET /v1/tools
GET /v1/tools?source=embedded   # Apenas ferramentas integradas
GET /v1/tools?source=mcp        # Apenas ferramentas de servidor MCP

Obter detalhes da ferramenta com esquema de entrada:

GET /v1/tools/calculator

Retorna { tool: { name, displayName, description, source, category, inputSchema, actions?, requiredTier?, requiredRuntimes?, riskTier?, riskExplanation?, requiresApproval? } }.

Campo Significado
inputSchema JSON Schema para a entrada da ferramenta — valide antes de invocar
actions Sub-ações opcionais (ex: Slate read/write); cada uma possui id, displayName, description, requiredTier opcional
requiredTier Nível mínimo de usuário (free se omitido). A invocação via API pública recusa qualquer nível acima de free
requiredRuntimes Plataformas onde esta ferramenta está disponível (macos, ios, etc.); omitir ⇒ em todos os lugares
riskTier Risco de consentimento: low (padrão), medium, high
riskExplanation Razão legível por humanos para o riskTier estar elevado
requiresApproval true quando a ferramenta precisa de aprovação do usuário por chamada — a invocação via API pública recusa estas

Invocar uma ferramenta diretamente:

POST /v1/tools/calculator/invoke
Content-Type: application/json

{ "input": { "expression": "sqrt(144) + 3^2" }, "threadId": "optional-thread-id" }

Retorna { result }. A entrada é validada contra o esquema da ferramenta — entradas inválidas retornam 422 com detalhes. Passe um threadId opcional se a ferramenta precisar de contexto de escopo de thread (ex: busca de anexos).

Restrições — o que a API pública recusa:

  • Ferramentas restritas por nível (metadata.requiredTier !== 'free') → 403. O loop do agente verifica o nível em relação à sessão do usuário; a API pública não possui contexto de nível transportado, portanto, a política conservadora é recusar. Em vez disso, use POST /v1/runs com um agente que possua o nível correto.
  • Ferramentas que exigem aprovação (metadata.approval.requiresApproval === true) → 403. Não há um humano no loop para perguntar. Invoque via POST /v1/runs (que apresenta a solicitação ao usuário) ou defina o modo de aprovação da ferramenta como approve_all no app para ignorar.
  • Ferramentas MCP remotas501 com orientação para usar /v1/runs (elas exigem o transporte de subprocesso do agente).

Ferramentas de visão e uso de imagem: faça o upload via POST /v1/attachments primeiro, depois passe o ID do anexo retornado dentro de input (ex: { "input": { "attachment_id": "att_abc", "prompt": "O que há nesta imagem?" } }). A ferramenta lê o binário do armazenamento via threadId; você não passa os bytes inline.

Conectores

Gerencie integrações OAuth — Google, Microsoft, GitHub, Notion, Slack e mais.

Navegar pelas integrações disponíveis:

GET /v1/connectors/catalog

Retorna todos os provedores OAuth registrados com seu nome, categoria e escopos padrão.

Listar suas contas conectadas:

GET /v1/connectors

Retorna as conexões ativas para o perfil atual. Os tokens nunca são expostos — apenas metadados (provedor, e-mail, status, escopos, carimbos de data/hora).

Obter uma única conexão:

GET /v1/connectors/{id}

Retorna metadados de uma conexão. Os tokens nunca são expostos.

Verificar a saúde da conexão:

POST /v1/connectors/{id}/test

Retorna { health: { status, isTokenExpired, canRefresh } }.

Remover uma conexão:

DELETE /v1/connectors/{id}

A criação de novas conexões requer o fluxo interativo OAuth via interface do app ou as rotas /auth/*.

Gatilhos

Agende agentes para rodar automaticamente — resumos diários, relatórios semanais, monitoramento baseado em intervalos.

Cada gatilho tem um discriminador kind: schedule (padrão — dispara por relógio), webhook (dispara quando um serviço externo faz um POST para o caminho do webhook) ou messaging (dispara de um adaptador de mensagens conectado — ex: mensagens recebidas do Slack/Discord que correspondem a um filtro de canal).

Listar gatilhos:

GET /v1/triggers

Retorna { triggers: [...] }. Cada entrada inclui seu kind, agendamento e campos específicos do tipo.

Obter um único gatilho:

GET /v1/triggers/{id}

Criar um gatilho agendado:

POST /v1/triggers
Content-Type: application/json

{
  \"name\": \"Resumo Matinal\",
  \"prompt\": \"Resuma meus e-mails não lidos e o calendário de hoje\",
  \"modeId\": \"general\",
  \"schedule\": { \"type\": \"daily\", \"time\": \"08:00\" }
}

Tipos de agendamento suportados:

  • { \"type\": \"interval\", \"minutes\": 60 } — a cada N minutos (mín 15, máx 1440)
  • { \"type\": \"daily\", \"time\": \"09:00\" } — diariamente em um horário específico
  • { \"type\": \"weekly\", \"day\": \"mon\", \"time\": \"09:00\" } — semanalmente
  • { \"type\": \"weekdays\", \"time\": \"08:30\" } — de segunda a sexta-feira
  • { \"type\": \"daysOfWeek\", \"days\": [\"mon\", \"wed\", \"fri\"], \"time\": \"10:00\" } — dias específicos
  • { \"type\": \"monthly\", \"dayOfMonth\": 1, \"time\": \"09:00\" } — mensalmente
  • { \"type\": \"manual\" } — apenas quando disparado via API

Disparar um gatilho manualmente:

POST /v1/triggers/{id}/fire

Retorna 202 com um threadId para a execução resultante.

Atualizar ou excluir:

PATCH /v1/triggers/{id}
DELETE /v1/triggers/{id}

Webhooks

Gatilhos de webhook permitem que serviços externos (CI/CD, monitoramento, construtores de formulários) disparem a execução de um agente via HTTP.

Criar um gatilho de webhook:

POST /v1/triggers
Content-Type: application/json

{
  \"name\": \"Deploy hook\",
  \"prompt\": \"Um deploy aconteceu: {{webhook.body}}\",
  \"modeId\": \"general\",
  \"kind\": \"webhook\"
}

Retorna 201 com um webhookSecret e webhookPath. Guarde o segredo — você precisará dele para assinar as cargas úteis.

Enviar um webhook:

# Calcular HMAC-SHA256 do corpo bruto da requisição
SIGNATURE=$(echo -n '{\"repo\":\"my-app\",\"branch\":\"main\"}' | openssl dgst -sha256 -hmac \"$WEBHOOK_SECRET\" | awk '{print $2}')

POST /v1/webhooks/{triggerId}
Content-Type: application/json
X-Webhook-Signature: $SIGNATURE

{\"repo\": \"my-app\", \"branch\": \"main\"}

O endpoint do webhook NÃO requer autenticação bearer — ele usa verificação HMAC. Retorna 202 com o threadId da execução despachada. O marcador {{webhook.body}} no prompt do gatilho é substituído pelo corpo bruto da requisição.

Gatilhos de Mensagens

Gatilhos de mensagens disparam quando um adaptador de mensagens conectado (ex: uma integração Slack ou Discord instalada via Hub da Comunidade) recebe uma mensagem que corresponde ao filtro do gatilho. Crie com kind: \"messaging\":

POST /v1/triggers
Content-Type: application/json

{
  \"name\": \"Respondedor de menção\",
  \"prompt\": \"Responda prestativamente a: {{message.text}}\",
  \"modeId\": \"general\",
  \"kind\": \"messaging\",
  \"messagingAdapterId\": \"slack-team-acme\",
  \"messagingChannelFilter\": \"#support\"
}

O adaptador é responsável por despachar eventos correspondentes para o gatilho; messagingChannelFilter é específico do adaptador.

Funções Personalizadas

Crie suas próprias ferramentas que os agentes podem chamar. As funções são escritas em JavaScript ou Python e executadas em um sandbox.

Listar funções:

GET /v1/functions

Criar uma função:

POST /v1/functions
Content-Type: application/json

{
  "name": "calcular_imc",
  "description": "Calcula o Índice de Massa Corporal a partir da altura e peso",
  "language": "javascript",
  "source": "return { imc: (input.weightKg / (input.heightM * input.heightM)).toFixed(1) };",
  "inputSchema": {
    "type": "object",
    "properties": {
      "weightKg": { "type": "number" },
      "heightM": { "type": "number" }
    },
    "required": ["weightKg", "heightM"]
  }
}

As funções JavaScript recebem input e devem retornar um resultado. As funções Python definem uma variável result:

# Exemplo em Python
result = {"imc": round(input["weightKg"] / (input["heightM"] ** 2), 1)}

Executar uma função diretamente:

POST /v1/functions/{id}/execute
Content-Type: application/json

{ "input": { "weightKg": 75, "heightM": 1.80 } }

Segurança: JavaScript é executado no sandbox vm do Node (sem acesso ao sistema de arquivos ou rede, tempo limite de 10s). Python é executado como um subprocesso com um tempo limite de 30s. Ambos validam a entrada antes da execução.

Atualizar ou excluir:

PATCH /v1/functions/{id}
DELETE /v1/functions/{id}

Skills

Skills são prompts salvos que os agentes podem referenciar e iniciar rapidamente a partir da visualização de conversa em branco. Skills instaladas via Hub (gerenciadas via instalação de pacotes) NÃO estão incluídas aqui — apenas skills criadas pelo usuário são listadas e editáveis.

Listar skills:

GET /v1/skills

Retorna { skills: [...] } de skills criadas pelo usuário para o perfil ativo. Skills marcadas para exclusão (tombstoned), sobreposições do hub e sombras de sincronização são filtradas.

Obter uma skill:

GET /v1/skills/{id}

Criar uma skill:

POST /v1/skills
Content-Type: application/json

{
  "prompt": "Resuma a página em 3 tópicos.",
  "tags": ["utilitário", "resumir"],
  "isFavorite": true,
  "modes": ["general"],
  "displayName": "Resumo Rápido",
  "description": "TL;DR em três tópicos da página ativa"
}

Apenas prompt é obrigatório. modes (opcional) restringe a skill a IDs de agentes específicos; omita para todos os modos. Retorna 201 com a nova skill (incluindo id, createdAt, updatedAt atribuídos pelo servidor).

Atualizar uma skill:

PATCH /v1/skills/{id}
Content-Type: application/json

{ "prompt": "Prompt atualizado", "isFavorite": false }

Campos editáveis: prompt, tags, modes, displayName, description, isFavorite. Tentativas de editar uma skill de sobreposição do hub retornam 404.

Excluir uma skill:

DELETE /v1/skills/{id}

Exclusão lógica via tombstone. Retorna 204. Skills de sobreposição do hub retornam 404 — em vez disso, desinstale o pacote de origem.

Fluxos de Trabalho

Orquestre múltiplos agentes em um DAG (grafo acíclico dirigido) — execute etapas em paralelo sempre que possível e alimente as saídas de etapas anteriores em etapas posteriores.

Validar um grafo de fluxo de trabalho:

POST /v1/workflows/validate
Content-Type: application/json

{
  "graph": {
    "nodes": [
      { "id": "research", "agentId": "general", "prompt": "Pesquisar tendências de energia renovável" },
      { "id": "analyze", "agentId": "general", "prompt": "Pesquisar preços da concorrência" },
      { "id": "report", "agentId": "general", "prompt": "Escrever um relatório combinando: {{outputs.research}} e {{outputs.analyze}}", "dependsOn": ["research", "analyze"] }
    ]
  }
}

Retorna { valid: true/false, errors: [...] }. Verifica ciclos, IDs duplicados e referências de dependência ausentes.

Executar um fluxo de trabalho:

POST /v1/workflows/execute
Content-Type: application/json

{
  "graph": {
    "nodes": [
      { "id": "research", "agentId": "general", "prompt": "Pesquisar tendências de energia renovável" },
      { "id": "summarize", "agentId": "general", "prompt": "Resumir: {{outputs.research}}", "dependsOn": ["research"] }
    ]
  }
}

Retorna { status: "completed", outputs: { research: "...", summarize: "..." }, nodeResults: {...} }.

Nós independentes (sem dependências compartilhadas) são executados em paralelo. O marcador {{outputs.nodeId}} no prompt de um nó é substituído pelo conteúdo de saída do nó upstream nomeado. Cada nó é uma execução completa de agente, portanto, pode usar ferramentas, navegar na web e acessar todos os recursos do agente de destino.

Bases de Conhecimento

Organize documentos em coleções pesquisáveis que os agentes podem consultar.

Listar bases de conhecimento:

GET /v1/knowledge/bases

Criar uma base de conhecimento:

POST /v1/knowledge/bases
Content-Type: application/json

{ "name": "Artigos de Pesquisa" }

Retorna 201 com o novo ID da base.

Carregar um documento para uma base de conhecimento:

POST /v1/knowledge/bases/{id}/documents
Content-Type: application/json

{
  "fileName": "artigo-de-pesquisa.pdf",
  "contentType": "application/pdf",
  "dataUrl": "data:application/pdf;base64,JVBERi0xLjQ...",
  "description": "Tendências de energia renovável 2026"
}

O campo dataUrl é uma URL de dados codificada em base64. Retorna 201 com os metadados do documento.

Listar documentos em uma base de conhecimento:

GET /v1/knowledge/bases/{id}/documents

Pesquisar dentro de uma base de conhecimento:

POST /v1/knowledge/bases/{id}/search
Content-Type: application/json

{ "query": "energia renovável" }

Retorna documentos correspondentes com base no nome do arquivo e na descrição. A pesquisa semântica (vetorial) chegará em uma versão futura.

Excluir um documento ou base de conhecimento:

DELETE /v1/knowledge/bases/{id}/documents/{docId}
DELETE /v1/knowledge/bases/{id}

Exportar e Importar Agentes

Compartilhe agentes como pacotes portáteis — entre dispositivos, equipes ou o Community Hub.

Exportar um agente:

POST /v1/agents/{id}/export

Retorna um pacote JSON contendo a definição do agente, requisitos de ferramentas (derivados das ferramentas habilitadas), requisitos de conectores (quais provedores OAuth são necessários) e templates de gatilhos. Metadados de sincronização são removidos — o pacote é um projeto limpo e autossuficiente.

Importar um agente:

POST /v1/agents/import
Content-Type: application/json

{
  \"package\": {
    \"$schema\": \"caiioo.agent.package/v1\",
    \"agent\": {
      \"id\": \"agente-de-pesquisa-compartilhado\",
      \"branding\": { \"name\": \"Agente de Pesquisa\", \"description\": \"Da equipe\" },
      \"defaultSettings\": { \"systemPrompt\": \"Você pesquisa coisas.\" },
      \"settingLevels\": {}
    },
    \"toolRequirements\": [
      { \"toolId\": \"web_browsing\", \"enabled\": true },
      { \"toolId\": \"search_tools\", \"enabled\": true }
    ]
  }
}

Retorna 201 com o agente instalado. Colisões de ID com agentes integrados ou existentes retornam 409.

Tratamento de Erros

A API usa códigos de status HTTP padrão:

Código Significado
200 Sucesso
201 Criado
202 Aceito (operação assíncrona iniciada)
204 Excluído (sem conteúdo)
400 Requisição inválida — verifique o campo error para detalhes
401 Não autorizado — segredo de sessão ausente ou inválido
403 Proibido — ex: tentando modificar um agente integrado
404 Não encontrado
409 Conflito — ex: ID do agente já existe
422 Erro de validação — a entrada não corresponde ao esquema da ferramenta
429 Limite de taxa excedido — veja os orçamentos na seção de Autenticação
500 Erro de servidor — verifique o campo error
501 Não implementado — o recurso existe mas não está disponível desta forma
503 Serviço indisponível — armazenamento ou provedor não pronto

Todas as respostas de erro incluem { \"error\": \"mensagem legível por humanos\" }.

Exemplo de Início Rápido

Aqui está um fluxo de trabalho completo: criar um agente, executá-lo e transmitir os resultados.

# 1. Criar um agente personalizado
curl -X POST http://localhost:3847/v1/agents \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "quick-summarizer",
    "branding": { "name": "Resumidor Rápido" },
    "defaultSettings": {
      "systemPrompt": "Resuma qualquer entrada de forma concisa em 3 tópicos.",
      "enabledTools": { "web_browsing": true }
    },
    "settingLevels": {}
  }'

# 2. Executá-lo de forma assíncrona
RUN=$(curl -s -X POST http://localhost:3847/v1/runs \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "agentId": "quick-summarizer", "input": { "message": "Resuma https://en.wikipedia.org/wiki/Artificial_intelligence" }, "mode": "async" }')

RUN_ID=$(echo $RUN | jq -r '.runId')

# 3. Transmitir os eventos
curl -N http://localhost:3847/v1/runs/$RUN_ID/events \
  -H "Authorization: Bearer $API_TOKEN"

# 4. Exportar o agente para compartilhamento
curl -X POST http://localhost:3847/v1/agents/quick-summarizer/export \
  -H "Authorization: Bearer $API_TOKEN"

This guide is maintained by the Caiioo team using Slate, our built-in editor.