@lionchat/mcp-server 1.12.1 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docs/instructions.md +11 -1
- package/dist/docs/resources/api-conventions.md +7 -0
- package/dist/docs/resources/best-practices.md +48 -1
- package/dist/docs/resources/conversation-flows.md +36 -0
- package/dist/docs/resources/data-model.md +25 -0
- package/dist/docs/resources/flowbuilder-design-guide.md +6 -0
- package/dist/docs/resources/flowbuilder-patterns.md +27 -0
- package/dist/docs/resources/formularios-publicos.md +499 -0
- package/dist/docs/resources/glossary.md +49 -1
- package/dist/docs/resources/troubleshooting.md +76 -3
- package/dist/resources.js +6 -0
- package/dist/resources.js.map +1 -1
- package/dist/tools.js +27 -5
- package/dist/tools.js.map +1 -1
- package/endpoints.json +470 -73
- package/package.json +1 -1
|
@@ -18,7 +18,12 @@ Comprovado em produção (24/07): a sessão que dizia "não há função de list
|
|
|
18
18
|
- **Famílias principais pra pesquisar:** conversations, conversations_messages, contacts,
|
|
19
19
|
kanban_items, funnels, flows, flow_tools, campaigns, macros, automation_rules, agents, teams,
|
|
20
20
|
inboxes, labels, canned_responses, reports, sla, csat, captain_assistants, captain_documents,
|
|
21
|
-
scheduled_messages, custom_attributes, webhooks, eclinica_integrations, tasks, notifications
|
|
21
|
+
scheduled_messages, custom_attributes, webhooks, eclinica_integrations, tasks, notifications,
|
|
22
|
+
lead_forms (Formulários públicos de captação).
|
|
23
|
+
- **Fora do MCP por decisão do dono (19/08): assinatura, plano, fatura, forma de pagamento, cartão,
|
|
24
|
+
saldo e recarga.** Não existem ferramentas dessas áreas e não devem ser criadas. Se o usuário
|
|
25
|
+
pedir, diga que isso se resolve no painel, na área de assinatura da conta — não tente por
|
|
26
|
+
ferramenta nem por chamada direta.
|
|
22
27
|
- Só depois de pesquisar e não encontrar é que se pode dizer que a função não existe.
|
|
23
28
|
- **Trabalho volumoso** (relatório de muitas conversas/cards): as listas são paginadas (25-100 por
|
|
24
29
|
página) — faça em ETAPAS ao longo de várias respostas, acumulando os resultados; nunca desista
|
|
@@ -47,6 +52,8 @@ Account (conta/empresa)
|
|
|
47
52
|
├─ Captain::Assistant (AI Agente / IA de atendimento)
|
|
48
53
|
│ └─ Captain::Scenario (instrução situacional; pode FIXAR parâmetro de tool em tool_bindings)
|
|
49
54
|
├─ AccountTask (agenda/tarefas)
|
|
55
|
+
├─ LeadForm (formulário público de captação)
|
|
56
|
+
│ └─ LeadFormResponse (preenchimento: in_progress / completed / abandoned)
|
|
50
57
|
└─ Booking (agendamento de demonstração/reunião)
|
|
51
58
|
```
|
|
52
59
|
|
|
@@ -360,6 +367,9 @@ Antes de escolher a ferramenta, cheque se a intenção bate com a coluna da dire
|
|
|
360
367
|
| Só a contagem / números | `lionchat_conversations_meta` / `lionchat_reports_summary` | Não liste o conteúdo completo |
|
|
361
368
|
| Criar contato | `lionchat_contacts_create` base (path `/contacts`) | NÃO use as variantes `_1` … `_9` |
|
|
362
369
|
| Pausar a IA agora (botão de pânico) | `lionchat_captain_assistants_update` (`paused: true`, top-level) | — |
|
|
370
|
+
| Criar/editar **formulário público de captação** (página de captura própria) | `lionchat_lead_forms_create` / `_update` | Leia `lionchat://docs/formularios-publicos` ANTES — o desenho vai em `form_data` e só entra no ar depois do `publish` (que valida o desenho e pode voltar 422 com a lista de pendências). Caixa de WhatsApp vinculada (`inbox_id`) é obrigatória pra publicar. Escrita é só de administrador |
|
|
371
|
+
| **Testar um formulário** antes de publicar | `lionchat_lead_forms_test_run` | Roda o RASCUNHO no motor real e desfaz tudo no fim — zero rastro. Mande `answers: [{node_id, value}]` (até 60) pra reproduzir um caminho; a resposta traz o bloco atual + o log do percurso |
|
|
372
|
+
| Conferir se um site **aceita ser exibido dentro do formulário** (bloco Página externa) | `lionchat_lead_forms_check_embed` | Body `{url}`; devolve `{status: allowed\|blocked\|unknown, reason}`. Grave o veredito em `embed_allowed` do bloco. Admin-only |
|
|
363
373
|
| Anexar arquivo a uma mensagem | `lionchat_upload_create` primeiro, depois usar o retorno em `lionchat_conversations_messages_create` | Confira `lionchat_upload_limits` se o arquivo for grande |
|
|
364
374
|
| Marcar conversa como **lida** | `lionchat_conversations_update_last_seen` | NÃO use `unread` (esse marca como NÃO-lida) |
|
|
365
375
|
| Criar/gerenciar **campanha** (disparo WhatsApp/SMS) | `lionchat_campaigns_*` (criar, estatísticas) | SEMPRE rode `campaigns_estimate_audience` antes de criar e mostre a contagem. Disparo em massa = confirmação obrigatória (seção 7b) |
|
|
@@ -442,6 +442,13 @@ mantém o comportamento antigo (só as colunas pedidas).
|
|
|
442
442
|
`GET /upload_limits` retorna o teto em MB por tipo (`image`, `video`, `audio`, `document`,
|
|
443
443
|
`fallback`). Consulte 1x antes de subir anexo grande — evita 422 no meio do fluxo.
|
|
444
444
|
|
|
445
|
+
**Desde 15/08/2026 o TIPO não rejeita mais anexo de mensagem** — a validação passou a ser só de
|
|
446
|
+
tamanho. Tipo sem balde próprio (nem imagem, nem vídeo, nem áudio) cai no balde de **documento**,
|
|
447
|
+
que é o maior. Ou seja: `upload_limits` continua sendo a única fonte dos tetos, mas a resposta
|
|
448
|
+
"esse formato não é aceito" deixou de existir nesse caminho. Os caminhos que **continuam** com
|
|
449
|
+
lista fechada de tipos são o upload por URL (`/upload` com `#validate`, usado no teste de mídia do
|
|
450
|
+
FlowBuilder) e o chat interno da equipe.
|
|
451
|
+
|
|
445
452
|
### Webhooks de saída — evento novo (2026-06)
|
|
446
453
|
|
|
447
454
|
`inbox_updated` entrou na lista de eventos assináveis (`webhooks_create/update`): dispara quando
|
|
@@ -330,7 +330,7 @@ Como a coleta de dados/cenários funciona hoje (importante pra diagnosticar "IA
|
|
|
330
330
|
|
|
331
331
|
- O admin pode FIXAR o parâmetro de uma ferramenta no cenário (campo scenario.tool_bindings): quais mídias enviar, qual funil+etapa do card, quais agendas no agendamento. "Deixar a IA decidir" = binding vazio.
|
|
332
332
|
- Quando UM cenário fixa a tool, a execução vira determinística (a IA não escolhe): mídia e kanban são aplicados pós-turno pelo BindingResolver (ordem texto→ação, sem duplicar, idempotente); o agendamento força/restringe a agenda mas a IA ainda define data/hora.
|
|
333
|
-
- Via MCP: scenarios_create/update persiste binding de send_media_asset e create_kanban_item/move_kanban_item (re-escopados por conta). O binding de create_booking NÃO é aceito pela API — pra limitar agendas via MCP, use config.booking_event_type_ids no assistente (captain_assistants_update).
|
|
333
|
+
- Via MCP: scenarios_create/update persiste binding de send_media_asset e create_kanban_item/move_kanban_item (re-escopados por conta). O binding de create_booking NÃO é aceito pela API — pra limitar agendas via MCP, use config.booking_event_type_ids no assistente (captain_assistants_update). **Atualização 15/08:** o modo direto/avulso do create_booking foi REMOVIDO — agenda de Booking é o ÚNICO caminho de agendamento da IA (ver seção "O que mudou no agendamento DA IA").
|
|
334
334
|
- Receita pra criar/editar cenário com binding via MCP (scenarios_create / scenarios_update): (1) o corpo vai SEMPRE embrulhado em `scenario`; (2) a instrução PRECISA mencionar a ferramenta como link markdown `[Rótulo](tool://slug)` — menção crua `(tool://slug)` NÃO conta e o binding é descartado no salvamento; (3) envie `tool_bindings` com o shape: `send_media_asset` → `{ "asset_ids": [Int] }`, `create_kanban_item`/`move_kanban_item` → `{ "funnel_id": Int, "stage": "<chave da etapa>" }`. Não precisa mandar `tools` (é auto-extraído da instrução e sobrescrito). `create_booking` NÃO entra em tool_bindings pela API.
|
|
335
335
|
- Pra APONTAR uma página da base de conhecimento num cenário via MCP, escreva `[@Nome](document://ID)` (o ID numérico do documento) DENTRO do texto da `instruction` — igual ao link de tool, o motor deriva daí o campo `document_ids`. NÃO existe param `document_ids` na API/MCP (mandar seria descartado em silêncio). Teto de 3 documentos; a página apontada ganha PRIORIDADE na busca RAG, NÃO exclusividade (o resto da base continua pesquisável).
|
|
336
336
|
|
|
@@ -445,6 +445,32 @@ criar a campanha e mostre a contagem ao usuário — estimativa e disparo usam o
|
|
|
445
445
|
- Rate limit da reserva pública: 10/5min por IP + 20/min por conta (429 ao estourar).
|
|
446
446
|
- Todo agendamento aparece vinculado a uma conversa (cria/reusa a conversa do contato).
|
|
447
447
|
|
|
448
|
+
### O que mudou no agendamento DA IA (2026-08-15)
|
|
449
|
+
|
|
450
|
+
**1. A IA só agenda por AGENDA de Booking.** `view_booking_option` virou a ÚNICA fonte de horário
|
|
451
|
+
— o modo direto/avulso do `create_booking` foi REMOVIDO (era o único caminho que criava
|
|
452
|
+
compromisso fora do motor de reservas). Consequência prática: a IA passou a respeitar os dias em
|
|
453
|
+
que a agenda NUNCA abre (parou de oferecer domingo) e não inventa mais identificador de agenda —
|
|
454
|
+
com uma única agenda liberada ela assume essa; com duas ou mais, recusa nomeando as válidas. Para
|
|
455
|
+
restringir quais agendas a IA oferece, continua valendo `captain_assistants_update` com
|
|
456
|
+
`config.booking_event_type_ids`.
|
|
457
|
+
|
|
458
|
+
**2. A IA entrega o link do Meet sozinha.** O link do Google Meet não existe no instante em que o
|
|
459
|
+
agendamento é criado (nasce depois da ida ao Google), e antes a IA prometia o link e nunca voltava.
|
|
460
|
+
Agora o sistema arma uma volta de ~25s; sem link ainda, ele remarca sozinho (+40s) sem gastar turno
|
|
461
|
+
de IA; com link, a IA manda o endereço literal. Se na segunda tentativa o link não veio, ela avisa
|
|
462
|
+
o cliente e aciona um humano (nota privada com menção). Requisitos: o tipo de agendamento precisa
|
|
463
|
+
gerar Meet e o dono da agenda precisa ter o Google conectado. `{{conversation.custom_attribute.meet_link}}`
|
|
464
|
+
e o `{{meet_link}}` da mensagem de confirmação do Booking passaram a vir preenchidos (antes saíam
|
|
465
|
+
vazios) — isso vale inclusive para cliente que não usa IA.
|
|
466
|
+
|
|
467
|
+
**3. A IA não confirma reunião que não existe.** No último instante antes da resposta virar
|
|
468
|
+
mensagem: se ela afirma agendamento concluído, a agenda está liberada e não há compromisso real na
|
|
469
|
+
conversa, o sistema roda UMA tentativa guiada que agenda de verdade com a data/hora prometidas.
|
|
470
|
+
Agendou, sai a confirmação verdadeira; não agendou, a frase é trocada por uma honesta — nunca
|
|
471
|
+
silêncio. Diagnóstico: se o cliente disser "a IA confirmou e não tem nada na agenda", esse é o
|
|
472
|
+
comportamento ANTIGO (medido: 39 afirmações falsas em 30 dias antes do conserto).
|
|
473
|
+
|
|
448
474
|
## Variáveis de conta (account_variables)
|
|
449
475
|
|
|
450
476
|
Pra dados fixos que se repetem (slogans, endereços, horários):
|
|
@@ -685,6 +711,9 @@ automática. Ver a seção de variáveis de conta acima.
|
|
|
685
711
|
```
|
|
686
712
|
Cada item de `attachments` é o `blob_id` retornado pelo upload. Pode mandar vários.
|
|
687
713
|
3. O mesmo padrão vale pra anexar mídia num card do Kanban (use o `blob_id` no campo de anexo do card).
|
|
714
|
+
4. **Anexo de MENSAGEM aceita QUALQUER tipo de arquivo (novo 15/08)** — só o TAMANHO reprova. Se
|
|
715
|
+
houver dúvida sobre um arquivo grande, confira antes com `lionchat_upload_limits_show` (segue
|
|
716
|
+
sendo a fonte dos tetos).
|
|
688
717
|
|
|
689
718
|
## Cuidados com tools de criação
|
|
690
719
|
|
|
@@ -804,3 +833,21 @@ Custom attribute em lugar errado vira:
|
|
|
804
833
|
1. Procure no `kanban-deep-dive.md` (Kanban) ou na doc da feature relevante
|
|
805
834
|
2. Liste o config global do recurso (`kanban_config_list`, `voip_settings_list`, etc) — campos `nil`/vazios mas presentes na response = espera input
|
|
806
835
|
3. Olhe `data-model.md` pra colunas jsonb no model — costumam guardar feature nativa
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
## Regras rápidas de 18/08
|
|
839
|
+
|
|
840
|
+
- **Mensagens: ordene SEMPRE por `created_at`, nunca por `id`.** Conversa com histórico importado
|
|
841
|
+
tem id fora de ordem por desenho (o id cresce na importação, a data é a original). A API já
|
|
842
|
+
devolve em ordem cronológica.
|
|
843
|
+
- **Import de contatos: o DDI é da planilha.** O sistema não completa 55; sem DDI = erro na linha;
|
|
844
|
+
`contacts_import_validate` NÃO valida telefone. No import do Kanban, telefone inválido cria card
|
|
845
|
+
SEM contato em silêncio. Oriente o cliente a subir `5511988887777` ou `+351912345678`.
|
|
846
|
+
- **Caixa oficial com aviso de bloqueio por pagamento** (`whatsapp_send_blocked_billing`):
|
|
847
|
+
`GET /inboxes/{id}/health` consulta a Meta e LIMPA o aviso se o envio voltou — além de sucesso
|
|
848
|
+
de template, é o único jeito de limpar.
|
|
849
|
+
- **Template Cloud que falhou pode virar `sent` sozinho** (socorro automático, até ~1h; o
|
|
850
|
+
`source_id` muda). Não reenvie por conta própria uma mensagem de template recém-falhada de erro
|
|
851
|
+
passageiro — o socorro cuida; reenviar por cima entrega em dobro.
|
|
852
|
+
- **Filtros de data fixa cortam o dia no fuso da CONTA** (padrão America/Sao_Paulo) — e mudar o
|
|
853
|
+
`timezone` da conta move essa fronteira.
|
|
@@ -471,6 +471,37 @@ pode ser disparado por **webhook externo próprio**: cria-se a integração embu
|
|
|
471
471
|
resolve contato/conversa (mesmas regras do Webhook Universal) e dispara o flow.
|
|
472
472
|
Receita completa no resource **FlowBuilder — Guia de Design** (seção do trigger `webhook`).
|
|
473
473
|
|
|
474
|
+
### Disparo de flow por FORMULÁRIO público de captação (2026-08)
|
|
475
|
+
|
|
476
|
+
Um flow pode ser disparado pelo que o lead faz num **Formulário público** (resource
|
|
477
|
+
`lionchat://docs/formularios-publicos`). São **três gatilhos**, todos no node `start`:
|
|
478
|
+
|
|
479
|
+
| Gatilho | Quando dispara |
|
|
480
|
+
|---|---|
|
|
481
|
+
| `lead_form_completed` | O lead **concluiu** o formulário |
|
|
482
|
+
| `lead_form_milestone` | O lead **atingiu um marco** dentro do formulário (sem precisar concluir) |
|
|
483
|
+
| `lead_form_abandoned` | O lead **parou no meio** e a janela de abandono do formulário venceu |
|
|
484
|
+
|
|
485
|
+
Como montar o item do gatilho:
|
|
486
|
+
- **`lead_form_id` é obrigatório** — o gatilho só casa com o formulário apontado; sem ele o flow
|
|
487
|
+
fica MUDO (nenhum erro, nenhum disparo).
|
|
488
|
+
- Pelo caminho **API/MCP**, `lead_form_id` (e `milestone_node_id`) vão no **topo do item**; a
|
|
489
|
+
**tela** grava os mesmos campos dentro de `config`. O motor lê os dois formatos — não precisa
|
|
490
|
+
duplicar.
|
|
491
|
+
- `milestone_node_id` é **opcional** e só existe no `lead_form_milestone`: preenchido, o flow
|
|
492
|
+
dispara só naquele marco; **vazio = qualquer marco** daquele formulário.
|
|
493
|
+
- Só vale em **flow individual** (`conversation_mode: 'individual'`). Flow de grupo e ferramenta
|
|
494
|
+
de IA (`ai_tool`) nunca são disparados por formulário.
|
|
495
|
+
|
|
496
|
+
Comportamento no disparo:
|
|
497
|
+
- Cada gatilho dispara **uma vez por resposta** (`completed`, `milestone:<node_id>` e `abandoned`
|
|
498
|
+
são chaves independentes) — retentativa não dobra o flow.
|
|
499
|
+
- Exige **contato** na resposta: lead que não deixou nome+telefone não dispara nada. Em caixa
|
|
500
|
+
WhatsApp (oficial ou QR Code), contato sem telefone também é pulado.
|
|
501
|
+
- O disparo **cria ou reabre uma conversa** na primeira caixa vinculada ao flow — ou seja, acorda
|
|
502
|
+
os ouvintes de `conversation_created` (automação, outros flows, webhook de saída, Kanban, SLA,
|
|
503
|
+
notificação). Conte com isso ao desenhar a cadeia.
|
|
504
|
+
|
|
474
505
|
### Proteção anti-loop entre motores (2026-06)
|
|
475
506
|
|
|
476
507
|
Automações e flows podem se encadear (automação dispara flow, flow dispara automação...).
|
|
@@ -492,6 +523,11 @@ ficar muda (2026-06-05).
|
|
|
492
523
|
| `message_created` | Nova mensagem (incoming ou outgoing) |
|
|
493
524
|
| `first_reply_created` | Primeira resposta humana |
|
|
494
525
|
|
|
526
|
+
**Os gatilhos de Formulário público (`lead_form_completed`, `lead_form_milestone`,
|
|
527
|
+
`lead_form_abandoned`) NÃO entram nessa tabela** — são gatilhos de **flow**, não eventos de
|
|
528
|
+
automação. Não adianta criar `automation_rule` com esses nomes em `event_name`; o caminho é o node
|
|
529
|
+
`start` de um flow (ver a seção acima).
|
|
530
|
+
|
|
495
531
|
### Subtipos de `conversation_updated` (campo `action_types`)
|
|
496
532
|
|
|
497
533
|
Ao criar/atualizar uma `automation_rule` com `event_name: 'conversation_updated'`, envie tambem
|
|
@@ -422,6 +422,7 @@ Atributos de sistema no CONTATO (prefixo `eclinica_`, protegidos, usáveis como
|
|
|
422
422
|
| `eclinica_compromisso` | text | Tipo da consulta — TEXTO LIVRE da recepção (ex: Consulta, Retorno) |
|
|
423
423
|
| `eclinica_agendatipo` | text | Tipo de Agendamento — NOME da lista fixa do painel, resolvido por unidade (novo 2026-07-28). **Filtrar sempre pelo NOME, nunca pelo número: os números colidem entre filiais** |
|
|
424
424
|
| `eclinica_agendatipo_id` | text | Tipo de Agendamento — número cru (não comparável entre filiais) |
|
|
425
|
+
| `eclinica_cor` | text | Cor do agendamento na agenda (hex, ex `#556B2F`) — novo 2026-08-18. Campo ESPARSO: evento sem cor APAGA a chave (nunca herda a da consulta anterior). No filtro, escrever com o `#`. Nos lembretes, a variável de sessão `{{cor}}` traz a cor da consulta daquele lembrete |
|
|
425
426
|
| `eclinica_profissional` | text | NOME do profissional, resolvido por unidade (novo 2026-07-10) |
|
|
426
427
|
| `eclinica_profissional_id` | text | Número do profissional (não comparável entre filiais) |
|
|
427
428
|
| `eclinica_convenio_id` | text | Convênio (número) |
|
|
@@ -502,6 +503,20 @@ MetaLeadIntegration (Facebook Lead Ads)
|
|
|
502
503
|
├── status (active/token_expired/paused)
|
|
503
504
|
└── meta_lead_forms (has_many)
|
|
504
505
|
|
|
506
|
+
LeadForm (Formulário público de captação — feature flag lead_forms, por conta)
|
|
507
|
+
├── account_id (FK)
|
|
508
|
+
├── name / slug (8 chars, gerado na criação e imutável) / display_mode (cards|chat) / active
|
|
509
|
+
├── form_data (jsonb: o desenho do construtor) — published_data (a FOTO publicada, que a página usa)
|
|
510
|
+
├── settings (jsonb: primary_color, theme, abandon_minutes, button_label) / published_at
|
|
511
|
+
└── counts: views / responses / completed (contadores) + lead_form_responses (has_many)
|
|
512
|
+
|
|
513
|
+
LeadFormResponse (um preenchimento do formulário)
|
|
514
|
+
├── lead_form_id (FK) / account_id (FK)
|
|
515
|
+
├── contact_id (FK opcional — o contato nasce assim que nome+telefone entram, mesmo sem concluir)
|
|
516
|
+
├── status (in_progress / completed / abandoned)
|
|
517
|
+
└── answers (respostas) / milestones (marcos atingidos) / utm_params / started_at / completed_at /
|
|
518
|
+
abandoned_at
|
|
519
|
+
|
|
505
520
|
CustomWebhookIntegration (Webhook Universal — entrada)
|
|
506
521
|
├── account_id (FK)
|
|
507
522
|
├── name / token (URL única) / active
|
|
@@ -585,3 +600,13 @@ Account.feature_enabled?('captain_v2') # checa bitfield
|
|
|
585
600
|
- Contact pode ser deletado (raro) — destroi conversations em cascata (cuidado)
|
|
586
601
|
- KanbanItem pode ser deletado livremente
|
|
587
602
|
- Funnel `archived = true` → não aparece na UI mas dados permanecem
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
## Limites da conta (18/08)
|
|
606
|
+
|
|
607
|
+
Os limites que a API devolve (`resource_limits.*` da conta, `email_usage.limit`,
|
|
608
|
+
`ai_agent_usage.limit`) são a SOMA de: limite do plano + ajustes manuais do Super Admin +
|
|
609
|
+
**adicionais contratados na tela de Cobrança** (recurso liberado na hora da contratação). Ou seja:
|
|
610
|
+
duas contas no MESMO plano podem ter limites diferentes — não é defeito. Limite `0` significa
|
|
611
|
+
ILIMITADO em toda a plataforma. A contratação/remoção de adicionais é feita SÓ pela tela de
|
|
612
|
+
Cobrança do painel (não há ferramenta MCP para isso, por decisão do dono).
|
|
@@ -463,6 +463,12 @@ o botão "Usar variável" ao lado do campo alterna lista fixa ↔ variável.
|
|
|
463
463
|
|
|
464
464
|
**Campos NATIVOS do contato (2026-07-29):** com `attr_source: 'contact'`, `attr_key` também aceita os paths canônicos `contact.name`, `contact.email`, `contact.cpf`, `contact.cnpj`, `contact.rg`, `contact.passport`, `contact.date_of_birth`, `contact.gender`, `contact.marital_status`, `contact.profession` e `contact.address.{cep,street,number,complement,neighborhood,city,state,country}` — gravam na ficha nativa do contato (não em custom_attributes). Regras: telefone/identifier/etiquetas NÃO são aceitos (mapa fechado — chave fora dele vira atributo personalizado comum); documentos, nascimento, gênero e **e-mail** só preenchem campo VAZIO; nome/profissão/estado civil/endereço sobrescrevem; valor em branco nunca grava; gênero aceita `m|f|o|na` e estado civil `solteiro|casado|uniao_estavel|divorciado|separado|viuvo`; data de nascimento em `dd/mm/aaaa` ou `aaaa-mm-dd`. Recusas aparecem no histórico de execução (passo 'skipped'/'error' com mensagem).
|
|
465
465
|
|
|
466
|
+
**Campos NATIVOS do contato em CONDIÇÃO (2026-08-13):** o bloco de Condições e o filtro do gatilho de data passaram a LER os mesmos paths nativos (`contact.name`, `contact.cpf`, `contact.marital_status`, `contact.address.city`, ...) na fonte `contact` — antes só liam atributo personalizado e o campo da ficha voltava vazio, jogando tudo na saída padrão em silêncio. Use com `is_empty`/`is_not_empty` para montar "o CPF está preenchido?". Aceita a forma curta (`contact.cpf`) e a longa (`contact.cadastral.cpf`). **`contact.label` NÃO é aceito** em condição (consulta cara em caminho reativo). **Gênero e estado civil são listas fechadas**: compare com o valor canônico (`m|f|o|na`, `solteiro|casado|uniao_estavel|divorciado|separado|viuvo`) — comparar com "Masculino" nunca casa.
|
|
467
|
+
|
|
468
|
+
**NÃO use campo nativo na CONDIÇÃO DE SAÍDA nem no gatilho "quando o atributo do contato mudar"** — o sistema só emite o evento de mudança para atributo PERSONALIZADO, então a regra nunca dispararia. Nesses dois lugares o seletor continua oferecendo apenas atributos personalizados, de propósito.
|
|
469
|
+
|
|
470
|
+
**Parâmetro `always_ask` no node inicial de `ai_tool` (2026-08-13):** `true` faz a IA perguntar o dado ao cliente mesmo que o campo já tenha valor salvo, e regravar com a resposta. Use quando o valor guardado não for confiável (o nome do WhatsApp costuma ser só o primeiro nome). O campo volta a contar como resolvido depois que a IA salvar naquela conversa. Omitir = comportamento de sempre (campo preenchido é pulado).
|
|
471
|
+
|
|
466
472
|
**Somar/subtrair NÃO é operação dedicada** — é filtro Liquid no próprio `attr_value`. O valor é resolvido como template antes de salvar. Exemplos:
|
|
467
473
|
|
|
468
474
|
```json
|
|
@@ -633,3 +633,30 @@ grupo** (o grupo é a conversa do flow).
|
|
|
633
633
|
6. Após criar, **ative** com `flows_toggle` se o cliente quiser que rode já. ATENÇÃO (2026-06-16): se já existir outro flow ATIVO com o mesmo gatilho na mesma inbox (e mesmo modo), a ativação retorna **422 `flow_trigger_conflict`** — exceto `webhook_received`/`manual_trigger`, que podem coexistir. Não fique reativando: explique o conflito ao usuário (qual flow + qual caixa) e ofereça desativar o outro ou mudar o gatilho. Dá pra checar antes com `POST /flows/check_conflicts` (não salva). Detalhes no `flowbuilder-design-guide` (seção 2.1, "Trava de gatilho duplicado").
|
|
634
634
|
|
|
635
635
|
Se a necessidade não bate com nenhum pattern, monte do zero seguindo o **`flowbuilder-design-guide`** — mas use estes templates como referência de layout/handle/schema válidos.
|
|
636
|
+
|
|
637
|
+
|
|
638
|
+
## Regras de autoria por API (18/08)
|
|
639
|
+
|
|
640
|
+
**`start_flow` nunca pode apontar pro PRÓPRIO flow.** O save aceita (sem 422), mas na execução o
|
|
641
|
+
passo é IGNORADO EM SILÊNCIO (só um aviso no log do servidor; nada no histórico de execução) e o
|
|
642
|
+
fluxo para ali. A tela esconde o próprio flow do seletor; por API a responsabilidade é sua:
|
|
643
|
+
`flow_id` do item `start_flow` tem que ser DIFERENTE do flow que está sendo editado.
|
|
644
|
+
|
|
645
|
+
**Condição: preencha `operator` E `field` JUNTOS.** O motor executa pelo `operator`, mas a tela
|
|
646
|
+
reabre a regra casando `operator`+`field` — condição escrita só com um dos dois roda certo e
|
|
647
|
+
APARECE errada pro cliente. Pares corretos:
|
|
648
|
+
|
|
649
|
+
| Condição | `field` | `operator` | `valueType` |
|
|
650
|
+
|---|---|---|---|
|
|
651
|
+
| Conversa TEM etiqueta | `{{conversation.label}}` | `conversation_has_label` | `labels_multi` |
|
|
652
|
+
| Conversa SEM etiqueta | `{{conversation.label}}` | `conversation_no_label` | `labels_multi` |
|
|
653
|
+
| Contato TEM etiqueta | `{{contact.label}}` | `contact_has_label` | `labels_multi` |
|
|
654
|
+
| Contato SEM etiqueta | `{{contact.label}}` | `contact_no_label` | `labels_multi` |
|
|
655
|
+
| Existe card | `_kanban_check` | `kanban_exists` | `funnel_stage` |
|
|
656
|
+
| Card em etapa | `_kanban_stage` | `kanban_in_stage` | `funnel_stage` |
|
|
657
|
+
| Card ganho | `_kanban_status` | `kanban_won` | `funnel_only` |
|
|
658
|
+
| Card perdido | `_kanban_status` | `kanban_lost` | `funnel_only` |
|
|
659
|
+
| Resposta do cliente | `{{last_response}}` | `equal_any` (e variações `_any`) | `response_multi` |
|
|
660
|
+
| Resposta do atendente | `{{last_agent_response}}` | `equal_any` (e variações `_any`) | `response_multi` |
|
|
661
|
+
|
|
662
|
+
Nas condições de etiqueta, `values` aceita array de títulos ou string separada por vírgula.
|