Spec: configuração da IA via Google Docs (autonomia do gestor)

Externaliza a parte de negócio do systemMessage (tom de voz,
saudação, horário, regras específicas da clínica) para um Google Doc
por clínica, público para leitura (sem credencial OAuth) e editável
só pela conta do gestor. docId fixo por workflow, setado uma vez na
instalação. Regras fixas de segurança (não duplicar agendamento,
fuso horário, confirmar nome) continuam hardcoded no n8n, nunca
editáveis por fora -- documentado como decisão de segurança, com a
limitação conhecida de que a separação é só de prioridade no prompt,
não um bloqueio técnico real.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Gustavo
2026-08-11 09:38:39 -03:00
co-authored by Claude Sonnet 5
parent a56bf09c88
commit 09488fa11c
@@ -0,0 +1,138 @@
# Design — Configuração da IA via Google Docs (autonomia do gestor)
**Data:** 2026-08-11
**Status:** Aprovado pelo usuário, aguardando plano de implementação.
## Objetivo
Hoje o `systemMessage` do AI Agent (prompt do agente de agendamento) é
texto fixo, hardcoded dentro de cada workflow n8n. Isso não escala: o
projeto está migrando para 1 workflow de agente por clínica/cliente
(Z-PRO em produção, Klingo/SysLife/ClinicAll com MCP Server nativo
prontos), e o número de clientes deve crescer — editar manualmente o
`systemMessage` de cada workflow toda vez que um gestor quiser ajustar
tom de voz, saudação, horário de funcionamento ou uma regra específica
da clínica não é sustentável.
Este design externaliza a **parte de negócio** da configuração da IA
para um Google Doc por clínica, editável diretamente pelo gestor daquela
clínica, sem depender de ninguém mexer no n8n depois da instalação
inicial.
## Escopo: o que é editável vs. o que fica fixo
**Editável pelo gestor (dentro do Google Doc, texto livre)**: tom de
voz, saudação, horário de funcionamento, e qualquer regra de negócio
específica da clínica (ex.: "não atendemos convênio X", "sempre
perguntar se é retorno").
**Fixo no n8n, nunca editável por fora** (mesmas regras já validadas em
produção no Z-PRO, ver `docs/n8n-agendamento-runbook.md`, seções 9-12):
- Nunca agendar mais de uma vez na mesma conversa.
- Datas/horários sempre com offset `-03:00` explícito, nunca `Z`/UTC.
- Sempre confirmar o nome completo do paciente antes de agendar.
- Data de hoje via `$now.setZone('America/Sao_Paulo')` (o modelo não tem
acesso à data real sem isso).
- Formato de resposta curto, adequado a WhatsApp.
Essa separação é uma decisão de segurança, não só de organização: as
regras fixas protegem contra duplicidade de agendamento e erros de
fuso horário — nunca podem ficar sujeitas a edição por alguém fora da
equipe técnica.
**Limitação conhecida, não resolvida por este design**: o
`systemMessage` final é montado concatenando as regras fixas com o
conteúdo do Doc. Se o gestor escrever no Doc algo que conflite com uma
regra fixa (ex.: tentar instruir o bot a pular a confirmação do nome),
isso é mitigado só pela ordem/redação do prompt (regras fixas vêm
primeiro, redigidas com prioridade), não por um bloqueio técnico real —
um modelo de linguagem pode, em tese, ser convencido a ignorar
instruções anteriores. Isso é uma limitação inerente a prompts de LLM,
não específica deste design, e fica documentada como tal.
## Arquitetura
```
[Webhook] → [Normalizar entrada] → [Buscar config da clínica] → [AI Agent] → ...
(HTTP GET no Google Doc
público, sem credencial)
```
- **Google Doc por clínica**: compartilhado como "qualquer pessoa com o
link pode **visualizar**" (leitura pública, sem exigir login) + edição
liberada só para a conta Google do gestor daquela clínica.
- **Leitura sem credencial**: a URL de exportação em texto puro do
Google Docs (`https://docs.google.com/document/d/<docId>/export?format=txt`)
é acessível via HTTP GET simples, sem OAuth — porque o Doc é público
pra leitura. Isso evita configurar uma credencial Google OAuth no n8n
só pra isso.
- **`docId` fixo por workflow**: mesmo padrão já usado nos outros
providers (`clinicId` fixo no Z-PRO, `baseUrl` fixo no
Klingo/SysLife/ClinicAll) — um node `Set` ("Config Clínica") com o
`docId` daquela clínica, ajustado manualmente **uma vez**, na
instalação do workflow daquela clínica. Depois disso, toda atualização
de conteúdo passa a ser feita pelo gestor editando o Doc diretamente —
nenhuma mudança no n8n é necessária.
## Componentes
### Node novo: "Buscar config da clínica" (`HTTP Request`)
- `GET https://docs.google.com/document/d/{{ $json.docId }}/export?format=txt`
- Sem autenticação.
- `onError: continueErrorOutput` — falha segura, ver seção abaixo.
### `systemMessage` do AI Agent — nova estrutura
Montado por expressão, concatenando:
1. As regras fixas de negócio (texto que já existe hoje no
`systemMessage`, sem alteração de conteúdo).
2. Um separador textual fixo (ex.: `"Instruções específicas desta
clínica:"`).
3. O conteúdo lido do Doc (`$json.docContent` ou equivalente).
As regras fixas continuam vindo **primeiro** no prompt final — mitigação
de prioridade, não bloqueio técnico (ver "Limitação conhecida" acima).
### Falha segura
Se a busca no Doc falhar (link mudou, Doc apagado/despublicado, timeout,
erro de rede), o node HTTP tem `onError: continueErrorOutput`, e o
`systemMessage` cai para as regras fixas **sem** a seção de instruções
específicas da clínica — o atendimento continua funcionando (só sem a
personalização), em vez de quebrar. Mesmo espírito do node "Erro -
Resposta padrão" que já existe no workflow do Z-PRO para outras falhas.
## Rollout
Aplicado primeiro no Z-PRO (único workflow de agente em produção real
até agora), com um Doc de teste, comparando respostas do agente
antes/depois da mudança para confirmar que as regras fixas continuam
valendo integralmente. Klingo, SysLife e ClinicAll ainda não têm
workflow de agente (só os MCP Servers) — o padrão "Config Clínica" com
`docId` já fica pronto pra ser replicado quando esses workflows forem
criados, sem trabalho adicional de design.
## Fora de escopo
- Qualquer mecanismo de validação/sanitização automática do conteúdo do
Doc contra as regras fixas — a mitigação é só de prompt (ver
"Limitação conhecida").
- Interface própria de edição (formulário, portal) — o Google Doc *é*
a interface, sem camada adicional.
- Cache do conteúdo do Doc entre execuções — cada conversa busca a
versão mais recente do Doc a cada chamada (sem necessidade de
sincronização em tempo real, e sem risco de servir conteúdo
desatualizado).
## Testes
Sem framework de teste automatizado (workflow n8n). Validação manual:
editar o Doc de teste, rodar uma conversa real com o Z-PRO, confirmar
que o tom/conteúdo do Doc aparece nas respostas do agente e que as
regras fixas (confirmar nome, não duplicar agendamento, fuso horário)
continuam sendo respeitadas. Testar também o caminho de falha (apontar
`docId` pra um Doc inexistente/despublicado) para confirmar que o
atendimento não quebra.