@lionchat/mcp-server 1.31.0 → 1.33.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.
@@ -62,7 +62,7 @@ Todo node tem essa estrutura base:
62
62
 
63
63
  **ATENÇÃO — chave `items`, não `triggers` (corrigido 19/08/2026).** Os gatilhos vão em **`data.items`**, cada item no formato **`{ "key": "...", "config": { ...filtros... } }`**. O formato antigo (`data.triggers` + `type` + filtros soltos no topo) ainda é aceito pelo motor por compatibilidade, mas **NÃO deve ser usado em fluxo novo**: o editor do FlowBuilder lê apenas `data.items`, então um fluxo gravado no formato antigo **dispara normalmente mas abre com o bloco Início EM BRANCO no painel do cliente** — e um clique em "Concluir" naquele modal apagava o gatilho em silêncio. Foram 53 fluxos de 9 contas nesse estado até o conserto de 19/08. Alguns leitores do backend (`has_webhook_trigger?` do disparo por webhook, o filtro de Campanha de Fluxo, o gatilho LionTrack e o histórico de execução) também só entendem `items`.
64
64
 
65
- **Triggers válidos:** `message_received`, `message_sent`, `conversation_created`, `conversation_resolved`, `conversation_reopened`, `team_changed`, `assignee_changed`, `label_added`, `label_removed`, `sla_missed`, `card_created`, `card_moved`, `card_won`, `card_lost`, `card_opened`, `card_snoozed`, `conversation_attribute_changed`, `card_attribute_changed`, `contact_attribute_changed`, `date_trigger`, `campaign_trigger`, `manual_trigger`, `webhook_received`, `page_track`, `group_participant_joined`, `group_participant_left`, `lead_form_completed`, `lead_form_milestone`, `lead_form_abandoned`, `booking_created`, `booking_cancelled`, `booking_rescheduled`, `booking_completed`.
65
+ **Triggers válidos:** `message_received`, `message_sent`, `conversation_created`, `conversation_resolved`, `conversation_reopened`, `team_changed`, `assignee_changed`, `label_added`, `label_removed`, `sla_missed`, `card_created`, `card_moved`, `card_won`, `card_lost`, `card_opened`, `card_snoozed`, `card_open_in_stage`, `card_open_in_funnel`, `conversation_attribute_changed`, `card_attribute_changed`, `contact_attribute_changed`, `date_trigger`, `campaign_trigger`, `manual_trigger`, `webhook_received`, `page_track`, `group_participant_joined`, `group_participant_left`, `lead_form_completed`, `lead_form_milestone`, `lead_form_abandoned`, `booking_created`, `booking_cancelled`, `booking_rescheduled`, `booking_completed`.
66
66
 
67
67
  **NÃO existem** os gatilhos `webhook` (o correto é **`webhook_received`**) nem `cron` (para disparo por data use `date_trigger`; para disparo em lote use `campaign_trigger` + Campanha de Fluxo). Até 19/08/2026 este guia listava os dois por engano — o fluxo 180 da conta 54 ficou ATIVO com `webhook` e **nunca disparou uma vez em 26 dias**, sem erro nenhum.
68
68
 
@@ -75,6 +75,13 @@ Todo node tem essa estrutura base:
75
75
  - `card_created` / `card_moved`: `funnel_ids` (array de STRINGS, ex.: `["37"]` — número puro `[37]` NÃO casa) + `funnel_stages` (array de `"funnel_id:chave_da_etapa"`, ex.: `"37:agendamento_pendente"`). A `chave_da_etapa` é a CHAVE INTERNA da etapa no funil (slug legível em funis de template; pode ser um UUID/`stage_<n>` em etapa criada à mão ou funil duplicado) — NÃO o nome exibido na tela. Sem `funnel_ids` → dispara em qualquer funil; com `funnel_ids` mas sem `funnel_stages` → qualquer etapa daquele(s) funil(is). O card precisa estar num funil listado em `funnel_ids` pra o filtro de etapa valer. ATENÇÃO: dois flows ATIVOS na mesma inbox com `card_created`/`card_moved` de funil/etapa sobrepostos são bloqueados na criação/ativação (ver `flow_trigger_conflict` no fim deste guia).
76
76
  - `team_changed`: `team_ids` (array de STRINGS; vazio = qualquer equipe). `assignee_changed`: `agent_ids` (array de STRINGS; vazio = qualquer atendente). `card_won` / `card_lost`: `funnel_ids` (array de STRINGS) — disparam SÓ quando o STATUS do card vira ganho/perdido, nunca por etapa com esse nome.
77
77
  - `card_opened` ("Card aberto") / `card_snoozed` ("Card adiado") — NOVOS 11/10/2026, mesma config `funnel_ids` (array de STRINGS; vazio = qualquer funil). `card_snoozed` dispara quando o card é ADIADO. `card_opened` dispara quando um card adiado ABRE (pela data, por alguém ou por automação) e também quando um card ganho/perdido é REABERTO — card NOVO não dispara (para isso existe `card_created`). Pela data, o fluxo sai pela fila de disparos agendados, uma vez por card. Use `{{trigger.kanban.previous_status}}` (`snoozed`/`won`/`lost`) para separar "voltou do adiamento" de "reabriram um ganho/perdido".
78
+ - `card_open_in_stage` ("Card aberto na etapa") / `card_open_in_funnel` ("Card aberto no funil") — NOVOS 28/10/2026, gatilhos de **PRAZO**: disparam o fluxo UMA vez quando o card cruza um prazo ("lead parado"). Item: `{ "key": "card_open_in_stage", "config": { "funnel_ids": ["12"], "funnel_stages": ["12:novo_lead"], "duration_value": 1, "duration_unit": "hours" } }`; `card_open_in_funnel` tem a mesma config **sem** `funnel_stages`. `funnel_ids` (array de STRINGS) vazio = qualquer funil; `funnel_stages` (`"<funil>:<chave_da_etapa>"`) vazio = qualquer etapa. `duration_unit` = `minutes`|`hours`|`days`; `duration_value` inteiro (ou texto de inteiro, ex.: `"2"`); o servidor recusa (422) prazo fora de **15 minutos a 365 dias**, unidade desconhecida e funil de outra conta.
79
+ - **Relógio:** `card_open_in_stage` conta o tempo desde que o card ENTROU na etapa atual (o SEGUNDO número do "2d / 1d" do card no quadro; trocar de funil também recomeça). `card_open_in_funnel` conta a idade do card desde a criação (o PRIMEIRO número, "2d"; trocar de funil NÃO recomeça).
80
+ - **Quem conta:** card ABERTO ou ADIADO; ganho e perdido nunca. Dispara **uma vez por entrada na etapa** (`card_open_in_stage`: sai e volta = conta do zero) e **uma vez por card** (`card_open_in_funnel`).
81
+ - **Só dispara quem CRUZA o prazo com o fluxo ligado.** Card que já passou do prazo quando o fluxo foi ligado NÃO dispara (nem depois); com prazo de 5 dias, o card que está com 4 dispara ao chegar a 5. Mudar o prazo, o funil ou a etapa do gatilho vale como gatilho NOVO: só cruzamentos depois da mudança disparam. Relógio corrido (noite e fim de semana contam); a conferência roda de 5 em 5 minutos, então o fluxo pode começar até ~5 min depois do prazo.
82
+ - **Onde roda:** inicia SÓ o fluxo dono do gatilho, em cada conversa do card (card sem conversa não dispara). O card que disparou é o "card do gatilho": `card_source: 'trigger'` funciona e as condições "Card na etapa" / "Card adiado" olham para ele. Variáveis `{{trigger.kanban.title}}`, `.funnel_name`, `.stage_name`, `.stage` valem como nos outros gatilhos de card; `{{trigger.type}}` = a própria chave (`card_open_in_stage` / `card_open_in_funnel`).
83
+ - Dois fluxos com o mesmo gatilho na mesma caixa são permitidos (não há checagem de conflito): os dois disparam.
84
+ - Exemplo — avisar um grupo de WhatsApp quando o lead passa mais de 1 hora na etapa do vendedor: Início `card_open_in_stage` (1 hora, funil + etapa) → (opcional) condição "Card na etapa" → bloco `update_group` com a operação de enviar mensagem ao grupo, texto usando `{{agent.name}}` e o link da conversa `https://<host>/app/accounts/<id_da_conta>/conversations/{{conversation.id}}`.
78
85
  - `page_track` (LionTrack, só flow individual): `{ "track_type": "visited_page"|"event_fired", "urls": [...], "operator": "contains"|"exact"|"starts_with", "event_names": [...], "event_operator": "equals"|"contains", "cooldown_hours": 24 }` — `cooldown_hours` (padrão 24, mínimo 1) não re-dispara pro mesmo contato dentro da janela.
79
86
  - `conversation_attribute_changed` / `card_attribute_changed` (novo 2026-07-08): disparam na VIRADA de um atributo (da CONVERSA ou do CARD do kanban) pro valor que casa — RE-ENTRAM toda vez que o atributo muda pro valor alvo. Config: `{ "logic": "and"|"or", "rules": [ { "attr_key": "...", "operator": "...", "value": "..." } ] }` (uma rule pode usar `values: [...]` no lugar de `value` pra multi-valor). O `attrSource` é IMPLÍCITO pela chave do gatilho (conversa vs card) — NÃO informe. Operadores (contexto REATIVO — desde 09/07 `is_empty`/`is_not_empty` NÃO valem aqui, pois "está vazio AGORA" dispararia a cada evento; use-os só no nó Condição): `equal`/`not_equal`/`contains`/`not_contains`/`starts_with`/`ends_with`/`greater_than`/`less_than`/`number_range`. Só `card_attribute_changed` aceita `funnel_id`/`card_source` opcionais dentro da rule (pra achar o card). Rule sem `attr_key` é ignorada.
80
87
  - `contact_attribute_changed` (novo 2026-07-22 — "Atributo do contato muda"): dispara quando um atributo personalizado do **CONTATO** muda e a condição casa — mesmo com o contato fora de flow. Item: `{ "key": "contact_attribute_changed", "config": { "logic": "and"|"or", "rules": [ { "attrSource": "contact", "attr_key": "...", "operator": "...", "value": "..." } ] } }` (1 a 10 rules; `values: [...]` pra multi-valor). **DIFERENTE dos irmãos de 08/07: aqui o `attrSource` VAI na rule e é SEMPRE `"contact"`.** Operadores iguais aos do nó Condição. **VERSÃO SEGURA por decisão de produto:** dispara SÓ na conversa mais recente que JÁ EXISTE numa caixa do flow (reabre se resolvida); contato sem conversa NÃO dispara e NUNCA cria conversa. Dedup de 30s por contato + anti-loop por profundidade de cadeia (flow que muda atributo que dispara flow…). Só flows de conversa.
@@ -156,7 +163,7 @@ Webhooks embutidos NÃO aparecem na listagem de integrações standalone; exclui
156
163
  **Gatilhos de AGENDAMENTO — Booking NATIVO do LionChat (2026-08-20):** `booking_created` (alguém marcou pelo link público, pela IA ou pelo painel), `booking_cancelled` (paciente cancelou pelo link, IA cancelou ou a equipe cancelou na Agenda), `booking_rescheduled` (a data/hora mudou — link do paciente, IA, editar/adiar na Agenda), `booking_completed` (equipe concluiu na Agenda; exige a Agenda unificada ligada na conta). **Não é e-Clínica.** Config (tudo opcional, vazio = todos): `booking_event_type_ids` (array de ids de tipo de agendamento, **STRING**), `agent_ids` (array de ids de usuário — o RESPONSÁVEL da tarefa), `create_conversation` (boolean, padrão `false`: só dispara para quem já tem conversa numa caixa do flow; `true` = cria a conversa na 1ª caixa do flow). Exemplo: `{ "key": "booking_created", "config": { "booking_event_type_ids": ["44"], "agent_ids": [], "create_conversation": true } }`. São INERTES a evento de conversa (quem dispara é o `Booking::FlowTriggerDispatcher`, por CONTA — caixa do flow só define onde a conversa é criada/reusada). Variáveis no flow: `{{booking.date}}` (DD/MM/AAAA), `{{booking.time}}`, `{{booking.weekday}}`, `{{booking.datetime}}` (ISO), `{{booking.type}}`, `{{booking.type_format}}` (presencial/videochamada), `{{booking.duration}}`, `{{booking.agent}}`, `{{booking.status}}` (confirmado/cancelado/remarcado/concluído), `{{booking.description}}`, `{{booking.cancel_url}}`, `{{booking.reschedule_url}}`, `{{booking.confirm_url}}`, `{{booking.calendar_url}}` (16/10: página onde o cliente salva o compromisso na agenda DELE, sem e-mail; no remarcado já sai com a hora nova — é o jeito de avisar a mudança, pedindo para apagar o compromisso antigo), `{{booking.color}}`, `{{booking.id}}`; só no remarcado: `{{booking.previous_date}}`, `{{booking.previous_time}}`, `{{booking.previous_datetime}}`; `{{booking.meeting_url}}` NÃO vem no criado (nasce vazio). Data/hora vêm da TAREFA da Agenda (sempre atuais). Regras: o evento mais novo SUBSTITUI a rodada ativa do mesmo flow na mesma conversa (2ª consulta do mesmo paciente, ou cancelado chegando com o criado ainda esperando resposta); excluir a tarefa, reabrir cancelada ou desfazer conclusão NÃO disparam; adiar (snooze) conta como remarcado; tipo com confirmação/lembrete próprios ligados + `booking_created` = o paciente pode receber duas mensagens (a tela avisa). Colisão entre flows é por CONTA: mesmo kind + tipos se cruzando + agentes se cruzando (vazio = todos). Há também `{{booking.event}}` (`created`|`cancelled`|`rescheduled`|`completed` — bom pra condição; não aparece no seletor da tela, mas resolve); `{{trigger.type}}` = a chave do gatilho (ex.: `booking_created`), `{{trigger.kind}}` = `created`|`cancelled`|`rescheduled`|`completed` e `{{trigger.booking_id}}`. SÓ flow de conversa **individual** (a tela nem oferece em flow de grupo); **nunca dispara flow `ai_tool`**. Em caixa WhatsApp OFICIAL, conversa criada nova (ou parada há mais de 24h) está FORA da janela — texto livre no 1º bloco cai em `window_closed`/erro; comece por template.
157
164
 
158
165
  **TRAVA DE GATILHO DUPLICADO (2026-06-16) — leia ANTES de ativar/criar flow ativo:** o sistema BLOQUEIA ter dois flows ATIVOS com o MESMO gatilho na MESMA inbox e mesmo `conversation_mode` (evita o evento disparar dois flows). Colisão = mesmo tipo de gatilho + config cruzando (mesmas keywords/funil/labels/url/etc) + inbox compartilhada + mesmo modo. EXCEÇÕES que podem coexistir: `webhook_received`, `manual_trigger` e `campaign_trigger` (este último porque não dispara por evento — é só uma autorização para a campanha).
159
- - **`date_trigger` separa por HORÁRIO (24/09/2026):** dois flows no mesmo campo de data, mesma direção e mesmos dias NÃO colidem se os dois tiverem horário FIXO diferente (ex.: "1 dia depois às 08:00" e "às 14:00"). Horário vindo de atributo/fórmula continua colidindo (só existe na hora do disparo); `send_time` vazio conta como 09:00 e "8:00" = "08:00". A entrega é de 10 em 10 minutos — horários a menos de 10 min podem sair juntos.
166
+ - **`date_trigger` separa por HORÁRIO (24/09/2026):** dois flows no mesmo campo de data, mesma direção e mesmos dias NÃO colidem se os dois tiverem horário FIXO diferente (ex.: "1 dia depois às 08:00" e "às 14:00"). Horário vindo de atributo/fórmula continua colidindo (só existe na hora do disparo); `send_time` vazio conta como 09:00 e "8:00" = "08:00". A entrega é de minuto em minuto (desde 26/10/2026) — horários no mesmo minuto saem juntos.
160
167
  - Ao **ativar** (`flows_toggle` inativo→ativo) ou **criar já ativo**: qualquer conflito é barrado.
161
168
  - Ao **editar** um flow já ativo: só conflito NOVO é barrado (duplicados que já existiam são preservados).
162
169
  - A API responde **422** com `{ "error_code": "flow_trigger_conflict", "conflicts": [{ flow_id, flow_name, trigger_type, inbox_id, inbox_name }] }`.
@@ -460,9 +467,34 @@ campanha"):
460
467
  (origem unificada), `ctwa_*` (anúncio click-to-WhatsApp: `ctwa_ad_id`, `ctwa_ad_title`, `ctwa_campaign_name`,
461
468
  `ctwa_adset_name`...), `meta_lead_*` (formulário Meta Lead Ads), `lt_*` (LionTrack: UTMs, página, dispositivo).
462
469
  Veja a lista real com `lionchat_custom_attributes_list` (`attribute_model: conversation_attribute` — com o sufixo; só `conversation` devolve a lista VAZIA —, `include_system: true` — as chaves de campanha são atributos de sistema).
463
- - **Valores fechados** de `origin_kind` (e `origin_first_kind`/`origin_last_kind`): `paid_ad` (Anúncio),
464
- `lead_form` (Formulário), `organic` (Orgânico), `direct` (Direto), `referral` (Indicação), `manual` (Origem
465
- cadastrada). O painel mostra o rótulo em português, mas a comparação é pelo VALOR — `"Anúncio"` nunca casa.
470
+ - **Valores fechados** de `origin_kind` (e `origin_first_kind`/`origin_last_kind`): `paid_ad` (Anúncio (clique)),
471
+ `lead_form` (Anúncio (formulário)), `organic` (Orgânico), `direct` (Direto), `referral` (Indicação),
472
+ `agendamento` (Página de agendamento), `formulario` (Formulário do site), `manual` (Origem cadastrada). O painel
473
+ mostra o rótulo em português, mas a comparação é pelo VALOR — `"Anúncio"` nunca casa.
474
+ - **Desde 26/10/2026, o formulário do mesmo anúncio continua formulário:** quando a pessoa preenche o formulário do
475
+ Meta e depois clica no MESMO anúncio para abrir o WhatsApp, a conversa fica com `origin_kind: "lead_form"` (antes
476
+ virava `paid_ad`). Conversas anteriores a 26/10 não mudam.
477
+
478
+ **"Veio de anúncio pago" — chave `origin_paid` (25/10/2026). USE ESTA para "só lead de anúncio":**
479
+ `origin_kind equal paid_ad` deixa de fora quem veio pelo FORMULÁRIO do anúncio (`lead_form`) — foi o defeito real da
480
+ Cast (conta 137, fluxo 590: a IA nunca ligou para os leads de formulário de 08/10 a 24/10). A chave `origin_paid` junta
481
+ as duas portas do anúncio. Forma que a tela grava (reabre no card "Veio de anúncio pago", Sim/Não):
482
+
483
+ ```json
484
+ { "id": "c1", "valueType": "attr_config", "attrSource": "conversation", "attrScope": "origin_paid",
485
+ "attr_key": "origin_paid", "operator": "equal", "value": "", "values": ["paid"] }
486
+ ```
487
+
488
+ - Sim = `operator: "equal"`; Não = `operator: "not_equal"` (inclui conversa sem origem e origem cadastrada a mão).
489
+ - Valores possíveis (calculados na hora, nunca gravados): `paid` (`paid_ad` ou `lead_form`), `not_paid` (orgânico,
490
+ direto, indicação, página de agendamento, formulário do site), `unknown` (`manual` ou tipo desconhecido — nunca é
491
+ tratado como pago), `unclassified` (sem origem ainda).
492
+ - É chave VIRTUAL: não existe em `custom_attributes`, não aparece em `lionchat_custom_attributes_list`, não serve em
493
+ `{{conversation.custom_attribute.origin_paid}}` nem como gatilho "atributo mudou". Só em condição (fluxo e
494
+ automação) e no filtro de conversas.
495
+ - A mesma pergunta existe na automação (condição `origin_paid`, operadores `equal_to`/`not_equal_to`), no filtro de
496
+ conversas (`lionchat_conversations_filter`) e no relatório de origem (`paid` e `by_paid` em
497
+ `lionchat_lead_origin_reports`).
466
498
  - `origin_platform` (e first/last): `facebook`, `instagram`, `google`, `tiktok`, `linkedin`, `youtube`,
467
499
  `whatsapp`, `email`, `messenger`, `audience_network` (Rede de parceiros da Meta, desde 29/09/2026), `direct` — e, para origem cadastrada pelo cliente em Configurações > Origens de Lead,
468
500
  `custom:<slug>` (slug = nome parametrizado, ex.: "Indicação de amigo" → `custom:indicacao-de-amigo`;
@@ -472,7 +504,8 @@ campanha"):
472
504
  "operator": "equal", "value": "paid_ad", "valueType": "variable" }` — reabre no card "Variável", não no de
473
505
  campanha. Prefira o formato `attr_config` acima quando o cliente vai editar pela tela.
474
506
  - Caso real (Cast, 01/09): flow "Ativar IA" só para lead de anúncio = condição `origin_kind equal paid_ad`
475
- na saída `cond_0` + ação `assign_captain` nessa saída; `default` sem nada.
507
+ na saída `cond_0` + ação `assign_captain` nessa saída; `default` sem nada. **Desde 25/10 use `origin_paid equal paid`
508
+ (seção acima)**: `origin_kind equal paid_ad` não pega o lead do formulário do anúncio.
476
509
 
477
510
  - **`attrScope: "lead_origin"` (02/09/2026):** preset "Origem do lead" da aba Conversas — mesmo shape do `campaign_attr`, ja nasce com `attr_key: "origin_platform"`. Valores: plataformas fixas (`facebook`, `google`...) ou origem cadastrada como `custom:<slug>`. O motor ignora `attrScope`; sem ele a regra reabre como "Atributo de campanha" (falha macia).
478
511
 
@@ -570,13 +603,51 @@ o botão "Usar variável" ao lado do campo alterna lista fixa ↔ variável.
570
603
  | `send_conversion` (novo 2026-09-01; `event_names` 2026-09-02; `messaging_event_names` 2026-09-10) | `{ destinations: ['meta'\|'ga4'\|'google_ads'], event_names: { meta?, google_ads?, ga4? }, messaging_event_names: { meta? }, event_name (reserva), value? }` | Manda o evento de conversão pro Meta (CAPI), Google Ads e/ou GA4 — o mesmo caminho do Funil, de dentro do fluxo. Aba Sistema (só flow `conversation`). Ver bloco próprio abaixo |
571
604
  | `deactivate_flow` ou `disable_flow` | `{}` | Encerra fluxo atual |
572
605
  | `set_booking_situation` (novo 2026-09-14) | `{ situation: 'cancelled' \| 'completed' \| 'attended' \| 'no_show' \| 'confirmed' }` | Muda a situação do agendamento **que disparou o fluxo** (gatilho de agendamento do bloco Início, ou fluxo ligado na configuração do tipo de agendamento). Aba **Agenda** (só flow `conversation`, só com a Agenda ligada na conta). Disparado por outra coisa: **não faz efeito e o passo fica com erro visível** (não há como adivinhar o agendamento). Já no estado pedido = passo PULADO, sem escrita (sem evento, sem laço). `cancelled` cancela o **agendamento** (desarma lembretes, invalida o link de gerenciar). Origem gravada = `fluxo`, ator = o próprio flow. Sem `rescheduled`/`snoozed`: o bloco não mexe em data |
606
+ | `create_account_task` (novo 2026-10-20) | `{ title, description?, task_type, agenda_id?, priority?, occupies_agenda?, duration_minutes?, due: {amount, unit: 'hours' \| 'days', at?, business_days?}, responsible: {mode: 'card_owner' \| 'fixed' \| 'funnel_rotation' \| 'team_rotation', user_id?, team_id?, fallback_user_id?}, card_source: 'funnel' \| 'trigger', funnel_id? }` | "Criar tarefa": cria uma tarefa COMUM da Agenda, presa ao card do fluxo (ou só à conversa, se não houver card). Os campos de `title` a `responsible` são os MESMOS da ação `create_task` da automação do funil (ver `kanban-deep-dive`). Aba **Agenda**; exige a Agenda unificada ligada na conta. **NÃO roda em fluxo `ai_tool` nem em fluxo de grupo** (o motor recusa com erro visível no passo; o save aceita, a tela esconde o item). Detalhes logo abaixo |
573
607
  | `update_attribute` | `{ attr_source: 'contact'\|'conversation'\|'card', attr_key, attr_value }` | Seta custom_attribute (ver abaixo) |
574
608
  | `assign_captain` (ou `assign_captain_assistant`) | `{ assistant_id }` | Atribui IA Captain |
575
609
  | `deactivate_captain` | `{}` | Tira a IA da conversa |
576
610
 
577
611
  **Handles que SAEM:** `success`. Não tem handle `error` — falhas viram warning silencioso e o flow continua.
578
612
 
579
- **`card_source` (blocos de card) — opcional:** as ações de card aceitam `card_source`: `'funnel'` (default — procura o card pelo `funnel_id`) ou `'trigger'` (usa o card que DISPAROU o flow, em flows iniciados por `card_created`/`card_moved`/`card_won`/`card_lost`/`card_opened`/`card_snoozed`). Com `'trigger'`, `funnel_id` deixa de ser obrigatório — EXCETO em `move_kanban_stage`/`create_kanban_item`, cujo funil/etapa são o DESTINO. Sem card-gatilho disponível, a ação é pulada (não cai no fallback de funil). Aplica-se a `move_kanban_stage`, `set_won`/`set_lost`/`set_open`, `snooze_kanban_item` (esta, sem card-gatilho, dá ERRO em vez de pular), `assign_agent_card`, `add_card_note`, `add_card_checklist`, `add_card_offer`, `update_attribute` (com `attr_source: 'card'`) e às condições `card_attr_equals`/`card_attr_contains` (gravando `card_source` na própria regra).
613
+ **`card_source` (blocos de card) — opcional:** as ações de card aceitam `card_source`: `'funnel'` (default — procura o card pelo `funnel_id`) ou `'trigger'` (usa o card que DISPAROU o flow, em flows iniciados por `card_created`/`card_moved`/`card_won`/`card_lost`/`card_opened`/`card_snoozed`/`card_open_in_stage`/`card_open_in_funnel`). Com `'trigger'`, `funnel_id` deixa de ser obrigatório — EXCETO em `move_kanban_stage`/`create_kanban_item`, cujo funil/etapa são o DESTINO. Sem card-gatilho disponível, a ação é pulada (não cai no fallback de funil). Aplica-se a `move_kanban_stage`, `set_won`/`set_lost`/`set_open`, `snooze_kanban_item` (esta, sem card-gatilho, dá ERRO em vez de pular), `assign_agent_card`, `add_card_note`, `add_card_checklist`, `add_card_offer`, `create_account_task` (aqui sem card-gatilho = ERRO; ver abaixo), `update_attribute` (com `attr_source: 'card'`) e às condições `card_attr_equals`/`card_attr_contains` (gravando `card_source` na própria regra).
614
+
615
+ **`create_account_task` — Criar tarefa (2026-10-20):**
616
+
617
+ ```json
618
+ { "key": "create_account_task", "config": {
619
+ "title": "Ligar para {{contact.name}}", "description": "", "task_type": "call", "agenda_id": null,
620
+ "priority": "none", "occupies_agenda": false, "duration_minutes": 45,
621
+ "due": { "amount": 3, "unit": "days", "at": "09:00", "business_days": true },
622
+ "responsible": { "mode": "card_owner", "fallback_user_id": 12 },
623
+ "card_source": "trigger", "funnel_id": ""
624
+ } }
625
+ ```
626
+
627
+ - **Os campos da regra** (`title`, `description`, `task_type`, `agenda_id`, `priority`, `due`, `responsible`,
628
+ `occupies_agenda`, `duration_minutes`) têm o mesmo formato e os mesmos limites da ação `create_task` do funil: `title` obrigatório; `due`
629
+ em horas (1 a 720) ou dias (0 a 365, com `at` "HH:MM" e `business_days` só em dias); `responsible.mode` com a chave
630
+ obrigatória do modo (`fallback_user_id`, `user_id` ou `team_id`; `funnel_rotation` não pede nenhuma no save,
631
+ mas no fluxo SEM card o rodízio do funil não tem funil e cai na pessoa reserva `fallback_user_id` — sem reserva a
632
+ tarefa não nasce, com o motivo no histórico: mande `fallback_user_id` se o fluxo puder rodar sem card). Regra torta =
633
+ passo VERMELHO com a frase do campo a consertar, sem tarefa.
634
+ - **Duração**: `duration_minutes` (22/10/2026): minutos que a tarefa ocupa, inteiro de 1 a 1440; ausente ou `null` = o tempo do TIPO (Tarefa/Follow-up/Prazo 15, Ligação/Personalizado 30, Reunião/Call 60, tipo criado pela conta 30). Com `occupies_agenda: true` o horário ocupado vai do prazo até o fim da duração.
635
+ - **De onde vem o card (`card_source`)**: `'trigger'` = o card que INICIOU o fluxo (gatilhos `card_created`,
636
+ `card_moved`, `card_won`, `card_lost`, `card_opened`, `card_snoozed`, `card_open_in_stage`, `card_open_in_funnel`); fluxo que não nasceu de card = ERRO
637
+ visível, nunca pulado. `'funnel'` (o padrão da tela) = o card DESSA conversa no funil `funnel_id` (**obrigatório**
638
+ neste modo; funil sem `funnel_id` ou que não existe mais = erro). Conversa sem card naquele funil não é erro: a
639
+ tarefa nasce SÓ na conversa e o passo diz "sem card". Variáveis `{{ }}` em `title` e `description` resolvem pelo
640
+ resolvedor do FLUXO.
641
+ - **Uma tarefa por passagem do bloco**: repetir o MESMO passo (nova tentativa do sistema) não duplica; uma nova
642
+ passagem pelo bloco (o fluxo rodando de novo) cria outra tarefa.
643
+ - **Ritmo**: há um freio de 1 tarefa por segundo por conta. Passo com vaga futura já fica verde ("nasce às
644
+ HH:MM:SS"); se depois a tarefa for reprovada (responsável que saiu da conta, dado inválido), o aviso vai para a
645
+ linha do card ("Fluxo X não criou a tarefa", só com card) e para o log — o passo não muda.
646
+ - **Histórico do card**: "Fluxo X criou uma tarefa (tipo) para Fulana" / "Fluxo X não criou a tarefa: motivo".
647
+ A tarefa grava o Fluxo como quem agendou (`booking_source` `fluxo`).
648
+ - O interruptor de emergência da automação do funil NÃO vale para o fluxo; a Agenda unificada desligada vale (erro
649
+ visível no passo).
650
+ - **Fluxo `ai_tool` e fluxo de grupo**: não use este item (recusado na execução, com erro visível no passo).
580
651
 
581
652
  **`send_conversion` — Enviar conversão (2026-09-01):**
582
653
 
@@ -1232,7 +1303,7 @@ Sempre presente:
1232
1303
 
1233
1304
  | Variável | Conteúdo |
1234
1305
  |---|---|
1235
- | `{{trigger.type}}` | código do **EVENTO** que disparou — **NÃO é a chave do item do Início**. Valores reais: `message_created` (gatilho `message_received`), `message_sent`, `conversation_created`, `conversation_opened` (gatilho `conversation_reopened`), `conversation_resolved`, `label_added`, `label_removed`, `team_changed`, `assignee_changed`, `sla_missed`, `kanban_item_created`/`card_created`, `kanban_item_stage_changed`/`card_moved`, `card_status_changed` (`card_won`, `card_lost`, `card_opened` e `card_snoozed` — olhe `{{trigger.kanban.status}}`: `won`/`lost`/`open`/`snoozed`; rótulo "Situação do card mudou" desde 11/10/2026), `conversation_attributes_changed`, `card_attributes_changed`, `contact_attribute_changed`, `group_participant_joined`/`_left`, `webhook_received`, `date_trigger`, `manual` (sidebar), `kanban_manual` (botão do card), `campaign` (Campanha de Fluxo), `page_track`, `activated_by_flow` (fluxo chamou fluxo), `lead_form` (os 3 gatilhos de formulário — `trigger.kind` diz `completed`/`milestone`/`abandoned`), `booking_created`/`booking_cancelled`/`booking_rescheduled`/`booking_completed`. Compare SEMPRE com esses códigos numa condição |
1306
+ | `{{trigger.type}}` | código do **EVENTO** que disparou — **NÃO é a chave do item do Início**. Valores reais: `message_created` (gatilho `message_received`), `message_sent`, `conversation_created`, `conversation_opened` (gatilho `conversation_reopened`), `conversation_resolved`, `label_added`, `label_removed`, `team_changed`, `assignee_changed`, `sla_missed`, `kanban_item_created`/`card_created`, `kanban_item_stage_changed`/`card_moved`, `card_status_changed` (`card_won`, `card_lost`, `card_opened` e `card_snoozed` — olhe `{{trigger.kanban.status}}`: `won`/`lost`/`open`/`snoozed`; rótulo "Situação do card mudou" desde 11/10/2026), `conversation_attributes_changed`, `card_attributes_changed`, `contact_attribute_changed`, `group_participant_joined`/`_left`, `webhook_received`, `date_trigger`, `manual` (sidebar), `kanban_manual` (botão do card), `campaign` (Campanha de Fluxo), `page_track`, `card_open_in_stage` / `card_open_in_funnel` (o `type` é a própria chave do gatilho de prazo; rótulo "Card aberto na etapa" / "Card aberto no funil"), `activated_by_flow` (fluxo chamou fluxo), `lead_form` (os 3 gatilhos de formulário — `trigger.kind` diz `completed`/`milestone`/`abandoned`), `booking_created`/`booking_cancelled`/`booking_rescheduled`/`booking_completed`. Compare SEMPRE com esses códigos numa condição |
1236
1307
  | `{{trigger.name}}` | rótulo legível do MESMO evento ("Mensagem recebida", "Card mudou de etapa") — use este pra ESCREVER pro cliente, e o `type` pra COMPARAR em condição |
1237
1308
  | `{{trigger.activated_at}}` | quando disparou (ISO 8601). Desde 20/08/2026 `name` e `activated_at` são preenchidos em TODOS os caminhos de disparo (antes só no de evento de conversa) |
1238
1309
  | `{{trigger.kanban_item_id}}` / `{{trigger.funnel_id}}` | só quando veio do Kanban |
@@ -1272,7 +1343,7 @@ Oferecidos no autocompletar (só quando o bloco Início tem o gatilho que os pre
1272
1343
 
1273
1344
  | Gatilhos do Início | Variáveis |
1274
1345
  |---|---|
1275
- | `card_created`, `card_moved`, `card_won`, `card_lost`, `card_opened`, `card_snoozed`, `card_attribute_changed` | `{{trigger.kanban.title}}`, `{{trigger.kanban.funnel_name}}`, `{{trigger.kanban.stage_name}}`, `{{trigger.kanban.stage}}` (código da etapa) |
1346
+ | `card_created`, `card_moved`, `card_won`, `card_lost`, `card_opened`, `card_snoozed`, `card_open_in_stage`, `card_open_in_funnel`, `card_attribute_changed` | `{{trigger.kanban.title}}`, `{{trigger.kanban.funnel_name}}`, `{{trigger.kanban.stage_name}}`, `{{trigger.kanban.stage}}` (código da etapa) |
1276
1347
  | `card_moved` | `{{trigger.kanban.previous_stage_name}}`, `{{trigger.kanban.previous_stage}}` |
1277
1348
  | `card_won`, `card_lost`, `card_opened`, `card_snoozed` | `{{trigger.kanban.status}}` (`won`/`lost`/`open`/`snoozed`) |
1278
1349
  | `card_opened` | `{{trigger.kanban.previous_status}}` (`snoozed` = voltou do adiamento; `won`/`lost` = reabriram um ganho/perdido) |
@@ -663,6 +663,39 @@ uma entrada por vez; quem entrar enquanto os balões da pessoa anterior saem nã
663
663
 
664
664
  ---
665
665
 
666
+ ## 18. Tarefa de acompanhamento ao ganhar um card (`create_account_task`)
667
+
668
+ **Caso:** quando um card é marcado como GANHO, criar para o responsável do card uma tarefa "Ligar para <cliente>" daqui a
669
+ 3 dias úteis, às 09:00 (pula sábado, domingo e feriado de dia inteiro da agenda). Usa o item "Criar tarefa" do bloco
670
+ Ações (aba Agenda). Pré-requisito: Agenda unificada ligada na conta. Não funciona em fluxo `ai_tool` nem de grupo.
671
+
672
+ ```json
673
+ {
674
+ "nodes": [
675
+ { "id": "n1", "type": "start", "position": { "x": 50, "y": 300 }, "data": { "label": "Início", "items": [{ "key": "card_won", "config": { "funnel_ids": ["1"] } }] } },
676
+ { "id": "n2", "type": "action", "position": { "x": 370, "y": 300 }, "data": { "label": "Tarefa de pós-venda", "items": [
677
+ { "key": "create_account_task", "config": {
678
+ "title": "Ligar para {{contact.name}} (pós-venda)", "description": "", "task_type": "call", "agenda_id": null,
679
+ "priority": "medium", "occupies_agenda": false,
680
+ "due": { "amount": 3, "unit": "days", "at": "09:00", "business_days": true },
681
+ "responsible": { "mode": "card_owner", "fallback_user_id": 12 },
682
+ "card_source": "trigger", "funnel_id": ""
683
+ } }
684
+ ] } }
685
+ ],
686
+ "edges": [
687
+ { "id": "e1", "source": "n1", "target": "n2", "sourceHandle": "success", "type": "deletable", "animated": true }
688
+ ]
689
+ }
690
+ ```
691
+
692
+ Notas:
693
+ - `card_source: "trigger"` usa o card que ganhou; sem `funnel_id`. Para agir sobre o card da conversa em outro funil
694
+ (fluxo disparado por mensagem, por exemplo), use `card_source: "funnel"` com `funnel_id` preenchido.
695
+ - `fallback_user_id` (12 aqui) é a pessoa que recebe quando o card não tem responsável: troque por um id de
696
+ `agents_list`. `task_type` é um dos 7 de fábrica ou uma `key` de `account_task_types_list`.
697
+ - Para a tarefa aparecer SÓ no card (sem bloquear o horário da Agenda) deixe `occupies_agenda` em `false`.
698
+
666
699
  ## Como usar este catálogo
667
700
 
668
701
  1. **Identifique o pattern mais próximo** do que o cliente pediu
@@ -451,7 +451,7 @@ em `responses_show.milestones`.
451
451
 
452
452
  **`lionchat_lead_forms_responses_list`** aceita `status` (`in_progress`, `completed`,
453
453
  `abandoned`), `days` e `page` (até 10.000). A lista nunca traz as respostas em si — só `{id, status,
454
- contact, current_node_label, answered_count, created_at, completed_at}` e `meta: {current_page,
454
+ contact, current_node_label, answered_count, created_at, completed_at, filled_by}` e `meta: {current_page,
455
455
  per_page: 25, total_count}`. **`contact` pode vir `{id: null, name, phone, pending: true}`** — é
456
456
  quem ainda está preenchendo (o contato só nasce nos três momentos); nome e telefone saem do que a
457
457
  pessoa já digitou. `answered_count` conta todas as chaves de `answers`, inclusive as sintéticas.
@@ -479,6 +479,25 @@ falha de transporte sem código), `timeout`, `ssrf_blocked`, `result_too_large`,
479
479
  `no_ai_key`, `ai_error`. (Os motivos `busy` e `unresolved_variable`, citados antes, não existem no
480
480
  código.)
481
481
 
482
+ ### Preenchimento pela equipe, dentro da conversa — 20/10/2026 (entra com o próximo deploy do app)
483
+
484
+ No painel, a barra lateral da conversa ganhou o quadro **Formulários**: o atendente (SDR) abre qualquer formulário
485
+ publicado e ligado numa janela e preenche durante a ligação. Essa resposta é **da equipe**:
486
+
487
+ - `filled_by` (lista, show e Preenchimentos do contato): `null` = o próprio cliente pelo link; `{id, name}` = o
488
+ atendente que preencheu; `{id, removed: true}` = o atendente foi apagado (o selo continua).
489
+ - Contato e conversa ficam **fixos**: os da conversa. Telefone digitado nunca troca de contato nem cria ficha; se já
490
+ for de outra ficha (com ou sem o nono dígito) não é gravado.
491
+ - Todos os blocos rodam como no link (atributos, etiquetas, marco, API, IA, WhatsApp, contrato, agenda). A única
492
+ diferença: o fluxo **"Formulário abandonado"** NÃO dispara — o pulo fica registrado com o motivo `filled_by_team`.
493
+ **"Formulário concluído"** dispara como no link (desde 23/10/2026; de 20 a 23/10 ele também era pulado, e esses
494
+ pulos antigos seguem no histórico). "Marco do formulário" dispara.
495
+ - Fica **fora** de `lionchat_lead_forms_stats` (funil, conclusão) e dos contadores da lista (`responses_count`,
496
+ `completed_count`), e do relatório de formulários. Aparece em `responses_list`/`responses_show` com o selo.
497
+ - Não há ferramenta do MCP para começar esse preenchimento — ele só existe na janela do painel.
498
+ - Atributo gravado por QUALQUER formulário (link ou equipe) acorda o mesmo que a edição manual: automação "atributo
499
+ alterado", fluxos de atributo e webhook (desde 20/10/2026).
500
+
482
501
  ## Preenchimentos do contato (`lionchat_contacts_form_entries_list` / `_show`) — 21/08 (entra com o próximo deploy do app depois de 21/08/2026)
483
502
 
484
503
  A aba "Preenchimentos" da ficha junta, numa lista só ordenada por data, tudo que a pessoa preencheu
@@ -488,7 +507,7 @@ FlowBuilder cria pro gatilho de um fluxo (`flow`, com o nome do fluxo). É a ún
488
507
  "o que esta PESSOA preencheu" — as outras são por formulário/integração, e duas delas são só de
489
508
  administrador; esta é liberada a qualquer agente.
490
509
 
491
- - **Lista**: `{payload: [{source, id, title, status, at, count, conversation}], meta: {total,
510
+ - **Lista**: `{payload: [{source, id, title, status, at, count, conversation, filled_by}], meta: {total,
492
511
  truncated}}`. `id` é o id do registro NA ORIGEM — só identifica junto com `source`. `status` é
493
512
  `in_progress|completed|abandoned` no nosso formulário e `received` nas demais. `count` = respostas
494
513
  (nosso) ou campos vinculados e gravados (de fora). `conversation` só existe em `lead_form`. Sem
@@ -16,7 +16,7 @@ Container de etapas. Conta pode ter vários funis (ex: "Vendas", "Pós-venda", "
16
16
  | `archived` | Boolean — funis arquivados não aparecem na UI ativa |
17
17
  | `active` | Boolean — controla se aceita movimentação |
18
18
  | `settings` | jsonb — config customizada (ex: cores, automações) |
19
- | `settings.agents` | agentes do funil. Grave `[{"id": <id do agente>}]` — cada item é um OBJETO, nunca número solto (ids de `lionchat_agents_list`); o sistema completa nome, e-mail, cargo e foto — é o que o editor do funil, o card e a conversa mostram. Agente de outra conta fica sem nome e sem acesso. `settings` é substituído INTEIRO no update: leia o funil antes e reenvie goals+agents+teams+automations. |
19
+ | `settings.agents` | agentes do funil. Grave `[{"id": <id do agente>}]` — cada item é um OBJETO, nunca número solto (ids de `lionchat_agents_list`); o sistema completa nome, e-mail, cargo e foto — é o que o editor do funil, o card e a conversa mostram. Agente de outra conta fica sem nome e sem acesso. `settings` é substituído INTEIRO no update: leia o funil antes e reenvie goals+agents+teams+automations. `settings.removed_stages` (lista das etapas já excluídas, usada para redirecionar cards) é do SERVIDOR: se você mandar essa chave ela é ignorada, sem erro, e o servidor a mantém sozinho. |
20
20
 
21
21
  ### Stages (Etapas) — dentro de `funnel.stages`
22
22
 
@@ -55,11 +55,55 @@ Stages NÃO são tabela separada. São armazenadas como jsonb dentro do Funnel:
55
55
  da mesma posição, senão pra primeira. **Confira o `funnel_stage` da resposta**: pode ser diferente
56
56
  do que você mandou. Leia `funnels_show` antes e use o slug exato.
57
57
  - `funnels_update` que tira do `stages` uma etapa com card responde **422 `STAGE_HAS_ITEMS`** com
58
- `stages: {"<slug>": <quantos cards>}`. Primeiro mova os cards com `lionchat_funnels_create_2`
59
- (`POST /funnels/{id}/migrate_stage`, `from_stage`, `to_stage` ou `to_funnel_id`) e só então
60
- reenvie o funil sem a etapa. Não existe parâmetro de destino no `update` de propósito.
58
+ `stages: {"<slug>": <quantos cards>}`. **Para EXCLUIR uma etapa que tem cards, use
59
+ `lionchat_funnels_remove_stage`** (`POST /funnels/{id}/remove_stage`, ver "Excluir etapa" abaixo): ela move
60
+ os cards para o destino EM SILÊNCIO e apaga a etapa. **Não** use a receita antiga (mover com `migrate_stage` e depois reenviar
61
+ o funil sem aquela etapa) — o `migrate_stage` (`lionchat_funnels_create_2`) NÃO exclui a etapa: move os
62
+ cards DISPARANDO tudo o que está ligado ao destino (automações do funil, regras, fluxos, webhooks, conversões)
63
+ e a etapa de origem continua no funil, só vazia. Usar `migrate_stage` para "limpar antes de excluir" dispara
64
+ automação e aviso ao cliente por card movido.
61
65
  - Funil apagado continua sendo erro (o card não é criado).
62
66
 
67
+ ### Excluir etapa (20/10/2026) — `lionchat_funnels_remove_stage`
68
+
69
+ `POST /funnels/{id}/remove_stage` com `from_stage` (CHAVE da etapa a excluir), `to_funnel_id` (obrigatório; pode ser o
70
+ próprio funil) e `to_stage` (CHAVE do destino). Os cards **mudam de etapa e não são apagados**; nada dispara (nenhuma
71
+ automação do funil, regra, fluxo, webhook, conversão nem aviso ao cliente). Desde 20/10/2026 o card passa a contar o
72
+ tempo na etapa nova **a partir da exclusão** (`stage_entered_at` = o instante da exclusão; antes mantinha a data): é o
73
+ que mantém os relatórios de meses passados mostrando cada card onde ele estava ("etapa removida"). Exige
74
+ administrador ou a permissão "gerenciar funis" (sem ela: **401**; vale também para o `migrate_stage`).
75
+
76
+ **Como a IA deve usar:**
77
+
78
+ 1. `lionchat_funnels_show` para pegar as chaves; conte os cards com `lionchat_funnels_stage_report` (id do funil + a
79
+ chave em `stage`, com `show_won`, `show_lost` e `show_snoozed` = `true` — sem isso o relatório conta só os abertos
80
+ não adiados e a etapa parece ter menos cards do que vai mover).
81
+ 2. Diga ao usuário quantos cards vão para onde e que a etapa será excluída; **peça o OK uma vez**.
82
+ 3. Chame com `confirm: true` — **toda** chamada leva `confirm: true`, inclusive a primeira. A ferramenta trabalha em
83
+ pedidos curtos (cerca de 8 segundos de cards por pedido, lotes de 125): **repita a chamada, sem perguntar de novo,
84
+ até vir `done: true`**.
85
+
86
+ **Respostas:**
87
+
88
+ | Resposta | Significa |
89
+ |---|---|
90
+ | `200 {done: true, moved, stage_removed: true, funnel}` | Terminou. `moved` é o TOTAL da exclusão inteira |
91
+ | `200 {done: true, moved: 0}` (sem `stage_removed`) | A etapa já estava excluída para o mesmo destino (fim normal, por exemplo repetição do pedido) |
92
+ | `200 {done: false, moved, remaining, reason}` | Ainda falta. `moved` é só deste pedido. `remaining` = cards que faltam; **nulo** = a contagem não coube no tempo (não é erro, repita); **100001** = "mais de 100 mil" |
93
+
94
+ `reason` quando `done: false`: `tempo` = repita agora; `travado` ou `faxina` = o banco estava ocupado, espere ~30 s e
95
+ repita; `destino_excluido` = a etapa de destino deixou de existir, pergunte ao usuário outro destino; `assumido` =
96
+ OUTRA pessoa assumiu a exclusão desta etapa (vêm `holder_name` e `to_stage_name`, que podem ser nulos): avise quem está
97
+ excluindo e para onde (sem nome, diga só "outra pessoa está excluindo esta etapa") e **pare, não repita**. Duas
98
+ respostas seguidas com `moved: 0` e `done: false` = algo está preso: **pare e avise**.
99
+
100
+ **Erros:** `422 {error, code}` com `code` = `DESTINATION_NOT_FOUND`, `SAME_STAGE`, `LAST_STAGE` (o funil precisa ficar
101
+ com pelo menos uma etapa), `ORIGIN_NOT_FOUND`, `STAGE_ALREADY_REMOVED_BY_OTHER`, `FINAL_SAVE_FAILED` (os cards já
102
+ foram movidos mas o funil não pôde ser salvo) e `FUNNEL_INVALID` — o texto de `error` já vem no idioma da conta,
103
+ mostre-o ao usuário. `409 STAGE_REMOVAL_IN_PROGRESS` = outra pessoa está excluindo esta etapa agora (`holder_name` e
104
+ `to_stage_name` podem ser nulos): avise e pare. **Qualquer Salvar do funil (com ou sem `stages`) também pode dar `409 FUNNEL_BUSY`**
105
+ (o funil está sendo alterado agora, por outra pessoa ou por uma exclusão de etapa): espere alguns instantes e repita.
106
+
63
107
  ### KanbanConfig (Configuração Global do Kanban) — CRÍTICO
64
108
 
65
109
  **Tabela separada do Funnel.** 1:1 com a conta. Guarda configurações que valem pra TODOS os funis. Tem 5 campos jsonb importantes:
@@ -517,13 +561,14 @@ PUT /api/v1/accounts/43/funnels/43
517
561
  | action | action_config | Observação |
518
562
  |---|---|---|
519
563
  | `move_to_stage` | `{stage}` | NUNCA executa com trigger `stage_moved` (anti-loop do backend) |
520
- | `assign_agent` | `{agent_id}` | Agente precisa ter acesso ao funil, senão é ignorado |
564
+ | `assign_agent` | `{agent_id}` | Agente precisa ter acesso ao funil, senão é ignorado. **Não use com gatilho `won`/`lost`**: a automação roda com o card já fechado e card fechado não aceita responsável novo — não faz nada (a tela não oferece mais desde 22/10) |
521
565
  | `create_note` | `{note_text}` | Cria nota no card com autor "Sistema" |
522
- | `notify_team` | `{message}` | HOJE só registra em log interno — não notifica ninguém de verdade |
566
+ | `notify_team` | `{message}` | HOJE só registra em log interno — não notifica ninguém de verdade. **Não use** (a tela não oferece mais desde 22/10) |
523
567
  | `duplicate_item` | `{funnel_id, stage}` | Cria cópia noutro funil/etapa; título ganha sufixo "(cópia)" |
524
568
  | `send_webhook` | `{webhook_url}` | POST com payload completo do card (fire-and-forget) |
525
569
  | `apply_checklist_template` | `{template_id}` | Template de `kanban_config.checklist_templates`; aditivo (appenda) — cada aplicação vira um grupo (carimba `group_id`/`group_name` nos itens) |
526
570
  | `update_checklist` | `{checklist_updates: [{checklist_item_id, completed, text}]}` | Não aparece na UI — só via API |
571
+ | `create_task` (20/10/2026) | `{title, description?, task_type, agenda_id?, priority?, occupies_agenda?, duration_minutes?, due: {amount, unit: 'hours'\|'days', at?: 'HH:MM', business_days?: true}, responsible: {mode: 'card_owner'\|'fixed'\|'funnel_rotation'\|'team_rotation', fallback_user_id (card_owner), user_id (fixed), team_id (team_rotation)}}` | Cria uma tarefa COMUM da Agenda presa ao card (ver "Tarefa automática do card" abaixo). Exige a Agenda unificada ligada na conta |
527
572
 
528
573
  **Regras críticas (gravar diferente disso = automação perdida ou morta):**
529
574
 
@@ -531,9 +576,41 @@ PUT /api/v1/accounts/43/funnels/43
531
576
  - Nomes de trigger/action fora das tabelas acima (ex.: `status_changed`, `duplicate_to_funnel`, `send_message`, `set_priority` — NÃO existem) são salvos mas NUNCA disparam, sem erro nenhum.
532
577
  - `id` no formato `automation_<timestamp_ms>` — a UI usa pra editar/remover a automação.
533
578
  - Trigger `card_created` + ação `duplicate_item` funciona (backend tem anti-loop), mas a UI esconde essa combinação.
579
+ - **A ordem da lista `automations` é a ordem de execução**: quando várias regras disparam no mesmo acontecimento (ex.:
580
+ duas em `won`), elas rodam de cima para baixo. Para mudar a ordem, reenvie a lista inteira na ordem desejada (no
581
+ painel, desde 22/10, a pessoa segura e arrasta cada regra). Mudar a ordem não mexe na configuração de nenhuma regra.
582
+ - `assign_agent` com `status_change` `won`/`lost` e `notify_team` são aceitos pelo servidor mas **não fazem nada**: não
583
+ grave regras novas com eles. Regra antiga que já os tenha aparece no painel com um aviso amarelo.
534
584
 
535
585
  Use para: "ao ganhar um card de Vendas → criar automaticamente em Pós-Venda na etapa Agendar Instalação" (`status_change`/`won` + `duplicate_item`).
536
586
 
587
+ #### Tarefa automática do card — ação `create_task` (20/10/2026)
588
+
589
+ - `title` é obrigatório (texto; aceita variáveis do card). `task_type`: um dos 7 de fábrica ou um tipo ativo da conta.
590
+ `agenda_id` nulo = a agenda padrão da conta. `priority`: `none|low|medium|high|urgent`.
591
+ - **Prazo (`due`)**: `unit: 'hours'` aceita `amount` de 1 a 720; `unit: 'days'` aceita 0 a 365, com `at` ("HH:MM") e
592
+ `business_days: true` (dias úteis) **só em dias**. Dia útil = segunda a sexta **sem feriado de dia inteiro** da agenda
593
+ da tarefa (feriado de meio período não conta). O fuso é o da agenda da tarefa. Prazo que já passou nasce atrasado,
594
+ nunca é empurrado.
595
+ - **Duração**: `duration_minutes` (22/10/2026): minutos que a tarefa ocupa, inteiro de 1 a 1440; ausente ou `null` = o tempo do TIPO (Tarefa/Follow-up/Prazo 15, Ligação/Personalizado 30, Reunião/Call 60, tipo criado pela conta 30). Com `occupies_agenda: true` o horário ocupado vai do prazo até o fim da duração.
596
+ - **Responsável (`responsible.mode`)**: `card_owner` (primeiro responsável do card; senão o da conversa; senão a reserva `fallback_user_id`,
597
+ obrigatória), `fixed` (exige `user_id`), `funnel_rotation` (rodízio de quem acessa o funil) e `team_rotation` (exige
598
+ `team_id`).
599
+ - **Formato conferido no Salvar**: regra `create_task` NOVA ou alterada é conferida uma a uma; regra torta recebe 422 que
600
+ diz a posição da regra e o campo a consertar, e as demais regras do funil não são afetadas.
601
+ - **Uma tarefa por acontecimento** (repetir o gatilho do mesmo acontecimento não duplica). Card importado por planilha
602
+ não cria; card importado e movido depois por uma pessoa cria.
603
+ - A tarefa nasce **presa ao card** (campo `kanban_item_id` da tarefa; `occupies_agenda` diz se ela bloqueia o horário).
604
+ Ao **excluir o card** (`lionchat_kanban_items_destroy`), só é apagada a tarefa presa a ESTE card que seja
605
+ SIMPLES: sem conversa, sem contato, sem agendamento, sem sessão de programa, sem anexo, que não veio do Google
606
+ Agenda e que não é somente leitura. Toda outra tarefa presa ao card apenas se SOLTA (continua na agenda, na
607
+ conversa e no contato), e a tarefa que só aponta para o card por `linked_kanban_item_id` também só se solta.
608
+ **A tarefa AUTOMÁTICA de um card que TEM conversa grava a conversa** (o servidor associa a conversa do card à
609
+ tarefa), portanto NÃO é "simples": ao excluir esse card ela sobrevive e fica na conversa. Só a tarefa automática
610
+ de card SEM conversa morre com o card. Conversa e contato nunca são apagados. Antes de excluir, avise o usuário
611
+ de que as tarefas simples presas ao card também somem.
612
+ - Excluir etapa com `remove_stage` **não** dispara esta ação (nem nenhuma outra); `migrate_stage` dispara.
613
+
537
614
  ### Sistema 2: AutomationRule global — eventos da conta
538
615
 
539
616
  `AutomationRule` é o motor geral da conta (mensagens, contatos, conversas, e também eventos Kanban). Bem mais genérico, com sistema completo de condições/ações.
@@ -567,9 +644,35 @@ Use para: ações cross-cutting que envolvem conversa/contato/label, ou regras c
567
644
 
568
645
  ## Bulk operations
569
646
 
570
- - `POST /api/v2/kanban/items/bulk_actions` — operações em massa (mover, atribuir, arquivar)
571
- - `POST /api/v2/kanban/items/import` — importar CSV de cards
572
- - `GET /api/v2/kanban/items/export` — exportar funil completo
647
+ - `POST /api/v1/accounts/{account_id}/bulk_actions` — operações em massa (mover, atribuir, arquivar) — `lionchat_kanban_bulk_bulk_actions`
648
+ - `POST /api/v1/accounts/{account_id}/kanban_items/import` — importar planilha de cards (só pela tela: exige o arquivo)
649
+ - `GET /api/v1/accounts/{account_id}/kanban_items/export` — exportar funil completo — `lionchat_kanban_items_export`
650
+
651
+ ### Importar cards com campos personalizados (2026-10-23)
652
+
653
+ A importação de cards (Kanban > botão azul **+** > **Importar itens**) liga colunas da planilha a **campos do card** e a
654
+ **atributos do contato**, no mesmo formato da importação de contatos. O conector não sobe o arquivo, então oriente a
655
+ pessoa a importar pela tela; o que segue serve para explicar o que ela vai ver e para ler o resultado.
656
+
657
+ - **O que pode ser importado** vem da prévia (`lionchat_kanban_items_create_3`, campo `attribute_fields`): campos do card
658
+ da conta (sem nome protegido nem secreto; dois campos com o mesmo nome = vale o primeiro) e atributos do contato (sem os
659
+ do sistema — rastreio, identificadores do WhatsApp — nem secretos). **Atributos do contato só aparecem para quem também
660
+ pode importar contatos** (administrador ou cargo "Exportar e importar contatos").
661
+ - **Como o card grava** (`item_details.custom_attributes`, nasce com o card): data `DD/MM/AAAA` ou `DD/MM/AA` vira
662
+ `AAAA-MM-DD`; número com ou sem milhar (`1.500`, `1.234,56`) vira texto (`"1500"`); hora vira `HH:MM`; campo de LISTA
663
+ aceita várias opções na mesma célula separadas por `;` e só grava opção que existe. Os demais tipos gravam o texto como
664
+ está na planilha.
665
+ - **Contato**: mesma conversão da importação de contatos. Vai só para o **contato principal do card** (numa linha com
666
+ vários contatos). Contato novo nasce com os atributos; contato que **já existe** tem o valor **substituído** — conta como
667
+ alteração (fluxo "Atributo do contato muda", webhook `contact_updated`). Célula vazia nunca apaga.
668
+ - **Resultado** (`lionchat_kanban_items_import_status`): `attributes_applied: true` confirma que os campos foram aplicados;
669
+ `skipped` lista os valores que **não** entraram (`row`, `field`, `message`) e `skipped_count` dá o total. O card nasce
670
+ do mesmo jeito — só aquele valor fica de fora (formato que não converte, opção fora da lista, texto longo demais, ou
671
+ linha sem telefone válido, que não tem contato para receber o atributo). `row` é a linha da planilha (cabeçalho = 1).
672
+ - **Armadilhas**: `422` = escolha de campo com formato errado, campo que não existe mais/é do sistema, ou coluna que a
673
+ planilha não tem (a mensagem lista quais); `403` = atributo de contato sem a permissão de importar contatos. Sem
674
+ `attributes_applied` no resultado de uma importação que ligou campos = o servidor estava sendo atualizado e os cards
675
+ nasceram sem eles (preencher nos cards, ou excluir e importar de novo — reimportar cria cards novos).
573
676
 
574
677
  ## Custom attributes em cards — TRÊS LUGARES POSSÍVEIS
575
678
 
@@ -785,6 +888,16 @@ data marcada, **abre sozinho** e volta para a coluna (disparando o fluxo "Card a
785
888
  sem card no funil, tempo inválido) — nunca passa verde sem adiar.
786
889
  - Fluxo: ação `snooze_kanban_item`, gatilhos `card_opened` ("Card aberto") e `card_snoozed` ("Card adiado") e
787
890
  condição `kanban_snoozed`. Ver o resource do FlowBuilder.
891
+ - Fluxo, **card parado (NOVO 28/10/2026)**: gatilhos de prazo `card_open_in_stage` ("Card aberto na etapa") e
892
+ `card_open_in_funnel` ("Card aberto no funil"). Config `{ "funnel_ids": ["12"], "funnel_stages": ["12:novo_lead"],
893
+ "duration_value": 1, "duration_unit": "hours" }` (`funnel_stages` só na etapa; vazio = qualquer funil/etapa;
894
+ `minutes`|`hours`|`days`, de 15 minutos a 365 dias). Relógio da etapa = tempo desde que o card ENTROU na etapa atual
895
+ (o segundo número "1d" do card; trocar de funil também recomeça); do funil = idade do card (o primeiro número "2d";
896
+ trocar de funil não recomeça). Conta card aberto ou adiado, nunca ganho/perdido. Dispara uma vez por entrada na etapa
897
+ (etapa) ou uma vez por card (funil), só para quem cruza o prazo com o fluxo ligado (card que já passou do prazo ao ligar
898
+ não dispara; mudar prazo/etapa/funil do gatilho = gatilho novo). Conferência de 5 em 5 minutos (pode chegar ~5 min
899
+ depois). Inicia só o fluxo dono do gatilho, em cada conversa do card; o card que disparou é o "card do gatilho"
900
+ (`card_source: 'trigger'`, condições "Card na etapa" e "Card adiado"). Dois fluxos iguais na mesma caixa disparam os dois.
788
901
 
789
902
  **Onde o adiado aparece e como filtrar:**
790
903
 
@@ -830,3 +943,68 @@ depois não trava outro salvamento.
830
943
  `co_participant_changed` (antes e depois, com nome e quem marcou).
831
944
  - Números: `coParticipantRanking`, `sharedSalesSummary`/`sharedSalesBySeller` (com `include_shared_sales=true`) no
832
945
  relatório agregado e a lista `lionchat_kanban_items_shared_sales` — ver `lionchat://docs/filtros-e-relatorios` §4.
946
+
947
+ ---
948
+
949
+ ## Analisar com IA — a IA sugere o que mudar nos cards (2026-10-28)
950
+
951
+ A mesma análise do botão **Analisar com IA** do Kanban (topo do quadro e menu da coluna). A IA lê os cards **abertos e
952
+ adiados** das etapas escolhidas de UM funil, com as conversas deles, e sugere: mudar de etapa (também para trás), levar
953
+ para outro funil, pôr/tirar etiqueta e marcar ganho/perdido. **Nada muda sem aplicar, e aplicar não tem como desfazer.**
954
+
955
+ ### Ferramentas
956
+
957
+ 1. `lionchat_kanban_ai_analyses_setup` — o que a janela mostra: etapas com a contagem de cards, se cada etapa e o funil
958
+ têm descrição, `selection` (quantos cards entram e `estimated_cost_usd`), funis de destino, etiquetas, motivos de
959
+ ganho/perda, `has_openai_key` e `latest_run` (análise viva do funil).
960
+ 2. `lionchat_kanban_ai_analyses_create` — cria a análise. Os cards são escolhidos AQUI: até `filters.limit` (1 a 1.000,
961
+ padrão 200), os parados há mais tempo, PULANDO os que a IA leu nos últimos 7 dias (a não ser que o cliente tenha
962
+ escrito depois); `filters.include_read: true` lê de novo os já lidos.
963
+ 3. `lionchat_kanban_ai_analyses_show` — andamento (`status`, contadores, custo).
964
+ 4. `lionchat_kanban_ai_analyses_items` — a lista de sugestões (só depois de `ready`). Com `no_change: true` traz também
965
+ `no_change_items`: os cards que a IA leu e deixou como estão, cada um com `lines` dizendo o porquê.
966
+ 5. `lionchat_kanban_ai_analyses_apply` — aplica o que o usuário escolheu. Pede `confirm: true`.
967
+ 6. `lionchat_kanban_ai_analyses_reanalyze` — analisa de novo UM card cuja linha travou.
968
+
969
+ ### Passo a passo
970
+
971
+ 1. `setup` com `funnel_id` (e `stages` para saber o total e o custo). Mostre ao usuário as etapas e quantos cards cada
972
+ uma tem. Dica: marcar VÁRIAS etapas numa análise só evita ler a mesma conversa duas vezes.
973
+ 2. Pergunte o que a IA pode fazer (`options`), quais cards (todos, `stale_days` ou `no_reply_days`) e QUANTOS
974
+ (`filters.limit`, 1 a 1.000; mostre o `estimated_cost_usd` e o `estimated_minutes` do `setup` com o mesmo número). Se o
975
+ `setup` disser `already_read` > 0, avise que esses serão pulados; para repetir nos mesmos cards, `include_read: true`.
976
+ 3. `create`. Depois chame `show` a cada 5 a 10 segundos até `status = ready` (ou `failed`, com `error_code`).
977
+ 4. `items`: mostre as sugestões agrupadas por etapa — card, ação, força ("Alta" >= 70%, "Média" 50-70%), motivo e o que
978
+ a ação dispara (`hints`: conversão, regras do funil, fluxos; aviso de WhatsApp QR).
979
+ 5. **Antes de aplicar, confirme com o usuário** quais cards e ações, quantas mudanças em quantos cards, e diga que **não
980
+ tem como desfazer**: fica como se uma pessoa tivesse feito à mão, e automações, fluxos e conversões do funil disparam.
981
+ 6. `apply` com `items: [{ item_id, actions: [ids] }]` e `confirm: true`. Os `actions` são os `id` das `suggestions`
982
+ daquele item (`stage`, `funnel`, `outcome`, `label_add:...`, `label_remove:...`) — nunca invente: ação que não foi
983
+ sugerida para o item volta em `ignored`.
984
+ 7. `show` até `status = finished`; `items` traz `done`, `apply_code` e `return_code` de cada card.
985
+ 8. **"Por que a IA não mudou nada?"** — chame `items` com `no_change: true` e explique pelos `no_change_items[].lines`:
986
+ `kind` (`stage`, `funnel`, `outcome`, `label`) + `state`: `same` = confirmou o que já está (com `confidence` em %),
987
+ `doubt` = as duas ordens discordaram (`value` x `other_value`), `weak` = pensou em `value` mas abaixo de 50%,
988
+ `other_funnel` = achou que o card é de outro funil (anulou a etapa), `not_chosen` = sugeriu um funil que não estava
989
+ entre os destinos, `add_no` / `remove_keeps` = etiqueta com a chance (`probability`). `lines: null` = análise antiga,
990
+ sem detalhes.
991
+
992
+ ### Regras que você PRECISA saber
993
+
994
+ - **Quem pode:** administrador ou cargo com a permissão `kanban_ai_analyze` ("Analisar funil com IA"), com o recurso de
995
+ plano `kanban_ai_analysis` ligado na conta e o menu do Kanban visível. Funil que a pessoa não vê = 404
996
+ `funnel_not_visible`. Sem o recurso = `feature_disabled`.
997
+ - **Custo:** usa a chave da OpenAI DA CONTA (`no_openai_key` sem ela). Costuma ficar abaixo de um centavo de dólar a cada
998
+ dezenas de cards — mostre o `estimated_cost_usd` do `setup` antes de criar.
999
+ - **Uma análise por vez por funil** (`funnel_busy`, 409) e no máximo duas rodando por conta (`account_busy`). Criar uma
1000
+ análise nova **substitui a lista anterior** do mesmo funil que tiver etapa em comum (ela vira `superseded`).
1001
+ - **A lista vale 24 horas** (`expires_at`); depois vira `expired` e é preciso analisar de novo.
1002
+ - **O que vem marcado** (`checked: true`): sugestões de força Alta de etapa, funil e perdido. Ganho, Média e etiqueta vêm
1003
+ sempre desmarcados, com o motivo em `unchecked_reason`. Na dúvida, proponha aplicar só as marcadas.
1004
+ - **Linha travada** (`locked`: `client_wrote` = o cliente escreveu depois da análise; `card_changed` = o card mudou):
1005
+ não aplique. Chame `reanalyze` com o `item_id` e depois `items` de novo.
1006
+ - **Linha que voltou** (`return_code`): `interrupted` (sistema reiniciou), `card_busy` e `apply_failed` podem ser
1007
+ aplicadas de novo; `agent_no_access` (o responsável não acessa o funil de destino) exige dar o acesso antes.
1008
+ - **"Por que não sugeriu nada?"** A IA só sugere quando responde a mesma coisa com as opções em duas ordens e com pelo
1009
+ menos 50% de certeza. Card sem conversa, ou com pouca conversa, costuma ficar como está (`counts.no_change`). Escrever
1010
+ a descrição das etapas e do funil melhora o resultado (o `setup` diz quais não têm).