Seu app como camada de dados para IA
Todo app gerado pela Fayz nasce pronto para agentes. Não é um recurso que você liga depois: o mesmo manifesto que descreve telas, rotas e dados também descreve, em contrato tipado, o que uma IA pode ler e fazer naquele app. Um agente que entende esse contrato consulta a agenda, resume o financeiro ou ajusta o estoque — sem que você escreva um endpoint de IA do zero.
Esta página explica o contrato aiTools, o que já vem de graça, como a shell de chat se conecta a um LLM e como um plugin próprio entra nessa camada.
O contrato aiTools
Todo plugin pode declarar um campo aiTools no seu manifesto (PluginManifest.aiTools?: PluginAITool[], em @fayz-ai/core). Cada ferramenta é uma função que um agente pode chamar, descrita num formato que LLMs entendem nativamente — o mesmo shape de function calling que a OpenAI e a Anthropic usam:
type PluginAITool = {
id: string // 'agenda.create-appointment'
name: string // 'createAppointment' — o nome que o LLM chama
description: string // o que a ferramenta faz, em linguagem natural
mode: 'read' | 'persist' // só lê dados, ou grava/muda estado?
parameters?: { // JSON Schema: type:'object', properties, required
type: 'object'
properties: Record<string, { type: string; description?: string }>
required?: string[]
}
permission?: { feature: string; action: 'read' | 'create' | ... }
suggestions?: { label: string }[] // chips de sugestão no chat
category?: string
}
Dois detalhes importam:
modesepara leitura de escrita.readconsulta;persistcria ou muda estado. A shell usa isso para filtrar e para você poder pedir confirmação antes de qualquerpersist.permissionprende a ferramenta ao controle de acesso. A mesma feature/permissão que protege a tela protege a ferramenta. Um agente rodando com o papel de um usuário só enxerga as ferramentas que aquele usuário poderia usar.
14 dos 22 plugins já declaram aiTools hoje — agenda, conversations, crm, dashboard, financial, forms, inventory, marketing, menu, orders, shop, tables, tasks e admin. Ligou o plugin, ganhou as ferramentas dele no contrato.
Exemplos reais do SDK
Estas são ferramentas que existem no código dos plugins hoje — não exemplos inventados:
| Plugin | Ferramenta | mode | O que faz |
|---|---|---|---|
agenda | listAppointments | read | Lista agendamentos de uma data ou período, com filtro por profissional. |
agenda | createAppointment | persist | Cria um agendamento para um cliente com profissional e serviço. |
agenda | checkAvailability | read | Verifica horários livres de um profissional numa data. |
menu | toggleMenuItemAvailability | persist | Marca um item do cardápio como disponível/esgotado. |
financial | getRevenue | read | Devolve o faturamento de um período. |
orders | createOrder | persist | Abre um novo pedido. |
inventory | getLowStock | read | Lista itens abaixo do ponto de reposição. |
conversations | sendMessage | persist | Envia uma mensagem numa conversa. |
dashboard | getKpiSummary | read | Resume os KPIs do negócio. |
O que já vem de graça: ferramentas de core + registries
Além do que cada plugin declara, a shell da Fayz (@fayz-ai/saas) injeta três ferramentas de core sempre presentes, definidas em core-ai-tools.ts:
getBusinessSummary(read) — o panorama do negócio.getTeamMembers(read) — quem está na equipe.navigateTo(read) — leva o usuário a uma tela.
E há um multiplicador: cada registry (entidade) não-readonly do seu app vira uma ferramenta list<Entidade> automaticamente. Registrou products, ganhou listProducts sem escrever nada — o comentário no código é literal: "Each registry gets a basic 'list' tool so plugins get AI capabilities for free." Suas entidades viram consultáveis por um agente só por existirem.
A shell de chat — e a fronteira honesta
A shell já traz a UI: um FAB de chat e um painel (ChatFab, ChatPanel), com chips de sugestão vindos das aiTools e filtragem por permissão e vertical via o hook useAITools. O usuário vê as ferramentas certas e sugestões prontas.
Mas o useChat é traga-seu-endpoint (BYO endpoint). Ele faz POST do histórico da conversa para um apiEndpoint no formato OpenAI que você configura. Sem endpoint, a resposta é um mock de demonstração.
O SDK não executa ferramentas. PluginAITool não tem handler — ele é um schema, não uma implementação. Quem recebe o tool_call do LLM, roda a ação contra o Supabase (respeitando RLS) e devolve o resultado é o backend do dono do app. O SDK entrega o contrato e a UI; o loop de execução é seu. Nunca presuma que a Fayz "roda o agente" por você.
A arquitetura-alvo, honesta sobre o que existe:
┌─────────────┐ histórico (tools ficam no seu backend) ┌──────────────────┐
│ ChatPanel │ ─────────────────────────────────────▶ │ seu apiEndpoint │
│ (shell UI) │ │ (seu backend) │
│ useAITools │ ◀───────────────────── │ + LLM (Claude/…) │
└─────────────┘ resposta / tool_call └────────┬─────────┘
▲ │ executa a tool
│ schemas de aiTools ▼
│ (do manifesto) ┌──────────────────┐
└───────────────────────────────── │ Supabase + RLS │
│ (dados do tenant) │
└──────────────────┘
A shell fornece os schemas (o que existe) e a UI. Seu endpoint fornece o LLM e a execução. O RLS garante que o agente só toca os dados do tenant certo.
Cenários práticos
Escritos como arquitetura-alvo sobre o que já existe — os schemas estão prontos; falta você plugar o endpoint:
- Assistente que consulta a agenda e marca. O LLM recebe
listAppointments,checkAvailabilityecreateAppointment. "Encaixa a Sarah amanhã de manhã?" → ele chamacheckAvailability, escolhe o horário e propõecreateAppointment(que épersist— você pede confirmação). - Resumo financeiro por chat.
getRevenue+getKpiSummaryalimentam "como foi a semana?" com números reais do tenant, não estimativa. - Agente de estoque.
getLowStockacha o que está acabando; umpersistde reposição (quando você o declarar) fecha o ciclo.
Um aiTool de verdade, em JSON
O schema que o seu endpoint entrega ao LLM — adaptado do createAppointment real do plugin-agenda:
{
"name": "createAppointment",
"description": "Creates a new appointment for a client with a specific professional and service.",
"parameters": {
"type": "object",
"properties": {
"client": { "type": "string", "description": "Client name" },
"professional": { "type": "string", "description": "Professional name" },
"service": { "type": "string", "description": "Service name" },
"date": { "type": "string", "description": "Date (YYYY-MM-DD)" },
"time": { "type": "string", "description": "Time (HH:MM)" }
},
"required": ["client", "professional", "service", "date", "time"]
}
}
O mode: 'persist' e o permission ficam no manifesto (não vão ao LLM) — são o que a shell e o seu backend usam para gate e confirmação.
Como um plugin próprio entra nessa camada
Simples: declare aiTools no manifesto. O fayz create plugin já emite o array (vazio) — é só preencher. Uma ferramenta bem feita:
- Tem
nameverbo-substantivo claro (listLeads,createOrder). - Declara
modehonesto —persistpara tudo que muda estado. - Descreve
parameterscomdescriptionem cada campo (o LLM lê isso). - Amarra
permissionà mesma feature da tela.
Feito isso, seu plugin aparece no chat, nas sugestões e no contrato que o agente lê. Para os campos completos, veja o Manifesto do plugin — referência. Para conectar o agente a este Dev Center, veja Conecte seu agente.