@lionchat/mcp-server 0.3.1 → 0.3.2
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 +24 -0
- package/dist/docs/prompts/create_flow_brainstorm.json +9 -0
- package/dist/docs/resources/flowbuilder-design-guide.md +427 -0
- package/dist/docs/resources/flowbuilder-patterns.md +362 -0
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/resources.js +12 -0
- package/dist/resources.js.map +1 -1
- package/endpoints.json +1 -1
- package/package.json +2 -2
|
@@ -153,6 +153,12 @@ Quando precisar de detalhes profundos, leia um destes documents via `resources/r
|
|
|
153
153
|
- `lionchat://docs/data-model` — Modelo de dados detalhado, FKs, índices
|
|
154
154
|
- `lionchat://docs/reports-guide` — Como interpretar cada um dos 19 endpoints de relatório
|
|
155
155
|
- `lionchat://docs/api-conventions` — Auth, paginação, filtros, errors, rate limits
|
|
156
|
+
- `lionchat://docs/conversation-flows` — Ciclo de vida de uma conversa (criação, auto-assignment, IA, resolução)
|
|
157
|
+
- `lionchat://docs/kanban-deep-dive` — Estrutura completa do Kanban (Funnel/Stage/Item/pipeline)
|
|
158
|
+
- `lionchat://docs/best-practices` — Como economizar tokens, evitar rate limit, ordem de operações
|
|
159
|
+
- `lionchat://docs/troubleshooting` — Códigos HTTP, erros comuns, debugging
|
|
160
|
+
- `lionchat://docs/flowbuilder-design-guide` — **OBRIGATÓRIO** antes de criar/editar fluxo: schema de nodes, handles expostos por tipo, layout/positioning, erros comuns, checklist
|
|
161
|
+
- `lionchat://docs/flowbuilder-patterns` — 10 templates de fluxos prontos pra adaptar (saudação, captura, qualificação, CSAT, IA, etc)
|
|
156
162
|
|
|
157
163
|
## 9. Prompts pré-prontos (workflows automatizados)
|
|
158
164
|
|
|
@@ -162,6 +168,24 @@ O usuário pode invocar via slash command (`/nome_do_prompt`):
|
|
|
162
168
|
- `stuck_leads` — Leads parados há N dias no Kanban
|
|
163
169
|
- `weekly_recap` — Resumo da semana
|
|
164
170
|
- `customer_health` — Saúde completa de 1 cliente (conversas + Kanban + CSAT)
|
|
171
|
+
- `inactive_contacts` — Contatos sem interação pra reativação
|
|
172
|
+
- `team_load_balance` — Carga e distribuição da equipe
|
|
173
|
+
- `quality_audit` — Auditoria de qualidade de conversas resolvidas
|
|
174
|
+
- `whatsapp_template_usage` — Uso e performance de templates WhatsApp
|
|
175
|
+
- `create_flow_brainstorm` — Banco de perguntas pra descobrir o que o cliente quer ANTES de criar um fluxo
|
|
176
|
+
|
|
177
|
+
### Regras específicas para criação de FlowBuilder
|
|
178
|
+
|
|
179
|
+
Quando o cliente pedir pra criar um fluxo:
|
|
180
|
+
|
|
181
|
+
1. **Antes de gerar JSON**, avalie se você tem informação suficiente. Se faltar (canal, gatilho, conteúdo, ramificações), use o prompt `create_flow_brainstorm` como **guia de perguntas sugeridas** — escolha só as relevantes pro caso, não force checklist
|
|
182
|
+
2. Fluxo simples (1-3 nodes, sem ramificação) → 2-3 perguntas bastam
|
|
183
|
+
3. Fluxo complexo (5+ nodes, IA, API externa, várias ramificações) → vale aprofundar
|
|
184
|
+
4. **SEMPRE consulte** `lionchat://docs/flowbuilder-design-guide` antes de chamar `flows_create` (schema, handles, layout)
|
|
185
|
+
5. **SEMPRE verifique** se algum template em `lionchat://docs/flowbuilder-patterns` já resolve o caso — adaptar é mais seguro do que criar do zero
|
|
186
|
+
6. **NUNCA crie** nodes sem `position: {x, y}` — eles ficam empilhados no canvas
|
|
187
|
+
7. **NUNCA invente** `sourceHandle` — use só os listados no design guide por tipo de node (ex: condition usa `cond_0`/`cond_1`/`default`, não IDs livres)
|
|
188
|
+
8. Antes de chamar `flows_create`, apresente um resumo em **linguagem natural** do que vai criar e confirme com o cliente
|
|
165
189
|
|
|
166
190
|
## 10. Idioma das respostas
|
|
167
191
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create_flow_brainstorm",
|
|
3
|
+
"title": "Perguntas sugeridas para criar um FlowBuilder",
|
|
4
|
+
"description": "Banco de perguntas para descobrir o que o cliente quer ANTES de gerar o flow_data. Use APENAS as perguntas relevantes pro caso — nao force checklist. Fluxo simples (1-3 nodes) precisa de 2-3 perguntas no maximo; fluxo complexo (5+ nodes, ramificacoes, IA, API) vale aprofundar. Sempre consulte o resource lionchat://docs/flowbuilder-design-guide e lionchat://docs/flowbuilder-patterns antes de gerar o JSON.",
|
|
5
|
+
"arguments": [
|
|
6
|
+
{ "name": "goal_hint", "description": "O que o cliente ja disse que quer (ex: 'fluxo de captura de lead')", "required": false }
|
|
7
|
+
],
|
|
8
|
+
"template": "Cliente quer criar um fluxo no FlowBuilder do LionChat.\n\nObjetivo declarado: {{goal_hint|Nao informado}}\n\nINSTRUCAO: avalie o que o cliente JA disse e o que ainda falta saber. Pergunte SO o que falta. Nao force checklist. Em fluxo simples, 2-3 perguntas bastam. Em fluxo complexo, aprofunde.\n\nABAIXO esta o BANCO de perguntas sugeridas por categoria. ESCOLHA SO AS RELEVANTES.\n\n## Categoria A — Proposito e gatilho (quase sempre necessario)\n- Qual o objetivo do fluxo? (saudacao, qualificacao, captura, suporte, pos-venda, CSAT, agendamento, re-engajamento, outro)\n- Quando dispara? (mensagem recebida com palavra-chave, conversa criada, conversa resolvida, label aplicada, cron, webhook externo)\n- Se palavra-chave: quais palavras? Match exact ou contains?\n\n## Categoria B — Canal e escopo\n- Em qual canal vai rodar? (WAHA, WhatsApp Cloud, Webwidget, Telegram, Email, Twitter, Facebook, Instagram, Line, SMS, API, Voz, WhatsApp Business)\n- Em qual(is) inbox(es) especifica(s)? (peca o ID via inboxes_list se nao soube)\n- Tem filtro de quem entra? (so leads novos, so clientes existentes, so quem tem label X)\n\n## Categoria C — Conteudo da conversa\n- Vai mandar quais mensagens? Texto livre, templates WhatsApp aprovados, midia (imagem/audio/video), lista de botoes interativos?\n- Vai fazer perguntas pro cliente? Quantas? Quais?\n- Para cada pergunta: aceita qualquer resposta livre, opcoes fixas (ex: 1/2/3), ou regex (ex: CPF, email, telefone)?\n- Quanto tempo espera por cada resposta? (default sensato: 30-60 min)\n- O que mandar se nao responder no tempo? (mensagem de timeout, encerrar, escalar pra humano)\n\n## Categoria D — Captura, ramificacao e logica\n- Onde salva as respostas? Em variavel temporaria do flow, atributo da conversa, atributo do contato, custom_attributes\n- Tem ramificacao por condicao? Quais criterios? (ex: 'se valor > 1000 vai pra time premium')\n- Vai chamar API externa? (URL, metodo, headers, body, autenticacao)\n- Vai usar IA (Captain Assistant)? Em que momento? Pra que?\n * generate = gerar resposta natural\n * intent = classificar intencao da mensagem\n * sentiment = analisar sentimento\n * extract = extrair info estruturada (CPF, valor, etc)\n- Tem teste A/B? (randomizer)\n\n## Categoria E — Acoes finais\n- No fim do fluxo: criar card no Kanban? (em qual funil/etapa?) Atribuir agente/time? (ID) Adicionar/remover label? Mudar status/prioridade? Disparar webhook externo?\n- Tem criterio pra encerrar antes? (exit_conditions: ex: 'conversa marcada como resolvida' ou 'label X aplicada')\n\n## Antes de chamar flows_create\n1. Se faltou info CRITICA (ex: canal, gatilho, conteudo basico): pergunte agora\n2. Se a info que falta e mero detalhe: assuma defaults sensatos\n - maxRetries: 3\n - waitTime: 60min para resposta, 30min para timeouts\n - sem ramificacao se cliente nao mencionou\n3. Apresente um RESUMO em linguagem natural do fluxo. Exemplo: 'Beleza, vou criar um fluxo assim: quando alguem mandar oi no WhatsApp, manda saudacao, pergunta se quer vendas/suporte, se vendas atribui ao time 1, se suporte ao time 2. Confirma?'\n4. Espere o cliente confirmar OU pedir ajustes\n5. So depois da confirmacao, chame flows_create\n6. ANTES de gerar o JSON: consulte lionchat://docs/flowbuilder-design-guide pra schema/handles/layout e lionchat://docs/flowbuilder-patterns pra ver se algum template ja resolve\n7. Apos gerar JSON, valide pelo checklist da secao 6 do design guide\n8. NUNCA crie node sem position. NUNCA invente sourceHandle.\n\nDEFAULTS SENSATOS quando cliente nao especificar:\n- channel_type: pergunte sempre, nao chute\n- inbox_ids: pergunte sempre\n- waitTime: 60 minutes\n- maxRetries: 3\n- waitUnit: minutes\n- saveTo: 'attribute' (conversa) na duvida\n- match_mode: 'contains' pra keywords"
|
|
9
|
+
}
|
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
# FlowBuilder — Guia de Design
|
|
2
|
+
|
|
3
|
+
Como criar fluxos do LionChat (FlowBuilder) que abrem certinhos no canvas, sem nodes empilhados, sem edges quebradas, sem campos inventados. Consulte sempre que for chamar `flows_create` ou `flows_update`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Decisão de node — qual usar pra cada caso
|
|
8
|
+
|
|
9
|
+
| Cliente quer | Use o node | NÃO use |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| Mandar mensagem (texto, template WhatsApp, áudio, imagem, lista de botões) | `send_message` | `action` pra mandar mensagem |
|
|
12
|
+
| Esperar resposta com opções fixas (1, 2, 3) | `wait_response` com `validation: 'options'` | `condition` depois — o próprio wait_response roteia pelas opções |
|
|
13
|
+
| Esperar resposta livre | `wait_response` com `validation: 'any'` | - |
|
|
14
|
+
| Validar CPF/email/telefone | `wait_response` com `validation: 'regex'` | `condition` com regex |
|
|
15
|
+
| Ramificar por valor de variável/atributo | `condition` | `wait_response` |
|
|
16
|
+
| Atribuir agente, time, label, status, prioridade, kanban, captain | `action` com `key` específica | - |
|
|
17
|
+
| Chamar API externa | `api` | `action` (não tem chamada HTTP genérica) |
|
|
18
|
+
| Esperar X tempo | `wait` | - |
|
|
19
|
+
| Esperar "segunda-feira às 9h" | `wait` com `waitUnit: 'weekday'` | `condition` por horário |
|
|
20
|
+
| Salvar valor calculado em variável | `set_variable` | `action` |
|
|
21
|
+
| Gerar resposta com IA | `ai` mode `generate` | - |
|
|
22
|
+
| Extrair info da mensagem (ex: pegar valor numérico) | `ai` mode `extract` | regex no wait_response |
|
|
23
|
+
| Classificar intenção da mensagem | `ai` mode `intent` | - |
|
|
24
|
+
| Analisar sentimento | `ai` mode `sentiment` | - |
|
|
25
|
+
| Encerrar fluxo no meio | `action` com `key: 'deactivate_flow'` OU `exit_conditions` no nível do flow | - |
|
|
26
|
+
| Distribuir aleatório entre branches | `randomizer` | - |
|
|
27
|
+
| Atualizar info de grupo WhatsApp (WAHA) | `update_group` | - |
|
|
28
|
+
| Iniciar outro fluxo | `action` com `key: 'start_flow'` OU node `activate_flow` | - |
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 2. Schema válido por tipo de node
|
|
33
|
+
|
|
34
|
+
Todo node tem essa estrutura base:
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"id": "uuid-ou-string-unica",
|
|
39
|
+
"type": "<tipo do node>",
|
|
40
|
+
"position": { "x": 0, "y": 0 },
|
|
41
|
+
"data": { "...": "campos específicos do tipo" }
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 2.1 `start`
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"id": "node-start",
|
|
50
|
+
"type": "start",
|
|
51
|
+
"position": { "x": 50, "y": 300 },
|
|
52
|
+
"data": {
|
|
53
|
+
"label": "Início",
|
|
54
|
+
"triggers": [
|
|
55
|
+
{ "type": "message_received", "keywords": ["oi", "ola"], "match_mode": "contains" }
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Triggers válidos:** `message_received`, `conversation_created`, `conversation_resolved`, `label_added`, `label_removed`, `cron`, `webhook`.
|
|
62
|
+
|
|
63
|
+
**Handles que SAEM:** `success`.
|
|
64
|
+
|
|
65
|
+
### 2.2 `send_message`
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"id": "node-send-1",
|
|
70
|
+
"type": "send_message",
|
|
71
|
+
"position": { "x": 370, "y": 300 },
|
|
72
|
+
"data": {
|
|
73
|
+
"label": "Boas-vindas",
|
|
74
|
+
"messageItems": [
|
|
75
|
+
{ "id": "m1", "type": "text", "content": "Oi {{contact.name}}! Como posso ajudar?" },
|
|
76
|
+
{ "id": "m2", "type": "delay", "seconds": 2 },
|
|
77
|
+
{ "id": "m3", "type": "whatsapp_template", "templateId": 123, "params": ["valor1"] }
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Tipos de item válidos:** `text`, `whatsapp_template` (ou `template`), `canned_response`, `user_input` (lista de botões interativos), `delay`, `attachment`, `audio`.
|
|
84
|
+
|
|
85
|
+
**ATENÇÃO:** usa `messageItems` (NÃO `items`).
|
|
86
|
+
|
|
87
|
+
**Handles que SAEM:** `success`, `no_response` (quando tem `user_input` com timeout), `error`.
|
|
88
|
+
|
|
89
|
+
### 2.3 `wait_response`
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"id": "node-wait-1",
|
|
94
|
+
"type": "wait_response",
|
|
95
|
+
"position": { "x": 690, "y": 300 },
|
|
96
|
+
"data": {
|
|
97
|
+
"label": "Pergunta menu",
|
|
98
|
+
"waitTime": 60,
|
|
99
|
+
"waitUnit": "minutes",
|
|
100
|
+
"validation": "options",
|
|
101
|
+
"acceptedOptions": ["1", "2", "3"],
|
|
102
|
+
"invalidMessage": "Por favor responda com 1, 2 ou 3",
|
|
103
|
+
"maxRetries": 3,
|
|
104
|
+
"saveTo": "attribute",
|
|
105
|
+
"saveAttrKey": "escolha_menu"
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**`validation` válidos:** `any`, `options`, `regex`.
|
|
111
|
+
|
|
112
|
+
**`saveTo` válidos:** `variable` (variável temporária do flow), `attribute` (custom_attributes da CONVERSA), `contact_attribute` (custom_attributes do CONTATO), `""` (não salva).
|
|
113
|
+
|
|
114
|
+
**Handles que SAEM dependem da validation:**
|
|
115
|
+
- `validation: 'any'` → `success`, `timeout`
|
|
116
|
+
- `validation: 'options'` → `option_<valor>` para cada valor em `acceptedOptions` (ex: `option_1`, `option_2`, `option_sim`) + `timeout`
|
|
117
|
+
- `validation: 'regex'` → `success`, `timeout`
|
|
118
|
+
|
|
119
|
+
**REGRA:** depois de wait_response com options, NUNCA coloque node `condition` pra ramificar — ligue os edges direto nos handles `option_X`.
|
|
120
|
+
|
|
121
|
+
### 2.4 `condition`
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"id": "node-cond-1",
|
|
126
|
+
"type": "condition",
|
|
127
|
+
"position": { "x": 1010, "y": 300 },
|
|
128
|
+
"data": {
|
|
129
|
+
"label": "Tipo de cliente",
|
|
130
|
+
"conditions": [
|
|
131
|
+
{ "id": "c1", "label": "VIP", "field": "contact.custom_attributes.plano", "operator": "equal", "value": "premium" },
|
|
132
|
+
{ "id": "c2", "label": "Padrão", "field": "contact.custom_attributes.plano", "operator": "equal", "value": "standard" }
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Operadores válidos:** `equal` (ou `field_equals`), `not_equal`, `contains`, `not_contains`, `starts_with`, `ends_with`, `greater_than`, `less_than`, `is_present`, `is_blank`, `regex`.
|
|
139
|
+
|
|
140
|
+
**Handles que SAEM:** `cond_0`, `cond_1`, `cond_2`, ... (UM POR CONDIÇÃO, pela ordem do array — NÃO use o `id` da condição) + `default` (quando nenhuma bate).
|
|
141
|
+
|
|
142
|
+
**ATENÇÃO:** o handle é `cond_INDEX` baseado na posição no array, NÃO o `id` da condição. Se você definir `conditions[0].id = "vip"`, mesmo assim o handle é `cond_0`.
|
|
143
|
+
|
|
144
|
+
### 2.5 `action`
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"id": "node-action-1",
|
|
149
|
+
"type": "action",
|
|
150
|
+
"position": { "x": 1330, "y": 300 },
|
|
151
|
+
"data": {
|
|
152
|
+
"label": "Finalizar atendimento",
|
|
153
|
+
"items": [
|
|
154
|
+
{ "key": "assign_team", "config": { "team_id": 5 } },
|
|
155
|
+
{ "key": "add_label", "config": { "labels": ["lead-qualificado"] } },
|
|
156
|
+
{ "key": "create_kanban_item", "config": { "funnel_id": 3, "funnel_stage": "novo_lead" } }
|
|
157
|
+
]
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**ATENÇÃO:** items usa `config` (NÃO `params`).
|
|
163
|
+
|
|
164
|
+
**Keys de action válidas:**
|
|
165
|
+
|
|
166
|
+
| Key | config esperado | Efeito |
|
|
167
|
+
|---|---|---|
|
|
168
|
+
| `assign_agent` | `{ agent_id }` | Atribui agente humano à conversa |
|
|
169
|
+
| `assign_team` | `{ team_id }` | Atribui time |
|
|
170
|
+
| `change_status` | `{ status: 'open' \| 'resolved' \| 'pending' \| 'snoozed' }` | Muda status da conversa |
|
|
171
|
+
| `change_priority` | `{ priority: 'urgent' \| 'high' \| 'medium' \| 'low' }` | Muda prioridade |
|
|
172
|
+
| `add_label` | `{ labels: ['slug1', 'slug2'] }` | Adiciona labels |
|
|
173
|
+
| `remove_label` | `{ labels: ['slug'] }` | Remove labels |
|
|
174
|
+
| `mute_conversation` | `{}` | Silencia notificações |
|
|
175
|
+
| `add_private_note` | `{ content: 'texto' }` | Adiciona nota interna |
|
|
176
|
+
| `create_kanban_item` | `{ funnel_id, funnel_stage, item_details? }` | Cria card no Kanban |
|
|
177
|
+
| `move_kanban_item_to_stage` | `{ funnel_stage }` | Move card (precisa ter card vinculado) |
|
|
178
|
+
| `move_kanban_stage` | `{ funnel_id, funnel_stage }` | Idem |
|
|
179
|
+
| `set_kanban_item_status` | `{ status: 'won' \| 'lost' \| 'active' }` | Marca status do card |
|
|
180
|
+
| `set_won` | `{}` | Atalho pra ganho |
|
|
181
|
+
| `set_lost` | `{ reason? }` | Atalho pra perdido |
|
|
182
|
+
| `assign_agent_card` | `{ agent_id }` | Atribui agente ao card |
|
|
183
|
+
| `add_card_note` | `{ content }` | Nota no card |
|
|
184
|
+
| `send_webhook` | `{ url, headers?, body? }` | Dispara webhook externo |
|
|
185
|
+
| `start_flow` | `{ flow_id }` | Inicia outro fluxo |
|
|
186
|
+
| `deactivate_flow` ou `disable_flow` | `{}` | Encerra fluxo atual |
|
|
187
|
+
| `update_attribute` | `{ entity: 'contact'\|'conversation'\|'card', key, value }` | Seta custom_attribute |
|
|
188
|
+
| `assign_captain` (ou `assign_captain_assistant`) | `{ assistant_id }` | Atribui IA Captain |
|
|
189
|
+
| `deactivate_captain` | `{}` | Tira a IA da conversa |
|
|
190
|
+
|
|
191
|
+
**Handles que SAEM:** `success`. Não tem handle `error` — falhas viram warning silencioso e o flow continua.
|
|
192
|
+
|
|
193
|
+
### 2.6 `api`
|
|
194
|
+
|
|
195
|
+
```json
|
|
196
|
+
{
|
|
197
|
+
"id": "node-api-1",
|
|
198
|
+
"type": "api",
|
|
199
|
+
"position": { "x": 1330, "y": 480 },
|
|
200
|
+
"data": {
|
|
201
|
+
"label": "Consulta CRM externo",
|
|
202
|
+
"method": "POST",
|
|
203
|
+
"url": "https://api.example.com/leads",
|
|
204
|
+
"headers": [
|
|
205
|
+
{ "key": "Authorization", "value": "Bearer {{env.CRM_TOKEN}}" },
|
|
206
|
+
{ "key": "Content-Type", "value": "application/json" }
|
|
207
|
+
],
|
|
208
|
+
"body": "{\"name\":\"{{contact.name}}\",\"email\":\"{{contact.email}}\"}",
|
|
209
|
+
"apiResponseVar": "crm_response"
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Handles que SAEM:** `success`, `error`.
|
|
215
|
+
|
|
216
|
+
### 2.7 `ai`
|
|
217
|
+
|
|
218
|
+
```json
|
|
219
|
+
{
|
|
220
|
+
"id": "node-ai-1",
|
|
221
|
+
"type": "ai",
|
|
222
|
+
"position": { "x": 1010, "y": 300 },
|
|
223
|
+
"data": {
|
|
224
|
+
"label": "Classifica intenção",
|
|
225
|
+
"aiMode": "intent",
|
|
226
|
+
"aiPrompt": "Classifique a intenção da última mensagem como: compra, suporte, reclamacao ou outro",
|
|
227
|
+
"aiIntentOptions": ["compra", "suporte", "reclamacao", "outro"],
|
|
228
|
+
"aiResponseVar": "intent_result"
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**`aiMode` válidos:** `generate`, `intent`, `sentiment`, `extract`.
|
|
234
|
+
|
|
235
|
+
**Handles que SAEM dependem do mode:**
|
|
236
|
+
- `generate` → `success`, `error`
|
|
237
|
+
- `intent` → uma saída por opção em `aiIntentOptions` (ex: `intent_compra`, `intent_suporte`) + `error`
|
|
238
|
+
- `sentiment` → `positive`, `negative`, `neutral` + `error`
|
|
239
|
+
- `extract` → `success`, `error` (resultado salvo em `aiResponseVar`)
|
|
240
|
+
|
|
241
|
+
### 2.8 `wait`
|
|
242
|
+
|
|
243
|
+
```json
|
|
244
|
+
{
|
|
245
|
+
"id": "node-wait-time-1",
|
|
246
|
+
"type": "wait",
|
|
247
|
+
"position": { "x": 690, "y": 300 },
|
|
248
|
+
"data": {
|
|
249
|
+
"label": "Espera 10 min",
|
|
250
|
+
"waitTime": 10,
|
|
251
|
+
"waitUnit": "minutes"
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**`waitUnit` válidos:** `seconds`, `minutes`, `hours`, `days`, `weekday` (espera próximo dia da semana).
|
|
257
|
+
|
|
258
|
+
Pra `weekday`, use também `targetWeekday` (0=domingo, 1=segunda... 6=sábado) e `targetHour` (0-23).
|
|
259
|
+
|
|
260
|
+
**Handles que SAEM:** `success`.
|
|
261
|
+
|
|
262
|
+
### 2.9 `set_variable`
|
|
263
|
+
|
|
264
|
+
```json
|
|
265
|
+
{
|
|
266
|
+
"id": "node-setvar-1",
|
|
267
|
+
"type": "set_variable",
|
|
268
|
+
"position": { "x": 370, "y": 300 },
|
|
269
|
+
"data": {
|
|
270
|
+
"label": "Define contexto",
|
|
271
|
+
"variables": [
|
|
272
|
+
{ "name": "origem_lead", "value": "Facebook Ads" },
|
|
273
|
+
{ "name": "score", "value": "{{contact.custom_attributes.lead_score}}" }
|
|
274
|
+
]
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**Handles que SAEM:** `success`.
|
|
280
|
+
|
|
281
|
+
### 2.10 `randomizer`
|
|
282
|
+
|
|
283
|
+
```json
|
|
284
|
+
{
|
|
285
|
+
"id": "node-rand-1",
|
|
286
|
+
"type": "randomizer",
|
|
287
|
+
"position": { "x": 690, "y": 300 },
|
|
288
|
+
"data": {
|
|
289
|
+
"label": "A/B test mensagem",
|
|
290
|
+
"mode": "branches",
|
|
291
|
+
"branches": [
|
|
292
|
+
{ "id": "A", "label": "Variante A", "weight": 50 },
|
|
293
|
+
{ "id": "B", "label": "Variante B", "weight": 50 }
|
|
294
|
+
]
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**Handles que SAEM:** o `id` de cada branch (`A`, `B`, ...). Em `mode: 'distribute_agents'` é `success`.
|
|
300
|
+
|
|
301
|
+
### 2.11 `update_group` (WAHA apenas)
|
|
302
|
+
|
|
303
|
+
Atualiza nome/descrição/foto de grupo WhatsApp. Use só quando flow roda em inbox WAHA e a conversa for de grupo.
|
|
304
|
+
|
|
305
|
+
**Handles que SAEM:** `success`, `error`.
|
|
306
|
+
|
|
307
|
+
### 2.12 `activate_flow`
|
|
308
|
+
|
|
309
|
+
```json
|
|
310
|
+
{
|
|
311
|
+
"id": "node-act-1",
|
|
312
|
+
"type": "activate_flow",
|
|
313
|
+
"position": { "x": 1010, "y": 300 },
|
|
314
|
+
"data": { "label": "Inicia flow B", "flow_id": 42 }
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
**Handles que SAEM:** `success`, `error`.
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## 3. Edges
|
|
323
|
+
|
|
324
|
+
```json
|
|
325
|
+
{
|
|
326
|
+
"id": "edge-1",
|
|
327
|
+
"source": "node-start",
|
|
328
|
+
"target": "node-send-1",
|
|
329
|
+
"sourceHandle": "success",
|
|
330
|
+
"type": "deletable",
|
|
331
|
+
"animated": true
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
**REGRAS:**
|
|
336
|
+
- `sourceHandle` é OBRIGATÓRIO em todo edge
|
|
337
|
+
- Tem que casar com um handle que o node `source` EFETIVAMENTE EXPÕE (ver tabelas acima)
|
|
338
|
+
- `id`: usar formato `edge-N` ou `e<source>-<target>`
|
|
339
|
+
- `type: 'deletable'` e `animated: true` são os defaults visuais
|
|
340
|
+
|
|
341
|
+
**Handles INVENTADOS quebram o flow.** Exemplos do que NÃO usar:
|
|
342
|
+
- `c1`, `c2`, `c3` (use `cond_0`, `cond_1`)
|
|
343
|
+
- `branch1`, `branchA` (no condition; use `cond_X`)
|
|
344
|
+
- `out`, `output`, `next` (use o nome real do handle)
|
|
345
|
+
- `option1` sem underscore (use `option_1`)
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## 4. Layout e positioning
|
|
350
|
+
|
|
351
|
+
Sem `position`, todos os nodes empilham no (0,0). Sempre informe.
|
|
352
|
+
|
|
353
|
+
### Regras de espaçamento
|
|
354
|
+
|
|
355
|
+
| Direção | Valor |
|
|
356
|
+
|---|---|
|
|
357
|
+
| Espaço horizontal entre nodes sequenciais | **+320** em X |
|
|
358
|
+
| Espaço vertical entre branches paralelos | **+150** em Y (2 ramos), **+180** (3 ramos), **+150** cada (4+) |
|
|
359
|
+
| Y do node start | **300** (ponto médio) |
|
|
360
|
+
|
|
361
|
+
### Exemplo de layout
|
|
362
|
+
|
|
363
|
+
Fluxo linear de 4 nodes:
|
|
364
|
+
```
|
|
365
|
+
(50, 300) → (370, 300) → (690, 300) → (1010, 300)
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
Fluxo com 1 wait_response 3 opções:
|
|
369
|
+
```
|
|
370
|
+
(1330, 120) -> option_1
|
|
371
|
+
↑
|
|
372
|
+
(50,300) → (370,300) → (690,300) → wait → (1330, 300) -> option_2
|
|
373
|
+
↓
|
|
374
|
+
(1330, 480) -> option_3
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Cada branch continua em seu próprio Y, X avança normal:
|
|
378
|
+
```
|
|
379
|
+
option_1 path: (1330, 120) → (1650, 120) → (1970, 120)
|
|
380
|
+
option_2 path: (1330, 300) → (1650, 300) → (1970, 300)
|
|
381
|
+
option_3 path: (1330, 480) → (1650, 480) → (1970, 480)
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### Regra importante
|
|
385
|
+
|
|
386
|
+
Nodes nunca devem ficar com a mesma coordenada `(x, y)`. Se dois nodes têm posição idêntica, eles SOBREPÕEM visualmente no canvas.
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## 5. Erros comuns (lista negra)
|
|
391
|
+
|
|
392
|
+
| Erro | Por que quebra | Forma certa |
|
|
393
|
+
|---|---|---|
|
|
394
|
+
| `items` no send_message | Schema usa `messageItems` | `messageItems: [...]` |
|
|
395
|
+
| `items[].params` no action | Schema usa `config` | `items: [{ key, config: {...} }]` |
|
|
396
|
+
| Falta `position` em algum node | Nodes empilham no canvas | Sempre `position: {x, y}` |
|
|
397
|
+
| `sourceHandle: "c1"` ou `"vip"` no condition | Não existem | `"cond_0"`, `"cond_1"`, etc |
|
|
398
|
+
| Node `condition` depois de `wait_response` com options | Redundante e atrapalha | Ligue `option_X` direto no próximo node |
|
|
399
|
+
| Edge sem `sourceHandle` | Frontend não consegue rotear | Sempre informe |
|
|
400
|
+
| Edge com `target` apontando pra ID que não existe | Quebra o grafo | Confira que `target` está em `nodes[]` |
|
|
401
|
+
| `channel_type: "WhatsApp"` | Precisa do nome de classe Rails | `"Channel::Whatsapp"`, `"Channel::Waha"`, `"Channel::WebWidget"` |
|
|
402
|
+
| `validation: "option"` (singular) | Não existe | `"options"` (plural) |
|
|
403
|
+
| `waitTime: "60"` (string) | Espera Integer | `waitTime: 60` |
|
|
404
|
+
| `inbox_ids` aninhado em `{flow:{...}}` | No MCP, achata-se sozinho | Passa `inbox_ids: [1, 2]` no nível raiz |
|
|
405
|
+
| Mais de 1 node `start` | Flow precisa ter exatamente 1 ponto de entrada | Só 1 |
|
|
406
|
+
| Node sem edge entrando (exceto start) | Node nunca executa | Confira que todo node não-start tem ao menos 1 edge target apontando pra ele |
|
|
407
|
+
| `flow_data` sem `nodes` ou sem `edges` | Estrutura inválida | Inclua sempre, mesmo que `edges: []` |
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## 6. Checklist pre-submit
|
|
412
|
+
|
|
413
|
+
Antes de chamar `flows_create` ou `flows_update`, valide mentalmente:
|
|
414
|
+
|
|
415
|
+
- [ ] Existe exatamente 1 node `type: 'start'`
|
|
416
|
+
- [ ] Todo node tem `id` único
|
|
417
|
+
- [ ] Todo node tem `type` válido (lista da seção 1)
|
|
418
|
+
- [ ] Todo node tem `position: { x: <int>, y: <int> }`
|
|
419
|
+
- [ ] Nenhum par de nodes tem a mesma posição `(x, y)`
|
|
420
|
+
- [ ] Todo node tem `data` com campos do schema do tipo
|
|
421
|
+
- [ ] Todo node não-start tem pelo menos 1 edge chegando (`edge.target = node.id`)
|
|
422
|
+
- [ ] Todo edge tem `source`, `target` e `sourceHandle`
|
|
423
|
+
- [ ] Todo `sourceHandle` é um handle real exposto pelo node source (seção 2)
|
|
424
|
+
- [ ] `channel_type` é classe Rails (`Channel::Waha` etc)
|
|
425
|
+
- [ ] `inbox_ids` (se enviado) tem inboxes do mesmo `channel_type`
|
|
426
|
+
- [ ] Não tem `condition` redundante depois de `wait_response` com options
|
|
427
|
+
- [ ] Layout: nodes em ordem visual da esquerda pra direita, sem sobreposição
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
# FlowBuilder — Templates Prontos
|
|
2
|
+
|
|
3
|
+
10 padrões testados para você adaptar em vez de criar do zero. Cada um já vem com layout válido, handles certos e campos no formato esperado. **Copie o `flow_data`, ajuste só o que o cliente pediu, e chame `flows_create`.**
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Boas-vindas com triagem
|
|
8
|
+
|
|
9
|
+
**Caso:** lead nova chega no WhatsApp, oferece menu (vendas/suporte/financeiro), atribui ao time certo.
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"nodes": [
|
|
14
|
+
{ "id": "n1", "type": "start", "position": { "x": 50, "y": 300 }, "data": { "label": "Início", "triggers": [{ "type": "conversation_created" }] } },
|
|
15
|
+
{ "id": "n2", "type": "send_message", "position": { "x": 370, "y": 300 }, "data": { "label": "Saudação", "messageItems": [
|
|
16
|
+
{ "id": "m1", "type": "text", "content": "Oi {{contact.name|default:'tudo bem?'}} 👋 Como posso ajudar hoje?\n\n1️⃣ Vendas\n2️⃣ Suporte\n3️⃣ Financeiro" }
|
|
17
|
+
] } },
|
|
18
|
+
{ "id": "n3", "type": "wait_response", "position": { "x": 690, "y": 300 }, "data": {
|
|
19
|
+
"label": "Aguarda escolha", "waitTime": 30, "waitUnit": "minutes", "validation": "options",
|
|
20
|
+
"acceptedOptions": ["1","2","3"], "invalidMessage": "Por favor responda 1, 2 ou 3", "maxRetries": 2, "saveTo": ""
|
|
21
|
+
} },
|
|
22
|
+
{ "id": "n4", "type": "action", "position": { "x": 1010, "y": 120 }, "data": { "label": "→ Vendas", "items": [
|
|
23
|
+
{ "key": "assign_team", "config": { "team_id": 1 } },
|
|
24
|
+
{ "key": "add_label", "config": { "labels": ["vendas"] } }
|
|
25
|
+
] } },
|
|
26
|
+
{ "id": "n5", "type": "action", "position": { "x": 1010, "y": 300 }, "data": { "label": "→ Suporte", "items": [
|
|
27
|
+
{ "key": "assign_team", "config": { "team_id": 2 } },
|
|
28
|
+
{ "key": "add_label", "config": { "labels": ["suporte"] } }
|
|
29
|
+
] } },
|
|
30
|
+
{ "id": "n6", "type": "action", "position": { "x": 1010, "y": 480 }, "data": { "label": "→ Financeiro", "items": [
|
|
31
|
+
{ "key": "assign_team", "config": { "team_id": 3 } },
|
|
32
|
+
{ "key": "add_label", "config": { "labels": ["financeiro"] } }
|
|
33
|
+
] } },
|
|
34
|
+
{ "id": "n7", "type": "send_message", "position": { "x": 1330, "y": 660 }, "data": { "label": "Timeout msg", "messageItems": [
|
|
35
|
+
{ "id": "m2", "type": "text", "content": "Não recebi sua resposta. Vou encaminhar pra equipe geral." }
|
|
36
|
+
] } }
|
|
37
|
+
],
|
|
38
|
+
"edges": [
|
|
39
|
+
{ "id": "e1", "source": "n1", "target": "n2", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
40
|
+
{ "id": "e2", "source": "n2", "target": "n3", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
41
|
+
{ "id": "e3", "source": "n3", "target": "n4", "sourceHandle": "option_1", "type": "deletable", "animated": true },
|
|
42
|
+
{ "id": "e4", "source": "n3", "target": "n5", "sourceHandle": "option_2", "type": "deletable", "animated": true },
|
|
43
|
+
{ "id": "e5", "source": "n3", "target": "n6", "sourceHandle": "option_3", "type": "deletable", "animated": true },
|
|
44
|
+
{ "id": "e6", "source": "n3", "target": "n7", "sourceHandle": "timeout", "type": "deletable", "animated": true }
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 2. Captura de lead simples
|
|
52
|
+
|
|
53
|
+
**Caso:** pega nome + email + interesse, cria card no funil "Novos Leads".
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"nodes": [
|
|
58
|
+
{ "id": "n1", "type": "start", "position": { "x": 50, "y": 300 }, "data": { "label": "Início", "triggers": [{ "type": "conversation_created" }] } },
|
|
59
|
+
{ "id": "n2", "type": "send_message", "position": { "x": 370, "y": 300 }, "data": { "label": "Pede nome", "messageItems": [
|
|
60
|
+
{ "id": "m1", "type": "text", "content": "Olá! Antes de continuar, qual seu nome completo?" }
|
|
61
|
+
] } },
|
|
62
|
+
{ "id": "n3", "type": "wait_response", "position": { "x": 690, "y": 300 }, "data": {
|
|
63
|
+
"label": "Aguarda nome", "waitTime": 15, "waitUnit": "minutes", "validation": "any",
|
|
64
|
+
"saveTo": "contact_attribute", "saveAttrKey": "nome_completo"
|
|
65
|
+
} },
|
|
66
|
+
{ "id": "n4", "type": "send_message", "position": { "x": 1010, "y": 300 }, "data": { "label": "Pede email", "messageItems": [
|
|
67
|
+
{ "id": "m2", "type": "text", "content": "Perfeito, {{contact.custom_attributes.nome_completo}}. Qual seu melhor email?" }
|
|
68
|
+
] } },
|
|
69
|
+
{ "id": "n5", "type": "wait_response", "position": { "x": 1330, "y": 300 }, "data": {
|
|
70
|
+
"label": "Aguarda email", "waitTime": 15, "waitUnit": "minutes", "validation": "regex",
|
|
71
|
+
"regexPattern": "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$", "invalidMessage": "Esse não parece um email válido. Tenta de novo?", "maxRetries": 2,
|
|
72
|
+
"saveTo": "contact_attribute", "saveAttrKey": "email"
|
|
73
|
+
} },
|
|
74
|
+
{ "id": "n6", "type": "action", "position": { "x": 1650, "y": 300 }, "data": { "label": "Cria card", "items": [
|
|
75
|
+
{ "key": "create_kanban_item", "config": { "funnel_id": 1, "funnel_stage": "novo_lead" } },
|
|
76
|
+
{ "key": "add_label", "config": { "labels": ["lead-capturado"] } }
|
|
77
|
+
] } },
|
|
78
|
+
{ "id": "n7", "type": "send_message", "position": { "x": 1970, "y": 300 }, "data": { "label": "Confirma", "messageItems": [
|
|
79
|
+
{ "id": "m3", "type": "text", "content": "Tudo certo! Em breve um consultor vai te chamar." }
|
|
80
|
+
] } }
|
|
81
|
+
],
|
|
82
|
+
"edges": [
|
|
83
|
+
{ "id": "e1", "source": "n1", "target": "n2", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
84
|
+
{ "id": "e2", "source": "n2", "target": "n3", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
85
|
+
{ "id": "e3", "source": "n3", "target": "n4", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
86
|
+
{ "id": "e4", "source": "n4", "target": "n5", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
87
|
+
{ "id": "e5", "source": "n5", "target": "n6", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
88
|
+
{ "id": "e6", "source": "n6", "target": "n7", "sourceHandle": "success", "type": "deletable", "animated": true }
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 3. Qualificação BANT (Budget / Authority / Need / Timing)
|
|
96
|
+
|
|
97
|
+
**Caso:** 4 perguntas pra qualificar lead B2B. Ramifica em "quente" vs "frio".
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"nodes": [
|
|
102
|
+
{ "id": "n1", "type": "start", "position": { "x": 50, "y": 300 }, "data": { "label": "Início", "triggers": [{ "type": "message_received", "keywords": ["proposta","orçamento"], "match_mode": "contains" }] } },
|
|
103
|
+
{ "id": "n2", "type": "send_message", "position": { "x": 370, "y": 300 }, "data": { "label": "B - Budget", "messageItems": [{ "id": "m1", "type": "text", "content": "Pra te ajudar melhor, qual a faixa de investimento que vocês têm em mente?\n\n1️⃣ Até R$ 5k\n2️⃣ R$ 5k a R$ 20k\n3️⃣ Acima de R$ 20k" }] } },
|
|
104
|
+
{ "id": "n3", "type": "wait_response", "position": { "x": 690, "y": 300 }, "data": { "label": "Budget", "waitTime": 60, "waitUnit": "minutes", "validation": "options", "acceptedOptions": ["1","2","3"], "saveTo": "contact_attribute", "saveAttrKey": "budget_tier" } },
|
|
105
|
+
{ "id": "n4", "type": "send_message", "position": { "x": 1010, "y": 300 }, "data": { "label": "A - Authority", "messageItems": [{ "id": "m2", "type": "text", "content": "Você é o decisor ou tem outras pessoas envolvidas?" }] } },
|
|
106
|
+
{ "id": "n5", "type": "wait_response", "position": { "x": 1330, "y": 300 }, "data": { "label": "Autoridade", "waitTime": 60, "waitUnit": "minutes", "validation": "any", "saveTo": "contact_attribute", "saveAttrKey": "authority" } },
|
|
107
|
+
{ "id": "n6", "type": "send_message", "position": { "x": 1650, "y": 300 }, "data": { "label": "N - Need", "messageItems": [{ "id": "m3", "type": "text", "content": "Conta um pouco: o que vocês precisam resolver hoje?" }] } },
|
|
108
|
+
{ "id": "n7", "type": "wait_response", "position": { "x": 1970, "y": 300 }, "data": { "label": "Necessidade", "waitTime": 60, "waitUnit": "minutes", "validation": "any", "saveTo": "contact_attribute", "saveAttrKey": "need" } },
|
|
109
|
+
{ "id": "n8", "type": "send_message", "position": { "x": 2290, "y": 300 }, "data": { "label": "T - Timing", "messageItems": [{ "id": "m4", "type": "text", "content": "Em quanto tempo precisam ter a solução rodando?\n\n1️⃣ Esse mês\n2️⃣ Próximos 3 meses\n3️⃣ Sem pressa" }] } },
|
|
110
|
+
{ "id": "n9", "type": "wait_response", "position": { "x": 2610, "y": 300 }, "data": { "label": "Prazo", "waitTime": 60, "waitUnit": "minutes", "validation": "options", "acceptedOptions": ["1","2","3"], "saveTo": "contact_attribute", "saveAttrKey": "timing_tier" } },
|
|
111
|
+
{ "id": "n10", "type": "condition", "position": { "x": 2930, "y": 300 }, "data": { "label": "Quente?", "conditions": [
|
|
112
|
+
{ "id": "c1", "label": "Lead quente", "field": "contact.custom_attributes.budget_tier", "operator": "not_equal", "value": "1" }
|
|
113
|
+
] } },
|
|
114
|
+
{ "id": "n11", "type": "action", "position": { "x": 3250, "y": 180 }, "data": { "label": "Quente", "items": [
|
|
115
|
+
{ "key": "assign_team", "config": { "team_id": 1 } },
|
|
116
|
+
{ "key": "add_label", "config": { "labels": ["lead-quente"] } },
|
|
117
|
+
{ "key": "create_kanban_item", "config": { "funnel_id": 1, "funnel_stage": "qualificado" } }
|
|
118
|
+
] } },
|
|
119
|
+
{ "id": "n12", "type": "action", "position": { "x": 3250, "y": 420 }, "data": { "label": "Frio", "items": [
|
|
120
|
+
{ "key": "add_label", "config": { "labels": ["lead-frio"] } },
|
|
121
|
+
{ "key": "create_kanban_item", "config": { "funnel_id": 1, "funnel_stage": "nutrir" } }
|
|
122
|
+
] } }
|
|
123
|
+
],
|
|
124
|
+
"edges": [
|
|
125
|
+
{ "id": "e1", "source": "n1", "target": "n2", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
126
|
+
{ "id": "e2", "source": "n2", "target": "n3", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
127
|
+
{ "id": "e3", "source": "n3", "target": "n4", "sourceHandle": "option_1", "type": "deletable", "animated": true },
|
|
128
|
+
{ "id": "e4", "source": "n3", "target": "n4", "sourceHandle": "option_2", "type": "deletable", "animated": true },
|
|
129
|
+
{ "id": "e5", "source": "n3", "target": "n4", "sourceHandle": "option_3", "type": "deletable", "animated": true },
|
|
130
|
+
{ "id": "e6", "source": "n4", "target": "n5", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
131
|
+
{ "id": "e7", "source": "n5", "target": "n6", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
132
|
+
{ "id": "e8", "source": "n6", "target": "n7", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
133
|
+
{ "id": "e9", "source": "n7", "target": "n8", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
134
|
+
{ "id": "e10", "source": "n8", "target": "n9", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
135
|
+
{ "id": "e11", "source": "n9", "target": "n10", "sourceHandle": "option_1", "type": "deletable", "animated": true },
|
|
136
|
+
{ "id": "e12", "source": "n9", "target": "n10", "sourceHandle": "option_2", "type": "deletable", "animated": true },
|
|
137
|
+
{ "id": "e13", "source": "n9", "target": "n10", "sourceHandle": "option_3", "type": "deletable", "animated": true },
|
|
138
|
+
{ "id": "e14", "source": "n10", "target": "n11", "sourceHandle": "cond_0", "type": "deletable", "animated": true },
|
|
139
|
+
{ "id": "e15", "source": "n10", "target": "n12", "sourceHandle": "default", "type": "deletable", "animated": true }
|
|
140
|
+
]
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## 4. Pesquisa CSAT pós-atendimento
|
|
147
|
+
|
|
148
|
+
**Caso:** ao resolver conversa, pede nota de 1 a 5 e comentário.
|
|
149
|
+
|
|
150
|
+
```json
|
|
151
|
+
{
|
|
152
|
+
"nodes": [
|
|
153
|
+
{ "id": "n1", "type": "start", "position": { "x": 50, "y": 300 }, "data": { "label": "Início", "triggers": [{ "type": "conversation_resolved" }] } },
|
|
154
|
+
{ "id": "n2", "type": "wait", "position": { "x": 370, "y": 300 }, "data": { "label": "Aguarda 5 min", "waitTime": 5, "waitUnit": "minutes" } },
|
|
155
|
+
{ "id": "n3", "type": "send_message", "position": { "x": 690, "y": 300 }, "data": { "label": "Pede nota", "messageItems": [{ "id": "m1", "type": "text", "content": "Antes de fechar: de 1 a 5, como foi seu atendimento?\n\n5 = excelente\n1 = ruim" }] } },
|
|
156
|
+
{ "id": "n4", "type": "wait_response", "position": { "x": 1010, "y": 300 }, "data": { "label": "Nota", "waitTime": 60, "waitUnit": "minutes", "validation": "options", "acceptedOptions": ["1","2","3","4","5"], "saveTo": "attribute", "saveAttrKey": "csat_score" } },
|
|
157
|
+
{ "id": "n5", "type": "send_message", "position": { "x": 1330, "y": 300 }, "data": { "label": "Pede comentário", "messageItems": [{ "id": "m2", "type": "text", "content": "Obrigado pela nota! Quer deixar algum comentário?" }] } },
|
|
158
|
+
{ "id": "n6", "type": "wait_response", "position": { "x": 1650, "y": 300 }, "data": { "label": "Comentário", "waitTime": 30, "waitUnit": "minutes", "validation": "any", "saveTo": "attribute", "saveAttrKey": "csat_comment" } },
|
|
159
|
+
{ "id": "n7", "type": "send_message", "position": { "x": 1970, "y": 300 }, "data": { "label": "Encerra", "messageItems": [{ "id": "m3", "type": "text", "content": "Valeu pelo feedback! 🙏" }] } }
|
|
160
|
+
],
|
|
161
|
+
"edges": [
|
|
162
|
+
{ "id": "e1", "source": "n1", "target": "n2", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
163
|
+
{ "id": "e2", "source": "n2", "target": "n3", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
164
|
+
{ "id": "e3", "source": "n3", "target": "n4", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
165
|
+
{ "id": "e4", "source": "n4", "target": "n5", "sourceHandle": "option_1", "type": "deletable", "animated": true },
|
|
166
|
+
{ "id": "e5", "source": "n4", "target": "n5", "sourceHandle": "option_2", "type": "deletable", "animated": true },
|
|
167
|
+
{ "id": "e6", "source": "n4", "target": "n5", "sourceHandle": "option_3", "type": "deletable", "animated": true },
|
|
168
|
+
{ "id": "e7", "source": "n4", "target": "n5", "sourceHandle": "option_4", "type": "deletable", "animated": true },
|
|
169
|
+
{ "id": "e8", "source": "n4", "target": "n5", "sourceHandle": "option_5", "type": "deletable", "animated": true },
|
|
170
|
+
{ "id": "e9", "source": "n5", "target": "n6", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
171
|
+
{ "id": "e10", "source": "n6", "target": "n7", "sourceHandle": "success", "type": "deletable", "animated": true }
|
|
172
|
+
]
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## 5. Roteamento por horário comercial
|
|
179
|
+
|
|
180
|
+
**Caso:** se dentro do expediente, atribui agente. Se fora, manda ausência.
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"nodes": [
|
|
185
|
+
{ "id": "n1", "type": "start", "position": { "x": 50, "y": 300 }, "data": { "label": "Início", "triggers": [{ "type": "conversation_created" }] } },
|
|
186
|
+
{ "id": "n2", "type": "condition", "position": { "x": 370, "y": 300 }, "data": { "label": "Horário comercial?", "conditions": [
|
|
187
|
+
{ "id": "c1", "label": "Dentro do horário", "field": "now.hour", "operator": "greater_than", "value": "8" }
|
|
188
|
+
] } },
|
|
189
|
+
{ "id": "n3", "type": "action", "position": { "x": 690, "y": 180 }, "data": { "label": "Atribui agente", "items": [
|
|
190
|
+
{ "key": "assign_team", "config": { "team_id": 1 } }
|
|
191
|
+
] } },
|
|
192
|
+
{ "id": "n4", "type": "send_message", "position": { "x": 690, "y": 420 }, "data": { "label": "Ausência", "messageItems": [
|
|
193
|
+
{ "id": "m1", "type": "text", "content": "Recebemos sua mensagem! Nosso horário é das 9h às 18h, dias úteis. Retornamos assim que possível." }
|
|
194
|
+
] } }
|
|
195
|
+
],
|
|
196
|
+
"edges": [
|
|
197
|
+
{ "id": "e1", "source": "n1", "target": "n2", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
198
|
+
{ "id": "e2", "source": "n2", "target": "n3", "sourceHandle": "cond_0", "type": "deletable", "animated": true },
|
|
199
|
+
{ "id": "e3", "source": "n2", "target": "n4", "sourceHandle": "default", "type": "deletable", "animated": true }
|
|
200
|
+
]
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## 6. Triagem com IA (classificação de intenção)
|
|
207
|
+
|
|
208
|
+
**Caso:** usa IA pra ler a primeira mensagem e classificar como compra/suporte/reclamação/dúvida.
|
|
209
|
+
|
|
210
|
+
```json
|
|
211
|
+
{
|
|
212
|
+
"nodes": [
|
|
213
|
+
{ "id": "n1", "type": "start", "position": { "x": 50, "y": 300 }, "data": { "label": "Início", "triggers": [{ "type": "message_received" }] } },
|
|
214
|
+
{ "id": "n2", "type": "ai", "position": { "x": 370, "y": 300 }, "data": {
|
|
215
|
+
"label": "Classifica", "aiMode": "intent",
|
|
216
|
+
"aiPrompt": "Classifique a intenção da última mensagem do cliente",
|
|
217
|
+
"aiIntentOptions": ["compra", "suporte", "reclamacao", "duvida"],
|
|
218
|
+
"aiResponseVar": "intent"
|
|
219
|
+
} },
|
|
220
|
+
{ "id": "n3", "type": "action", "position": { "x": 690, "y": 60 }, "data": { "label": "→ Compra", "items": [{ "key": "assign_team", "config": { "team_id": 1 } }, { "key": "add_label", "config": { "labels": ["intent-compra"] } }] } },
|
|
221
|
+
{ "id": "n4", "type": "action", "position": { "x": 690, "y": 240 }, "data": { "label": "→ Suporte", "items": [{ "key": "assign_team", "config": { "team_id": 2 } }, { "key": "add_label", "config": { "labels": ["intent-suporte"] } }] } },
|
|
222
|
+
{ "id": "n5", "type": "action", "position": { "x": 690, "y": 420 }, "data": { "label": "→ Reclamação", "items": [{ "key": "assign_team", "config": { "team_id": 3 } }, { "key": "change_priority", "config": { "priority": "high" } }, { "key": "add_label", "config": { "labels": ["intent-reclamacao"] } }] } },
|
|
223
|
+
{ "id": "n6", "type": "action", "position": { "x": 690, "y": 600 }, "data": { "label": "→ Dúvida", "items": [{ "key": "assign_captain", "config": { "assistant_id": 1 } }] } }
|
|
224
|
+
],
|
|
225
|
+
"edges": [
|
|
226
|
+
{ "id": "e1", "source": "n1", "target": "n2", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
227
|
+
{ "id": "e2", "source": "n2", "target": "n3", "sourceHandle": "intent_compra", "type": "deletable", "animated": true },
|
|
228
|
+
{ "id": "e3", "source": "n2", "target": "n4", "sourceHandle": "intent_suporte", "type": "deletable", "animated": true },
|
|
229
|
+
{ "id": "e4", "source": "n2", "target": "n5", "sourceHandle": "intent_reclamacao", "type": "deletable", "animated": true },
|
|
230
|
+
{ "id": "e5", "source": "n2", "target": "n6", "sourceHandle": "intent_duvida", "type": "deletable", "animated": true }
|
|
231
|
+
]
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## 7. Re-engajamento de lead frio
|
|
238
|
+
|
|
239
|
+
**Caso:** após 7 dias sem resposta, manda template aprovado e marca label.
|
|
240
|
+
|
|
241
|
+
```json
|
|
242
|
+
{
|
|
243
|
+
"nodes": [
|
|
244
|
+
{ "id": "n1", "type": "start", "position": { "x": 50, "y": 300 }, "data": { "label": "Início", "triggers": [{ "type": "label_added", "label": "follow-up" }] } },
|
|
245
|
+
{ "id": "n2", "type": "wait", "position": { "x": 370, "y": 300 }, "data": { "label": "Espera 7 dias", "waitTime": 7, "waitUnit": "days" } },
|
|
246
|
+
{ "id": "n3", "type": "send_message", "position": { "x": 690, "y": 300 }, "data": { "label": "Template re-engajamento", "messageItems": [
|
|
247
|
+
{ "id": "m1", "type": "whatsapp_template", "templateId": 42, "params": ["{{contact.name}}"] }
|
|
248
|
+
] } },
|
|
249
|
+
{ "id": "n4", "type": "action", "position": { "x": 1010, "y": 300 }, "data": { "label": "Marca tentativa", "items": [
|
|
250
|
+
{ "key": "add_label", "config": { "labels": ["reengajamento-enviado"] } },
|
|
251
|
+
{ "key": "remove_label", "config": { "labels": ["follow-up"] } }
|
|
252
|
+
] } }
|
|
253
|
+
],
|
|
254
|
+
"edges": [
|
|
255
|
+
{ "id": "e1", "source": "n1", "target": "n2", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
256
|
+
{ "id": "e2", "source": "n2", "target": "n3", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
257
|
+
{ "id": "e3", "source": "n3", "target": "n4", "sourceHandle": "success", "type": "deletable", "animated": true }
|
|
258
|
+
]
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## 8. Suporte com escalation pra humano
|
|
265
|
+
|
|
266
|
+
**Caso:** tenta resolver com IA. Se cliente pedir "atendente humano" ou IA não souber, escala.
|
|
267
|
+
|
|
268
|
+
```json
|
|
269
|
+
{
|
|
270
|
+
"nodes": [
|
|
271
|
+
{ "id": "n1", "type": "start", "position": { "x": 50, "y": 300 }, "data": { "label": "Início", "triggers": [{ "type": "message_received" }] } },
|
|
272
|
+
{ "id": "n2", "type": "condition", "position": { "x": 370, "y": 300 }, "data": { "label": "Pede humano?", "conditions": [
|
|
273
|
+
{ "id": "c1", "label": "Sim", "field": "last_message.content", "operator": "contains", "value": "humano" }
|
|
274
|
+
] } },
|
|
275
|
+
{ "id": "n3", "type": "action", "position": { "x": 690, "y": 120 }, "data": { "label": "→ Humano", "items": [
|
|
276
|
+
{ "key": "deactivate_captain", "config": {} },
|
|
277
|
+
{ "key": "assign_team", "config": { "team_id": 2 } },
|
|
278
|
+
{ "key": "add_label", "config": { "labels": ["escalado-humano"] } }
|
|
279
|
+
] } },
|
|
280
|
+
{ "id": "n4", "type": "action", "position": { "x": 690, "y": 480 }, "data": { "label": "→ IA atende", "items": [
|
|
281
|
+
{ "key": "assign_captain", "config": { "assistant_id": 1 } }
|
|
282
|
+
] } }
|
|
283
|
+
],
|
|
284
|
+
"edges": [
|
|
285
|
+
{ "id": "e1", "source": "n1", "target": "n2", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
286
|
+
{ "id": "e2", "source": "n2", "target": "n3", "sourceHandle": "cond_0", "type": "deletable", "animated": true },
|
|
287
|
+
{ "id": "e3", "source": "n2", "target": "n4", "sourceHandle": "default", "type": "deletable", "animated": true }
|
|
288
|
+
]
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## 9. Agendamento via API externa
|
|
295
|
+
|
|
296
|
+
**Caso:** cliente quer marcar reunião — fluxo chama API de booking, salva ID, confirma.
|
|
297
|
+
|
|
298
|
+
```json
|
|
299
|
+
{
|
|
300
|
+
"nodes": [
|
|
301
|
+
{ "id": "n1", "type": "start", "position": { "x": 50, "y": 300 }, "data": { "label": "Início", "triggers": [{ "type": "message_received", "keywords": ["agendar","reunião"], "match_mode": "contains" }] } },
|
|
302
|
+
{ "id": "n2", "type": "send_message", "position": { "x": 370, "y": 300 }, "data": { "label": "Pede data", "messageItems": [{ "id": "m1", "type": "text", "content": "Em que data você prefere? (formato DD/MM)" }] } },
|
|
303
|
+
{ "id": "n3", "type": "wait_response", "position": { "x": 690, "y": 300 }, "data": { "label": "Data", "waitTime": 30, "waitUnit": "minutes", "validation": "regex", "regexPattern": "^\\d{2}/\\d{2}$", "invalidMessage": "Formato inválido. Use DD/MM (ex: 25/05)", "maxRetries": 2, "saveTo": "variable", "saveVariable": "data_pref" } },
|
|
304
|
+
{ "id": "n4", "type": "api", "position": { "x": 1010, "y": 300 }, "data": {
|
|
305
|
+
"label": "Cria booking", "method": "POST",
|
|
306
|
+
"url": "https://api.example.com/bookings",
|
|
307
|
+
"headers": [{ "key": "Authorization", "value": "Bearer {{env.BOOKING_TOKEN}}" }, { "key": "Content-Type", "value": "application/json" }],
|
|
308
|
+
"body": "{\"contact_id\":\"{{contact.id}}\",\"date\":\"{{data_pref}}\"}",
|
|
309
|
+
"apiResponseVar": "booking_result"
|
|
310
|
+
} },
|
|
311
|
+
{ "id": "n5", "type": "send_message", "position": { "x": 1330, "y": 180 }, "data": { "label": "Confirma", "messageItems": [{ "id": "m2", "type": "text", "content": "Reunião agendada! ID {{booking_result.id}}. Te mando lembrete 1h antes." }] } },
|
|
312
|
+
{ "id": "n6", "type": "send_message", "position": { "x": 1330, "y": 420 }, "data": { "label": "Erro", "messageItems": [{ "id": "m3", "type": "text", "content": "Não consegui agendar agora. Um atendente vai te ajudar." }] } },
|
|
313
|
+
{ "id": "n7", "type": "action", "position": { "x": 1650, "y": 420 }, "data": { "label": "Escala", "items": [{ "key": "assign_team", "config": { "team_id": 1 } }] } }
|
|
314
|
+
],
|
|
315
|
+
"edges": [
|
|
316
|
+
{ "id": "e1", "source": "n1", "target": "n2", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
317
|
+
{ "id": "e2", "source": "n2", "target": "n3", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
318
|
+
{ "id": "e3", "source": "n3", "target": "n4", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
319
|
+
{ "id": "e4", "source": "n4", "target": "n5", "sourceHandle": "success", "type": "deletable", "animated": true },
|
|
320
|
+
{ "id": "e5", "source": "n4", "target": "n6", "sourceHandle": "error", "type": "deletable", "animated": true },
|
|
321
|
+
{ "id": "e6", "source": "n6", "target": "n7", "sourceHandle": "success", "type": "deletable", "animated": true }
|
|
322
|
+
]
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## 10. Notificação interna por webhook (label aplicada)
|
|
329
|
+
|
|
330
|
+
**Caso:** quando label "urgente" é aplicada, dispara webhook pro n8n/Slack.
|
|
331
|
+
|
|
332
|
+
```json
|
|
333
|
+
{
|
|
334
|
+
"nodes": [
|
|
335
|
+
{ "id": "n1", "type": "start", "position": { "x": 50, "y": 300 }, "data": { "label": "Início", "triggers": [{ "type": "label_added", "label": "urgente" }] } },
|
|
336
|
+
{ "id": "n2", "type": "action", "position": { "x": 370, "y": 300 }, "data": { "label": "Dispara webhook", "items": [
|
|
337
|
+
{ "key": "send_webhook", "config": {
|
|
338
|
+
"url": "https://hooks.slack.com/services/XXX/YYY/ZZZ",
|
|
339
|
+
"headers": [{ "key": "Content-Type", "value": "application/json" }],
|
|
340
|
+
"body": "{\"text\":\"🚨 Conversa urgente: {{conversation.id}} — cliente {{contact.name}}\"}"
|
|
341
|
+
} },
|
|
342
|
+
{ "key": "change_priority", "config": { "priority": "urgent" } }
|
|
343
|
+
] } }
|
|
344
|
+
],
|
|
345
|
+
"edges": [
|
|
346
|
+
{ "id": "e1", "source": "n1", "target": "n2", "sourceHandle": "success", "type": "deletable", "animated": true }
|
|
347
|
+
]
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## Como usar este catálogo
|
|
354
|
+
|
|
355
|
+
1. **Identifique o pattern mais próximo** do que o cliente pediu
|
|
356
|
+
2. **Copie o `flow_data` inteiro**
|
|
357
|
+
3. **Substitua os IDs e valores reais** (team_id, funnel_id, assistant_id, templateId, URLs, etc) — confira antes via `teams_list`, `funnels_list`, `captain_assistants_list`, `inboxes_whatsapp_templates_list`
|
|
358
|
+
4. **Adicione campos do flow**: `name`, `description`, `channel_type` (`Channel::Waha` etc), `inbox_ids`
|
|
359
|
+
5. **Chame `flows_create`** com o payload completo
|
|
360
|
+
6. Após criar, **ative** com `flows_toggle` se o cliente quiser que rode já
|
|
361
|
+
|
|
362
|
+
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.
|
package/dist/index.js
CHANGED
|
@@ -49,8 +49,8 @@ async function main() {
|
|
|
49
49
|
console.error(`Base URL: ${config.baseUrl}`);
|
|
50
50
|
console.error(`Account: ${config.accountId}`);
|
|
51
51
|
console.error(`Tools registered: ${toolCount}`);
|
|
52
|
-
console.error(`Resources registered:
|
|
53
|
-
console.error(`Prompts registered:
|
|
52
|
+
console.error(`Resources registered: 10 (glossary, data-model, reports-guide, api-conventions, conversation-flows, kanban-deep-dive, best-practices, troubleshooting, flowbuilder-design-guide, flowbuilder-patterns)`);
|
|
53
|
+
console.error(`Prompts registered: 9 (productivity_report, stuck_leads, weekly_recap, customer_health, inactive_contacts, team_load_balance, quality_audit, whatsapp_template_usage, create_flow_brainstorm)`);
|
|
54
54
|
if (config.categories) {
|
|
55
55
|
console.error(`Categories filter: ${config.categories.join(', ')}`);
|
|
56
56
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,oFAAoF;AACpF,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AACxF,MAAM,OAAO,GAAW,GAAG,CAAC,OAAO,CAAC;AAEpC,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,6FAA6F;QAC7F,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAE5B,+EAA+E;QAC/E,IACE,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC;YACtC,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;YACrC,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EACrC,CAAC;YACD,OAAO,CAAC,KAAK,CAAC,4EAA4E,CAAC,CAAC;QAC9F,CAAC;QAED,0FAA0F;QAC1F,gFAAgF;QAChF,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B;YACE,IAAI,EAAE,qBAAqB;YAC3B,OAAO,EAAE,OAAO;SACjB,EACD;YACE,YAAY,EAAE,qBAAqB,EAAE;YACrC,YAAY,EAAE;gBACZ,KAAK,EAAE,EAAE;gBACT,SAAS,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE;gBACnD,OAAO,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE;aAChC;SACF,CACF,CAAC;QAEF,wEAAwE;QACxE,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;QAE1C,uFAAuF;QACvF,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAExD,6EAA6E;QAC7E,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC1B,eAAe,CAAC,MAAM,CAAC,CAAC;QAExB,iFAAiF;QACjF,OAAO,CAAC,KAAK,CAAC,wBAAwB,OAAO,EAAE,CAAC,CAAC;QACjD,OAAO,CAAC,KAAK,CAAC,aAAa,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7C,OAAO,CAAC,KAAK,CAAC,YAAY,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;QAC9C,OAAO,CAAC,KAAK,CAAC,qBAAqB,SAAS,EAAE,CAAC,CAAC;QAChD,OAAO,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/resources.js
CHANGED
|
@@ -53,6 +53,18 @@ export const RESOURCES = [
|
|
|
53
53
|
description: 'Codigos HTTP, erros comuns (401/403/422/429), erros MCP, debugging, quando reportar suporte. Use pra interpretar erros.',
|
|
54
54
|
filename: 'troubleshooting.md',
|
|
55
55
|
},
|
|
56
|
+
{
|
|
57
|
+
name: 'FlowBuilder Design Guide',
|
|
58
|
+
uri: 'lionchat://docs/flowbuilder-design-guide',
|
|
59
|
+
description: 'OBRIGATORIO antes de criar/editar fluxo. Arvore de decisao por necessidade, schema por tipo de node (com handles expostos), regras de layout/positioning, erros comuns, checklist pre-submit.',
|
|
60
|
+
filename: 'flowbuilder-design-guide.md',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'FlowBuilder Patterns',
|
|
64
|
+
uri: 'lionchat://docs/flowbuilder-patterns',
|
|
65
|
+
description: '10 templates de fluxos prontos pra adaptar: saudacao, captura, qualificacao BANT, CSAT, horario comercial, IA intent, re-engajamento, escalation, agendamento, webhook. Cada um com layout valido e handles certos.',
|
|
66
|
+
filename: 'flowbuilder-patterns.md',
|
|
67
|
+
},
|
|
56
68
|
];
|
|
57
69
|
function findDocsPath(filename) {
|
|
58
70
|
const candidates = [
|
package/dist/resources.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,iEAAiE;AAEjE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAS1D,MAAM,CAAC,MAAM,SAAS,GAAkB;IACtC;QACE,IAAI,EAAE,oBAAoB;QAC1B,GAAG,EAAE,0BAA0B;QAC/B,WAAW,EACT,mIAAmI;QACrI,QAAQ,EAAE,aAAa;KACxB;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,GAAG,EAAE,4BAA4B;QACjC,WAAW,EACT,sGAAsG;QACxG,QAAQ,EAAE,eAAe;KAC1B;IACD;QACE,IAAI,EAAE,oBAAoB;QAC1B,GAAG,EAAE,+BAA+B;QACpC,WAAW,EACT,4GAA4G;QAC9G,QAAQ,EAAE,kBAAkB;KAC7B;IACD;QACE,IAAI,EAAE,mBAAmB;QACzB,GAAG,EAAE,iCAAiC;QACtC,WAAW,EACT,iHAAiH;QACnH,QAAQ,EAAE,oBAAoB;KAC/B;IACD;QACE,IAAI,EAAE,uBAAuB;QAC7B,GAAG,EAAE,oCAAoC;QACzC,WAAW,EACT,oJAAoJ;QACtJ,QAAQ,EAAE,uBAAuB;KAClC;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,GAAG,EAAE,kCAAkC;QACvC,WAAW,EACT,oIAAoI;QACtI,QAAQ,EAAE,qBAAqB;KAChC;IACD;QACE,IAAI,EAAE,eAAe;QACrB,GAAG,EAAE,gCAAgC;QACrC,WAAW,EACT,2HAA2H;QAC7H,QAAQ,EAAE,mBAAmB;KAC9B;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,GAAG,EAAE,iCAAiC;QACtC,WAAW,EACT,yHAAyH;QAC3H,QAAQ,EAAE,oBAAoB;KAC/B;CACF,CAAC;AAEF,SAAS,YAAY,CAAC,QAAgB;IACpC,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,SAAS,EAAE,mBAAmB,EAAE,QAAQ,CAAC;QAC9C,IAAI,CAAC,SAAS,EAAE,0BAA0B,EAAE,QAAQ,CAAC;KACtD,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC5B,MAAM,CAAC,gBAAgB,CACrB,GAAG,CAAC,IAAI,EACR,GAAG,CAAC,GAAG,EACP;YACE,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,QAAQ,EAAE,eAAe;SAC1B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;YACZ,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC5C,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC5D,CAAC;YACD,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,GAAG,EAAE,GAAG,CAAC,IAAI;wBACb,QAAQ,EAAE,eAAe;wBACzB,IAAI,EAAE,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC;qBACtC;iBACF;aACF,CAAC;QACJ,CAAC,CACF,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"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"}
|
package/endpoints.json
CHANGED
|
@@ -8817,7 +8817,7 @@
|
|
|
8817
8817
|
"method": "POST",
|
|
8818
8818
|
"path": "/api/v1/accounts/{account_id}/flows",
|
|
8819
8819
|
"title": "Criar Flow",
|
|
8820
|
-
"description": "Cria um flow (FlowBuilder) na conta. Requer Admin. flow_data segue formato Vue Flow {nodes:[], edges:[]}. NODE SCHEMA — start: {label}. send_message: {label, messageItems:[{id, type:'text', content}]} handles: success/no_response/error. wait_response: {label, waitTime, waitUnit:'minutes'|'seconds', validation:'any'|'options'|'regex', acceptedOptions:['1','2'] (se options), regexPattern (se regex), invalidMessage, maxRetries:3, saveTo:'variable'|'attribute'|'', saveVariable, saveAttrKey} — quando validation='options' os handles ficam 'option_{val}' + 'timeout'; senão 'success' + 'timeout' — NUNCA precisa de condition node depois. condition: {label, conditions:[{id, label, field, operator, value}]} handles = id de cada condicao + 'default'. action: {label, items:[{key, config:{...}}]} keys comuns assign_team({team_id}), assign_agent({agent_id}), add_label({labels:['slug',...]}), remove_label({labels}), change_status({status}), change_priority({priority}), mute_conversation({}), add_private_note({content}), create_kanban_item({funnel_id, funnel_stage,...}), move_kanban_stage({funnel_id, funnel_stage}), deactivate_flow({}), assign_captain({assistant_id}). api: {label, method, url, headers:[{key,value}], body, apiResponseVar}. set_variable: {label, variables:[{name, value}]}. wait: {label, waitTime, waitUnit}. EDGE SCHEMA: {id, source, target, sourceHandle (opcional, OBRIGATORIO casar com handle exposto pelo node source), type:'deletable', animated:true}. ERROS COMUNS QUE DEVEM SER EVITADOS: (1) action usa items[].config NAO items[].params; (2) send_message usa messageItems NAO items; (3) wait_response com validation='options' NAO precisa de condition node — use sourceHandle='option_X' diretamente; (4) sourceHandle inventado tipo 'c1','c2' nao funciona — sempre usar o handle real; (5) inbox_ids precisa vir aninhado em {flow:{inbox_ids:[]}} no PUT bruto, mas no MCP basta inbox_ids no nivel raiz. Cria novo flow. Obrigatórios: name, channel_type. Valida unicidade quando aplicável. Retorna o flow criado com ID atribuído.",
|
|
8820
|
+
"description": "Cria um flow (FlowBuilder) na conta. Requer Admin. flow_data segue formato Vue Flow {nodes:[], edges:[]}. NODE SCHEMA — start: {label}. send_message: {label, messageItems:[{id, type:'text', content}]} handles: success/no_response/error. wait_response: {label, waitTime, waitUnit:'minutes'|'seconds', validation:'any'|'options'|'regex', acceptedOptions:['1','2'] (se options), regexPattern (se regex), invalidMessage, maxRetries:3, saveTo:'variable'|'attribute'|'', saveVariable, saveAttrKey} — quando validation='options' os handles ficam 'option_{val}' + 'timeout'; senão 'success' + 'timeout' — NUNCA precisa de condition node depois. condition: {label, conditions:[{id, label, field, operator, value}]} handles = id de cada condicao + 'default'. action: {label, items:[{key, config:{...}}]} keys comuns assign_team({team_id}), assign_agent({agent_id}), add_label({labels:['slug',...]}), remove_label({labels}), change_status({status}), change_priority({priority}), mute_conversation({}), add_private_note({content}), create_kanban_item({funnel_id, funnel_stage,...}), move_kanban_stage({funnel_id, funnel_stage}), deactivate_flow({}), assign_captain({assistant_id}). api: {label, method, url, headers:[{key,value}], body, apiResponseVar}. set_variable: {label, variables:[{name, value}]}. wait: {label, waitTime, waitUnit}. EDGE SCHEMA: {id, source, target, sourceHandle (opcional, OBRIGATORIO casar com handle exposto pelo node source), type:'deletable', animated:true}. ERROS COMUNS QUE DEVEM SER EVITADOS: (1) action usa items[].config NAO items[].params; (2) send_message usa messageItems NAO items; (3) wait_response com validation='options' NAO precisa de condition node — use sourceHandle='option_X' diretamente; (4) sourceHandle inventado tipo 'c1','c2' nao funciona — sempre usar o handle real; (5) inbox_ids precisa vir aninhado em {flow:{inbox_ids:[]}} no PUT bruto, mas no MCP basta inbox_ids no nivel raiz. Cria novo flow. Obrigatórios: name, channel_type. Valida unicidade quando aplicável. Retorna o flow criado com ID atribuído. POSITIONING (CRITICO): cada node DEVE ter position:{x,y}. Sem isso, todos empilham no canvas no (0,0). Regra basica de layout: start em {x:50,y:300}, espaco horizontal +320 entre nodes sequenciais, ramificacoes em +/-150 vertical. ANTES DE GERAR JSON consulte o resource lionchat://docs/flowbuilder-design-guide (schema completo de cada tipo de node, handles expostos, erros comuns, checklist) e lionchat://docs/flowbuilder-patterns (10 templates prontos pra adaptar). BRAINSTORMING: se faltou info critica (canal, gatilho, conteudo), use o prompt create_flow_brainstorm como banco de perguntas sugeridas — pergunte SO o que falta, sem checklist forcado. APOS GERAR: rode o checklist da secao 6 do design guide antes de submeter (1 node start, todo node com id unico + position + data, todo edge com sourceHandle valido). NUNCA invente sourceHandle (no condition use cond_0/cond_1/default, no wait_response options use option_X, no AI intent use intent_<opcao>).",
|
|
8821
8821
|
"category": "Flows",
|
|
8822
8822
|
"params": [
|
|
8823
8823
|
{
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lionchat/mcp-server",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "MCP server for LionChat API — 547 tools +
|
|
3
|
+
"version": "0.3.2",
|
|
4
|
+
"description": "MCP server for LionChat API — 547 tools + 10 resources + 9 prompts for AI agents (FlowBuilder enriched)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|