Plano: configuração da IA via Google Docs (Z-PRO)
6 tasks: verificar estrutura atual antes de modificar (workflow em produção), adicionar os 4 nodes novos (Config Clínica, Buscar config da clínica, Doc OK, Doc falhou), rewire das conexões, estender o systemMessage do AI Agent sem alterar as regras fixas existentes, preencher docId de teste e testar de ponta a ponta (incluindo caminho de falha), atualizar runbook + commit. Disciplina extra por mexer em produção real: validação após cada task, teste de falha obrigatório antes de concluir. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
09488fa11c
commit
1525b2a099
@@ -0,0 +1,303 @@
|
||||
# Configuração da IA via Google Docs Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task (não subagent-driven-development — as tasks são chamadas de API do n8n, não commits de código; não há diff de git pra revisar por task). Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Externalizar a parte de negócio do `systemMessage` do AI Agent do workflow Z-PRO em produção para um Google Doc por clínica, editável diretamente pelo gestor, sem depender de ninguém mexer no n8n depois da instalação inicial.
|
||||
|
||||
**Architecture:** Um node `HTTP Request` novo busca o conteúdo em texto puro do Google Doc (URL de exportação pública, sem credencial) logo antes do AI Agent; o `systemMessage` passa a concatenar as regras fixas de negócio já existentes com o conteúdo do Doc. Falha na busca cai num fallback seguro (regras fixas sem a parte da clínica), nunca quebra o atendimento.
|
||||
|
||||
**Tech Stack:** n8n (`devn8n.gtigrupo.com.br`), `n8n-nodes-base.httpRequest`, `n8n-nodes-base.set`, workflow `Agendamento - GChat - Z-PRO (clínica exemplo)` (`yG2mi6ECBpPv4Hmn`, ativo em produção).
|
||||
|
||||
## Global Constraints
|
||||
|
||||
- **Nenhuma regra fixa de negócio muda de conteúdo** (confirmar nome completo, nunca duplicar agendamento, offset `-03:00`, data de hoje via `$now`) — só a estrutura do `systemMessage` muda (concatenação), o texto das regras existentes permanece idêntico.
|
||||
- As regras fixas continuam vindo **primeiro** no `systemMessage` final, antes do conteúdo do Doc.
|
||||
- O workflow está **ativo em produção** — qualquer alteração precisa ser validada (`n8n_validate_workflow`) antes de considerar a task concluída, e testada com cuidado (ver Task 8) antes de encerrar.
|
||||
- Falha na busca do Doc nunca pode quebrar o atendimento — sempre cair no fallback (regras fixas sem a seção da clínica), nunca erro visível pro cliente.
|
||||
|
||||
Spec de referência: `docs/superpowers/specs/2026-08-11-config-ia-google-docs-design.md`
|
||||
|
||||
---
|
||||
|
||||
## Pré-requisito (ação manual do usuário)
|
||||
|
||||
Criar um Google Doc de teste com algum conteúdo de exemplo (ex.: uma
|
||||
saudação diferente, uma regra fictícia tipo "não atendemos às
|
||||
segundas-feiras"). Compartilhar:
|
||||
- **Visualização**: "Qualquer pessoa com o link" pode visualizar.
|
||||
- **Edição**: liberada só pra sua própria conta (ou a conta do gestor de
|
||||
teste), não pública.
|
||||
|
||||
Anotar o **ID do documento** — é o trecho da URL entre `/d/` e
|
||||
`/edit`, por exemplo em
|
||||
`https://docs.google.com/document/d/1AbCdEfGhIjKlMnOpQrStUvWxYz/edit`
|
||||
o `docId` é `1AbCdEfGhIjKlMnOpQrStUvWxYz`.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Verificar a estrutura atual das conexões antes de modificar
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: workflow `yG2mi6ECBpPv4Hmn` (produção, ativo).
|
||||
|
||||
- [ ] **Step 1: Ler a estrutura atual**
|
||||
|
||||
`n8n_get_workflow` com `{"id": "yG2mi6ECBpPv4Hmn", "mode": "structure"}`.
|
||||
Confirmar visualmente qual `sourceOutput`/índice da conexão de `"É
|
||||
step=process?"` (node `if-early-reply`) aponta pra `"AI Agent"` — no
|
||||
snapshot mais recente é o índice **1** do output `main` (índice 0 é o
|
||||
branch `earlyReply === true`, sem conexão; índice 1 é o branch
|
||||
`earlyReply === false`, que hoje vai direto pro AI Agent). Se a
|
||||
estrutura tiver mudado desde este plano ter sido escrito, ajustar os
|
||||
índices dos steps seguintes de acordo com o que for encontrado aqui —
|
||||
não assumir cegamente.
|
||||
|
||||
---
|
||||
|
||||
### Task 2: Adicionar os 4 nodes novos (sem conectar ainda)
|
||||
|
||||
**Interfaces:**
|
||||
- Produces: 4 nodes novos no workflow `yG2mi6ECBpPv4Hmn`: `Config
|
||||
Clínica`, `Buscar config da clínica`, `Doc OK`, `Doc falhou`.
|
||||
|
||||
- [ ] **Step 1: Adicionar os nodes**
|
||||
|
||||
`n8n_update_partial_workflow` com `{"id": "yG2mi6ECBpPv4Hmn", "operations": [...]}`:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"type": "addNode",
|
||||
"node": {
|
||||
"id": "config-clinica",
|
||||
"name": "Config Clínica",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"typeVersion": 3.5,
|
||||
"position": [240, -560],
|
||||
"parameters": {
|
||||
"mode": "manual",
|
||||
"includeOtherFields": true,
|
||||
"assignments": {
|
||||
"assignments": [
|
||||
{ "id": "cfg-docid", "name": "docId", "type": "string", "value": "SUBSTITUIR_PELO_DOC_ID_DA_CLINICA" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "addNode",
|
||||
"node": {
|
||||
"id": "buscar-config-clinica",
|
||||
"name": "Buscar config da clínica",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.4,
|
||||
"position": [400, -560],
|
||||
"onError": "continueErrorOutput",
|
||||
"parameters": {
|
||||
"method": "GET",
|
||||
"url": "=https://docs.google.com/document/d/{{ $json.docId }}/export?format=txt",
|
||||
"authentication": "none",
|
||||
"options": {
|
||||
"response": { "response": { "responseFormat": "text" } },
|
||||
"timeout": 10000
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "addNode",
|
||||
"node": {
|
||||
"id": "doc-ok",
|
||||
"name": "Doc OK",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"typeVersion": 3.5,
|
||||
"position": [560, -640],
|
||||
"parameters": {
|
||||
"mode": "manual",
|
||||
"includeOtherFields": true,
|
||||
"assignments": {
|
||||
"assignments": [
|
||||
{ "id": "docok-content", "name": "docContent", "type": "string", "value": "={{ $json.data }}" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "addNode",
|
||||
"node": {
|
||||
"id": "doc-falhou",
|
||||
"name": "Doc falhou",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"typeVersion": 3.5,
|
||||
"position": [560, -480],
|
||||
"parameters": {
|
||||
"mode": "manual",
|
||||
"includeOtherFields": true,
|
||||
"assignments": {
|
||||
"assignments": [
|
||||
{ "id": "docfalhou-content", "name": "docContent", "type": "string", "value": "" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Validar (nós ainda desconectados, esperado ter avisos de nó órfão, sem erros de configuração)**
|
||||
|
||||
`n8n_validate_workflow` com `{"id": "yG2mi6ECBpPv4Hmn"}`. Esperado:
|
||||
`errorCount: 0` (avisos de nós desconectados são esperados nesta etapa
|
||||
intermediária, serão resolvidos na Task 3).
|
||||
|
||||
---
|
||||
|
||||
### Task 3: Rewire das conexões
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: os 4 nodes da Task 2, e os índices confirmados na Task 1.
|
||||
|
||||
- [ ] **Step 1: Desconectar "É step=process?" de "AI Agent" e reconectar a cadeia nova**
|
||||
|
||||
```json
|
||||
[
|
||||
{ "type": "rewireConnection", "source": "É step=process?", "sourceOutput": "main", "sourceIndex": 1, "from": "AI Agent", "to": "Config Clínica" },
|
||||
{ "type": "addConnection", "source": "Config Clínica", "target": "Buscar config da clínica", "sourceOutput": "main", "sourceIndex": 0, "targetIndex": 0 },
|
||||
{ "type": "addConnection", "source": "Buscar config da clínica", "target": "Doc OK", "sourceOutput": "main", "sourceIndex": 0, "targetIndex": 0 },
|
||||
{ "type": "addConnection", "source": "Buscar config da clínica", "target": "Doc falhou", "sourceOutput": "main", "sourceIndex": 1, "targetIndex": 0 },
|
||||
{ "type": "addConnection", "source": "Doc OK", "target": "AI Agent", "sourceOutput": "main", "sourceIndex": 0, "targetIndex": 0 },
|
||||
{ "type": "addConnection", "source": "Doc falhou", "target": "AI Agent", "sourceOutput": "main", "sourceIndex": 0, "targetIndex": 0 }
|
||||
]
|
||||
```
|
||||
|
||||
(O output de erro do `HTTP Request` com `onError: continueErrorOutput`
|
||||
é o índice `main[1]` — se a validação no Step 2 apontar índice
|
||||
diferente, corrigir aqui antes de prosseguir.)
|
||||
|
||||
- [ ] **Step 2: Validar**
|
||||
|
||||
`n8n_validate_workflow` com `{"id": "yG2mi6ECBpPv4Hmn"}`. Esperado:
|
||||
`errorCount: 0`, sem nós desconectados.
|
||||
|
||||
---
|
||||
|
||||
### Task 4: Atualizar o `systemMessage` do AI Agent
|
||||
|
||||
**Interfaces:**
|
||||
- Modifica: node `AI Agent` do workflow `yG2mi6ECBpPv4Hmn`.
|
||||
|
||||
- [ ] **Step 1: Adicionar a seção do Doc ao final do `systemMessage`, sem alterar o texto existente**
|
||||
|
||||
`n8n_update_partial_workflow` com:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "yG2mi6ECBpPv4Hmn",
|
||||
"operations": [
|
||||
{
|
||||
"type": "patchNodeField",
|
||||
"nodeName": "AI Agent",
|
||||
"fieldPath": "parameters.options.systemMessage",
|
||||
"patches": [
|
||||
{
|
||||
"find": "ou avise que vai encaminhar para um atendente.",
|
||||
"replace": "ou avise que vai encaminhar para um atendente.\n\nInstruções específicas desta clínica:\n{{ $json.docContent }}"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Validar**
|
||||
|
||||
`n8n_validate_workflow` com `{"id": "yG2mi6ECBpPv4Hmn", "options": {"profile": "ai-friendly"}}`.
|
||||
Esperado: `errorCount: 0`. Ler o node `AI Agent` de volta
|
||||
(`n8n_get_workflow` modo `filtered`, `nodeNames: ["AI Agent"]`) e
|
||||
conferir visualmente que as 7 regras originais continuam intactas e a
|
||||
seção nova foi anexada corretamente ao final.
|
||||
|
||||
---
|
||||
|
||||
### Task 5: Preencher o `docId` de teste e testar de ponta a ponta
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: `docId` do Pré-requisito.
|
||||
|
||||
- [ ] **Step 1: Preencher o `docId` real no node "Config Clínica"**
|
||||
|
||||
`n8n_update_partial_workflow` com
|
||||
`{"id": "yG2mi6ECBpPv4Hmn", "operations": [{"type": "patchNodeField", "nodeName": "Config Clínica", "fieldPath": "parameters.assignments.assignments[0].value", "patches": [{"find": "SUBSTITUIR_PELO_DOC_ID_DA_CLINICA", "replace": "<docId real do Pré-requisito>"}]}]}`.
|
||||
|
||||
- [ ] **Step 2: Teste real — conteúdo do Doc aparece na resposta**
|
||||
|
||||
Enviar ao webhook de produção uma mensagem de teste com um `protocol`
|
||||
novo (mesmo processo já usado nos testes anteriores do Z-PRO — ver
|
||||
`docs/n8n-agendamento-runbook.md`). Conferir que a resposta do agente
|
||||
reflete o conteúdo de exemplo colocado no Doc de teste (ex.: a saudação
|
||||
ou regra fictícia adicionada no Pré-requisito).
|
||||
|
||||
- [ ] **Step 3: Teste real — regras fixas continuam valendo**
|
||||
|
||||
Numa segunda mensagem de teste (protocolo diferente), confirmar que as
|
||||
regras fixas continuam ativas: o agente ainda pede confirmação do nome
|
||||
completo, ainda usa offset `-03:00` corretamente, ainda recusa agendar
|
||||
duas vezes na mesma conversa. **Não é necessário completar um
|
||||
agendamento real** pra este teste — só confirmar o comportamento nas
|
||||
primeiras mensagens da conversa já é suficiente; se for necessário
|
||||
completar um agendamento pra validar totalmente, seguir a disciplina de
|
||||
sempre (dado fictício, execução única, conferência visual no Z-PRO).
|
||||
|
||||
- [ ] **Step 4: Teste do caminho de falha**
|
||||
|
||||
Trocar temporariamente o `docId` no node "Config Clínica" pra um valor
|
||||
inválido (`patchNodeField` igual ao Step 1, com um ID inexistente),
|
||||
enviar uma mensagem de teste, confirmar que o atendimento **não quebra**
|
||||
— o agente responde normalmente, só sem a personalização da clínica.
|
||||
Depois, reverter o `docId` de volta pro valor real.
|
||||
|
||||
---
|
||||
|
||||
### Task 6: Atualizar o runbook e commit
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: resultado validado da Task 5.
|
||||
|
||||
- [ ] **Step 1: Adicionar seção ao runbook**
|
||||
|
||||
Adicionar uma seção nova em `docs/n8n-agendamento-runbook.md`
|
||||
(numerada na sequência, após a seção 14) documentando: o que foi
|
||||
mudado (4 nodes novos + `systemMessage` estendido), o `docId` de
|
||||
produção usado (se já houver um real, não o de teste), e o padrão a
|
||||
replicar quando os workflows de agente de Klingo/SysLife/ClinicAll
|
||||
forem criados (mesmo padrão "Config Clínica" com `docId`, um Google Doc
|
||||
por clínica).
|
||||
|
||||
- [ ] **Step 2: Commit**
|
||||
|
||||
```bash
|
||||
cd "D:\PROJETOS\KLINGO-CLINICAL-SYSLIFE-GCHAT-AGENDAMENTO"
|
||||
git add docs/n8n-agendamento-runbook.md
|
||||
git commit -m "docs: registra configuração da IA via Google Docs (Z-PRO)
|
||||
|
||||
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>"
|
||||
```
|
||||
|
||||
(Os nodes em si vivem no n8n, não em arquivo — não há mais nada pra
|
||||
commitar além da atualização de documentação.)
|
||||
|
||||
---
|
||||
|
||||
## Observação sobre execução
|
||||
|
||||
Mesmo padrão dos planos anteriores: tasks são chamadas de API ao n8n,
|
||||
não commits de código. **Diferente dos planos de MCP Server anteriores,
|
||||
este mexe num workflow já ativo em produção real** — por isso a Task 1
|
||||
existe especificamente para verificar a estrutura real antes de
|
||||
qualquer modificação (não assumir índices de conexão de memória), e a
|
||||
Task 5 inclui teste do caminho de falha antes de considerar a task
|
||||
concluída. Se qualquer validação (`n8n_validate_workflow`) apontar erro
|
||||
em qualquer momento, parar e corrigir antes de prosseguir — não deixar
|
||||
o workflow de produção num estado quebrado entre tasks.
|
||||
Reference in New Issue
Block a user