11 KiB
Design — Confirmação de Agenda via WhatsApp (ClinicAll)
Data: 2026-08-11 Status: Aprovado pelo usuário, aguardando plano de implementação.
Objetivo
Mesmo padrão já implementado para o Klingo
(docs/superpowers/specs/2026-08-11-confirmacao-agenda-klingo-design.md),
agora para o ClinicAll: permitir que o paciente confirme presença
numa consulta agendada via WhatsApp. Diferente do Klingo, o ClinicAll
não tem uma API de "Telefonia" separada — os endpoints de confirmação
fazem parte da mesma TCalendarController já usada no MVP de
agendamento (docs/superpowers/specs/2026-08-11-mcp-server-nativo-n8n-clinicall-design.md),
verificados diretamente no manual oficial (docs/API Clinicall.pdf,
versão 1.1.16).
Relação com o trabalho anterior
- Reaproveita o MCP Server standalone de Mensageria (Z-PRO)
(
docs/n8n-agendamento-runbook.md, seção 17) para o disparo do lembrete — mesma decisão do Klingo, assumindo que o cliente ClinicAll de exemplo também usaria Z-PRO/GChat como canal de WhatsApp. - É um MCP novo e separado do MCP de agendamento do ClinicAll
(seção 14.3 do runbook) — mesmo
TCalendarController/TDomainController, mas endpoints diferentes (confirmação de presença, não criação de agendamento), mesmo espírito de separação de responsabilidades já usado no Klingo (MCP de Telefonia separado do MCP de Agendamento). - Mesma pendência de autenticação já documentada no MVP de agendamento
do ClinicAll: o manual não documenta nenhum header de autenticação
por requisição para
TCalendarController/TDomainController. Decisão idêntica à já tomada:authentication: noneem todos os nodes HTTP, nada inventado.
Escopo: 5 tools do MCP Server "ClinicAll - Confirmação de Agenda"
| Tool | Endpoint | Uso |
|---|---|---|
listar_agendamentos_do_dia |
GET /TCalendarController/agendamento (param: data) |
Base do lembrete proativo — todas as marcações de uma data (livres e agendadas) |
buscar_agendamento_por_cpf |
GET/POST /TCalendarController/agendamentoSemPaciente (params: cpf, dataNascimento) |
O agente usa isso pra achar a consulta pendente do paciente — precisa de CPF e data de nascimento, diferente do Klingo (que só pedia CPF) |
confirmar_presenca |
POST /TCalendarController/AgendamentoFlags |
Ação central — atualiza estadoAgenda/situacaoAgenda da marcação |
consultar_estados_agenda |
GET /TDomainController/estadoAgenda |
Tabela de domínio — valores exatos aceitos em estadoAgenda (ex.: "CONFIRMADO PELA TELEFONISTA", "NAO CONFIRMADO", "FALTOU") |
consultar_situacoes_agenda |
GET /TDomainController/situacaoAgenda |
Tabela de domínio — valores exatos aceitos em situacaoAgenda (ex.: "Agendado", "Presente", "Atrasado") |
Diferença estrutural real em relação ao Klingo: o Klingo aceita um
código curto de 1 letra (C/S/N) pra confirmar. O ClinicAll exige
uma string exata e longa em dois campos separados
(estadoAgenda/situacaoAgenda), cujos valores válidos só existem
documentados nas tabelas de domínio — por isso consultar_estados_agenda
e consultar_situacoes_agenda entram como tools de apoio (não
opcionais): sem elas, o agente teria que adivinhar a string exata, o
que violaria a disciplina de não inventar valores. Não há tool
equivalente a NPS ou consulta de bloqueios — o manual do ClinicAll não
documenta nada parecido para este módulo; ficam fora, sem inventar.
Arquitetura
Três peças, mesmo padrão do Klingo:
1) MCP Server "ClinicAll - Confirmação de Agenda" (servidor + 5 sub-workflows)
[MCP Server Trigger] ──Tools──┬── listar_agendamentos_do_dia ──▶ GET /TCalendarController/agendamento
├── buscar_agendamento_por_cpf ──▶ GET/POST /TCalendarController/agendamentoSemPaciente
├── confirmar_presenca ──▶ POST /TCalendarController/AgendamentoFlags
├── consultar_estados_agenda ──▶ GET /TDomainController/estadoAgenda
└── consultar_situacoes_agenda ──▶ GET /TDomainController/situacaoAgenda
2) Workflow proativo "Lembrete de Confirmação - ClinicAll (exemplo)"
[Cron 8h diário] → [ClinicAll: listar_agendamentos_do_dia (amanhã)]
→ [Loop por agendamento] → [Mensageria ZPRO: enviar_texto]
3) Workflow de exemplo "Confirmação de Agenda - GChat - ClinicAll+Z-PRO (exemplo)"
[Webhook Z-PRO/GChat] → [AI Agent] → resposta ao paciente
tools: MCP ClinicAll - Confirmação de Agenda (buscar_agendamento_por_cpf, confirmar_presenca,
consultar_estados_agenda, consultar_situacoes_agenda)
memória: Postgres Chat Memory (mesmo padrão dos outros exemplos)
Sem cliente ClinicAll real disponível: mesma disciplina do Klingo —
estrutura completa, validada (n8n_validate_workflow, 0 erros
esperados), sem teste de ponta a ponta.
Componentes
MCP Server "ClinicAll - Confirmação de Agenda"
Mesmo esqueleto de sub-workflow dos outros MCP Servers deste projeto:
Execute Workflow Trigger → Config ClinicAll (Set com baseUrl
placeholder) → montagem de query/body → HTTP Request
(authentication: none, neverError: true + fullResponse: true) →
classificação de resultado (mesma taxonomia genérica dos outros
providers: AUTHENTICATION_ERROR 401/403, NOT_FOUND 404,
VALIDATION_ERROR 400/422, CLINICALL_API_ERROR demais — o manual não
documenta código de erro específico pra estes endpoints).
listar_agendamentos_do_dia: parâmetrodata(obrigatório, conforme documentado — "Mandatório data da agenda"). URL:{{baseUrl}}/datasnap/rest/TCalendarController/agendamento/<data>(mesmo endpoint base já usado no MVP de agendamento comPUTpara conciliar; aqui usado comGETpara listar).buscar_agendamento_por_cpf: parâmetroscpfedataNascimento(ambos obrigatórios, conforme documentado). Endpoint:{{baseUrl}}/datasnap/rest/TCalendarController/agendamentoSemPaciente. Ambiguidade real do manual: o endpoint documenta métodosGET, POSTsem esclarecer se os parâmetros vão como query string (GET) ou corpo (POST) — o exemplo do manual não mostra a requisição, só a resposta. Decisão desta etapa: implementar comoGETcom os dois parâmetros como query string (?cpf=...&dataNascimento=...), por ser o padrão mais comum nos demais endpoints GET documentados deste mesmo manual (todos os outros GETs do ClinicAll usam query string, nunca body) — mas isso é uma suposição não verificada contra a API real, registrada explicitamente como tal.confirmar_presenca: parâmetrosidAgenda(obrigatório),situacaoAgenda(obrigatório, string exata — ex.:"Agendado"),estadoAgenda(obrigatório, string exata — ex.:"CONFIRMADO PELA TELEFONISTA"),confirmadoPor(opcional — nome de quem confirmou, útil quando não é o próprio paciente respondendo),usuarioConfirmou,dataConfirmacao,horarioFlag,usuarioFlag(estes quatro opcionais, preenchidos com dados fixos identificando a automação — ex.:usuarioConfirmou: "bot-whatsapp"— já que não há usuário humano operando). Endpoint:{{baseUrl}}/datasnap/rest/TCalendarController/AgendamentoFlags.consultar_estados_agenda: sem parâmetro obrigatório (aceitanomeopcional de busca, conforme documentado). Endpoint:{{baseUrl}}/datasnap/rest/TDomainController/estadoAgenda.consultar_situacoes_agenda: mesmo padrão, endpoint{{baseUrl}}/datasnap/rest/TDomainController/situacaoAgenda.
Workflow proativo "Lembrete de Confirmação - ClinicAll (exemplo)"
[Cron Trigger, 8h diário] → [ClinicAll: listar_agendamentos_do_dia]
(data = amanhã, calculada via expressão)
→ [Loop] → [Mensageria ZPRO: enviar_texto]
(number = telefoneCelular do paciente dentro do objeto Paciente
aninhado, body = mensagem com nomePaciente + dataAgenda/horaAgenda)
Mesmo padrão do Klingo: chamada direta via Execute Workflow (sem IA,
fluxo determinístico). Nota: no ClinicAll, o telefone do paciente vem
aninhado dentro do objeto Paciente de cada item da lista
(item.Paciente.telefoneCelular), diferente do Klingo onde celular
era um campo direto do item — refletir isso na extração de dados.
Itens com situacaoAgenda: "Livre" (sem paciente vinculado) devem ser
filtrados antes do envio — só mandar lembrete pra marcações com
idPaciente preenchido. Texto fixo nesta rodada (sem Google Docs — é
exemplo/esqueleto, sem gestor real). Fica inativo de propósito —
sem clínica real, ativar geraria só chamadas com erro.
Workflow de exemplo "Confirmação de Agenda - GChat - ClinicAll+Z-PRO (exemplo)"
Réplica estrutural do padrão já usado no Klingo e no Z-PRO (webhook → AI Agent → memória Postgres), sem cliente real associado.
- Webhook: mesmo contrato Z-PRO/GChat já documentado (seção 6 do runbook).
- AI Agent:
systemMessagefixo instruindo o agente a: entender se a mensagem é uma resposta de confirmação/recusa; se for, pedir CPF e data de nascimento do paciente (diferente do Klingo, que só precisava do CPF) e usarbuscar_agendamento_por_cpfpara achar a marcação pendente; consultarconsultar_estados_agendaeconsultar_situacoes_agendapara obter as strings exatas válidas antes de decidir o que enviar (nunca inventar um valor de estado); chamarconfirmar_presencacomestadoAgenda: "CONFIRMADO PELA TELEFONISTA"(paciente confirmou) ouestadoAgenda: "NAO CONFIRMADO"/"FALTOU"conforme o caso, mantendosituacaoAgenda: "Agendado"(a marcação continua agendada, só o estado de confirmação muda); responder confirmando o registro ao paciente. - Tools: MCP ClinicAll - Confirmação de Agenda —
buscar_agendamento_por_cpf,confirmar_presenca,consultar_estados_agenda,consultar_situacoes_agendaconectadas (todas as 4 excetolistar_agendamentos_do_dia, que só serve ao workflow proativo). - Memória:
Postgres Chat Memory, mesmo padrão da seção 16/18 do runbook, credencial placeholder (sem cliente real).
Fica inativo de propósito, mesma razão do workflow proativo.
Fora de escopo (adiado)
- NPS / avaliação pós-consulta — não documentado no manual do ClinicAll para este módulo.
- Consulta de bloqueios de agenda — não documentado no manual do
ClinicAll para este módulo (existe
flagEstadoAgenda: "B" — BLOQUEADOcomo estado de uma marcação individual, mas não um endpoint de consulta de bloqueios como no Klingo). - Resolver a ambiguidade de GET vs. body em
agendamentoSemPacientecontra a API real — fica pendente até haver clínica real pra testar. - Configuração via Google Docs no workflow de exemplo — sem gestor real associado.
- Teste de ponta a ponta contra a API real do ClinicAll — sem clínica real disponível, mesma limitação já registrada no MVP de agendamento.
Testes
Sem clínica ClinicAll real disponível: validação estrutural apenas
(n8n_validate_workflow, 0 erros esperados em todos os workflows).
Teste real de ponta a ponta fica pendente para quando houver uma
clínica ClinicAll real — nesse momento, resolver primeiro a
autenticação (mesma pendência do MVP de agendamento) e a ambiguidade
de agendamentoSemPaciente antes de qualquer teste de confirmação.