Como Fazer O Fluxo De Trabalho Funcionar Como Abaixo

Conversa em Chat

Mensagem de Prompt IA

"Você é um assistente de viagens profissional. Você opera em três fases distintas e deve seguir regras de formatação rigorosas para cada uma.

Por favor, faça a conversa com o usuário, cumprimente e exiba o botão de acordo com a solicitação do usuário.

FASE 1: Descoberta de País

Gatilho: Saudação inicial.

Ação: Chamar get_destinations.

Formato: Comece com [TYPE:DESTINATION], seguido de uma saudação, depois o JSON bruto […].

FASE 2: Descoberta de Cidade

Gatilho: Usuário seleciona um país.

Ação: Chamar get_cities.

Formato: Comece com [TYPE:CITY], seguido de um breve prompt de seleção, depois o JSON bruto […].

FASE 3: Descoberta de Pacotes

Gatilho: Usuário seleciona uma cidade.

Ação: Chamar tour_packages usando o valor do payload.

Instrução para Obter ID da Cidade: Quando o usuário seleciona uma cidade, você receberá uma mensagem com um valor de payload. Este payload é o term_id para aquela cidade. Você deve usar este valor específico ao chamar a ferramenta tour_packages. Se você não tiver um term_id, peça ao usuário para esclarecer sua seleção de cidade.

Formato: Comece com [TYPE:PACKAGES], seguido de uma breve confirmação, depois o JSON bruto […].

PROTOCOLOS CRÍTICOS:

CABEÇALHOS DE ROTEAMENTO: Cada mensagem DEVE começar com [TYPE:DESTINATION], [TYPE:CITY] ou [TYPE:PACKAGES].

SEM RESUMOS: Nunca escreva listas conversacionais ou contagens. Forneça apenas a tag, uma breve saudação e o JSON bruto.

LEIVEL DE MÁQUINA: O JSON […] deve ser a parte final de cada mensagem.

USO DE FERRAMENTAS: Sempre use as ferramentas fornecidas para buscar dados. Nunca invente pacotes ou cidades."

IMPORTANTE:

  • Retorne APENAS JSON válido
  • NÃO inclua explicações
  • NÃO escape aspas
  • NÃO inclua [TYPE:…] dentro do JSON
  • A saída deve ser diretamente analisável por JSON.parse

Fluxo de Trabalho

Analisador Global

const rawOutput = $input.first().json.output || “”;

// =========================
// Helper: Retorno padrão
// =========================
function formatResponse(data) {
return [{ json: data }];
}

// =========================
// Detectar TYPE
// =========================
function detectType(text) {
if (text.includes(“[TYPE:DESTINATION]”)) return “DESTINATION”;
if (text.includes(“[TYPE:CITY]”)) return “CITY”;
if (text.includes(“[TYPE:PACKAGES]”)) return “PACKAGES”;
return null;
}

// =========================
// Extrair JSON LIMPO
// =========================
function extractJSONArray(text) {
if (!text) return null;

// Remover tags TYPE
let cleaned = text.replace(/\[TYPE:[A-Z]+\]/g, "").trim();

// Remover placeholder
if (cleaned.includes("[...]")) return null;

// Obter limites do JSON
const start = cleaned.indexOf('[');
const end = cleaned.lastIndexOf(']');

if (start === -1 || end === -1) return null;

let jsonString = cleaned.substring(start, end + 1);

// 🔥 Corrigir problemas comuns de IA
jsonString = jsonString
    .replace(/\\\//g, "/")     // corrigir barras escapadas
    .replace(/;\s*$/, "")      // remover ponto e vírgula à direita
    .trim();

try {
    let parsed = JSON.parse(jsonString);

    // Lidar com JSON duplo codificado
    if (typeof parsed === "string") {
        parsed = JSON.parse(parsed);
    }

    return parsed;
} catch (e) {
    throw new Error("Falha na Análise do JSON:\n" + jsonString);
}

}

// =========================
// PRINCIPAL
// =========================
const type = detectType(rawOutput);
const parsed = extractJSONArray(rawOutput);

// =========================
// DESTINATION
// =========================
if (type === “DESTINATION” && parsed) {
return formatResponse({
recipient: { id: “123456” },
message: {
text: “Selecione um país:”,
quick_replies: parsed[0].data.map(i => ({
content_type: “text”,
title: i.destination,
payload: i.id
}))
}
});
}

// =========================
// CITY
// =========================
if (type === “CITY” && parsed) {
return formatResponse({
recipient: { id: “123456” },
message: {
text: “Selecione uma cidade:”,
quick_replies: parsed[0].data.map(i => ({
content_type: “text”,
title: i.city || i.name,
payload: i.id
}))
}
});
}

// =========================
// PACKAGES
// =========================
if (type === “PACKAGES” && parsed) {
const packages = parsed[0].data;

const elements = packages.map(pkg => ({
    title: pkg.title,
    subtitle: pkg.subtitle || "Melhor pacote de turismo disponível",
    image_url: pkg.image_url,
    buttons: (pkg.buttons || []).map(btn => ({
        type: btn.type === "web_url" ? "web_url" : "postback",
        title: btn.title,
        url: btn.url,
        payload: btn.payload
    }))
}));

return formatResponse({
    recipient: { id: "123456" },
    message: {
        attachment: {
            type: "template",
            payload: {
                template_type: "generic",
                elements: elements
            }
        }
    }
});

}

// =========================
// FALLBACK
// =========================
return formatResponse({
message: {
text: rawOutput || “Nenhuma resposta disponível.”
}
});

Minhas Perguntas

  • Gostaria de ter a conversa também e o Agente IA fará a busca por conta própria e fornecerá.
  • Atualmente, ele funciona apenas de acordo com o clique do botão e o payload.
  • Após o clique nos detalhes do programa pelo usuário, a IA buscará os dados apenas para aquele pacote e continuará a conversa.

Para fazer tudo isso funcionar, você poderia me sugerir como criar o fluxo de trabalho e como fazer o design do sistema, quantos Agentes IA eu preciso usar e como dizer ao fluxo de trabalho qual ferramenta usar quando necessário?

Por favor, me ajude no brainstorming ou me guie, obrigado.

Tudo bem, depois de ler seus posts, aqui está meu feedback após considerar os requisitos, espero que isso ajude.

Objetivo e abordagem

  • Criar um fluxo de conversa modular e auto-aprendizado que possa buscar dados além de payloads de botões predefinidos.

  • Usar um pequeno conjunto de agentes de IA especializados (ou ferramentas) para cobrir descoberta, seleção, empacotamento e conversa narrativa.

  • Orquestrar o uso de ferramentas de forma declarativa no workflow, para que o sistema escolha a ferramenta correta no momento certo.


Visão geral do design do sistema

  • Componentes primários

    1. Chat Orchestrator (n8n ou um microsserviço): conduz o estado da conversa, roteando para agentes/ferramentas.

    2. Camada de Agente de IA: um pequeno conjunto de agentes especializados (Discovery, City, Packages, Narrative) com escopos definidos.

    3. Dados e Ferramentas: get_destinations, get_cities, tour_packages, e qualquer fonte de dados externa. Todos acessados via APIs estáveis.

    4. Armazenamento de Estado e Contexto: armazena dados de sessão do usuário, país/cidade escolhidos e pacote selecionado, além de IDs para rastreabilidade.

    5. Formatador de Mensagens: aplica os headers de roteamento [TYPE:DESTINATION]/[TYPE:CITY]/[TYPE:PACKAGES] e payload JSON final.

    6. Observabilidade: logs estruturados, IDs de rastreamento e dashboards de erro.

  • Padrão de fluxo de dados

    1. Usuário cumprimenta → agente Discovery fornece destinos.

    2. Usuário seleciona um destino → agente City fornece cidades para aquele país.

    3. Usuário seleciona uma cidade → agente Packages busca pacotes; conversa continua com detalhe do pacote.

    4. Ao selecionar o pacote, o sistema busca dados detalhados do pacote e atualiza a conversa com conteúdo rico.


Design de agente de IA e funções

  • Agente A: Discovery

    • Propósito: buscar e apresentar destinos; manter payload JSON como fonte única de verdade.

    • Output: header [TYPE:DESTINATION] + saudação + JSON bruto.

  • Agente B: City

    • Propósito: buscar cidades para um destino escolhido; fornecer prompts concisos para selecionar uma cidade.

    • Output: header [TYPE:CITY] + prompt breve + JSON bruto.

  • Agente C: Packages

    • Propósito: buscar pacotes para uma cidade quando uma cidade é selecionada; fornecer detalhes compactos e fáceis de escanear.

    • Output: header [TYPE:PACKAGES] + confirmação breve + JSON bruto.

  • Agente D: Narrative/Conversation

    • Propósito: gerar diálogo humanizado que faça referência ao destino/cidade/pacote escolhido e guie o usuário.

    • Output: mensagens em linguagem natural guiadas pelo contexto atual, enquanto ainda emitem o header TYPE quando necessário.

  • Agente E: Verificação e Segurança

    • Propósito: garantir precisão dos dados, prevenir alucinações, aplicar privacidade de dados e validar integridade de payload em todas as etapas.
  • Opcional: Agente de Enriquecimento de Dados

    • Propósito: buscar metadados adicionais (sazonalidade, clima, dicas locais) para enriquecer descrições de pacotes.
  • Comece com 4 agentes centrais (Discovery, City, Packages, Narrative) mais um agente Verification leve. Você pode adicionar enriquecimento depois.

Como o workflow decide qual ferramenta/agente usar

  • Implementar uma camada de roteamento no Orchestrator:

    • Se nenhum TYPE presente ou saudação inicial → Discovery.

    • Se o usuário selecionou um país → City.

    • Se o usuário selecionou uma cidade → Packages.

    • Se o usuário pede narrativa ou detalhe mais profundo → Narrative.

    • Se integridade de dados ou dados sensíveis estão envolvidos → Verification.

  • Use transições de estado explícitas:

    • state: { phase: “discovery” | “city” | “packages” | “narrative”, country_id, city_id, package_id, user_id }
  • Defina um registro de ferramenta centralizado com:

    • name, type (chamada de API, função local, LLM), input schema, output schema, error policy.

Schema de conversa e formatação

  • Manter o header de roteamento obrigatório em cada mensagem:

    • [TYPE:DESTINATION]

    • [TYPE:CITY]

    • [TYPE:PACKAGES]

  • Garantir que o payload JSON legível por máquina seja o último bloco da mensagem.

  • Exemplo de fluxo de conversa (nível alto)

    1. Discovery:

      • Output: [TYPE:DESTINATION] + saudação + JSON bruto de destinos
    2. City:

      • Output: [TYPE:CITY] + prompt + JSON bruto de cidades
    3. Packages:

      • Output: [TYPE:PACKAGES] + confirmação + JSON bruto de pacotes
    4. Narrative:

      • Output: mensagens em linguagem natural com contexto, ou narrativa detalhada de pacote, ainda marcadas quando necessário.
  • Persistência e rastreabilidade

    • Anexar um session_id e um request_id a cada mensagem para correlacionar etapas.

Blueprint de orquestração de workflow (orientado para n8n)

  • Layout de nós (blocos modulares)

    1. Trigger: webhook HTTP ou Chat para iniciar uma sessão.

    2. State Loader: carregar contexto de sessão de um datastore.

    3. AI Gateway: selecionar agente apropriado baseado na fase.

    4. Agent Call: invocar get_destinations / get_cities / tour_packages ou conteúdo narrativo.

    5. Response Formatter: embrulhar no header [TYPE:*] correto e JSON final.

    6. State Saver: persistir contexto atualizado e seleções.

    7. Output: enviar ao usuário, registrar a interação.

  • Contratos de dados

    • Destinations API retorna: [{ id, country, name, description, image }, …]

    • Cities API retorna: [{ id, city, country_id, region }, …]

    • Packages API retorna: [{ id, title, summary, image_url, price, details }, …]

  • Tratamento de erro

    • Política de retry com backoff exponencial para erros de API transitórios.

    • Mensagens de fallback se APIs falharem, com um ID de rastreamento claro.

    • Validação em cada etapa para garantir que campos obrigatórios existam antes de prosseguir.

  • Segurança e isolamento

    • Cada container usa uma rede dedicada e uma chave de API com escopo para o agente.

    • Secrets gerenciados por um vault; rotacionar periodicamente.

    • Least-privilege em manifestos Docker Compose ou Kubernetes.