Skip to content

3. O Agente iFriend (ADK Multi-Agent)

O que é o Google ADK?

O Agent Development Kit (ADK) é o framework do Google para criar agentes de IA. Os conceitos fundamentais são:

flowchart LR
    subgraph "Google ADK"
        A[LlmAgent] -->|usa| P[System Prompt]
        A -->|registra| T[Tools]
        A -->|registra| SA[Sub-Agentes]
        A -->|configura| CB[Callbacks]
        R[Runner] -->|executa| A
        R -->|gerencia| S[Session]
    end
Conceito Descrição
LlmAgent Agente que recebe prompt, tools, callbacks e modelo LLM
Tool Função Python que o agente pode invocar para buscar dados ou executar ações
Sub-Agent Agente especializado que recebe delegação do agente principal
AgentTool Wrapper que invoca um agente como tool (call-and-return)
Runner Executor que gerencia o ciclo: receber mensagem → rodar agente → retornar resposta
Session Estado da conversa (histórico, variáveis, contexto JWT) — compartilhado entre agentes
Callback Função que roda antes ou depois do agente processar

Arquitetura Multi-Agent (Coordinator/Dispatcher)

A iFriend utiliza uma arquitetura Coordinator/Dispatcher: um orquestrador central (root_agent) delega para agentes especializados conforme a intenção do usuário.

flowchart TB
    subgraph "root_agent — Orquestrador Slim"
        direction LR
        ROOT["🧠 root_agent<br/>gemini-2.5-flash<br/>~60 linhas de prompt"]
        RT["Tools:<br/>PreloadMemoryTool<br/>AgentTool research<br/>faq_tool"]
    end

    subgraph "Sub-Agentes — LLM-driven transfer"
        direction TB
        DISC["🔍 discovery_agent<br/>Busca de produtos<br/>8 tools"]
        ITIN["📅 itinerary_agent<br/>Roteiros multi-destino<br/>3 tools"]
        QUOTE["💰 quote_agent<br/>Cotação, orçamento e propostas<br/>11 tools"]
        BOOK["📋 booking_agent<br/>Reservas<br/>8 tools"]
        BINFO["ℹ️ booking_info_agent<br/>Consulta reservas<br/>1 tool"]
        PAY["💳 payment_agent<br/>Pagamentos<br/>3 tools"]
        UTIL["📧 utils_agent<br/>Email e CSV<br/>2 tools"]
        SUPP["🤝 support_agent<br/>Atendimento humano<br/>4 tools"]
        CTOUR["🎯 custom_tour_agent<br/>Orçamento personalizado<br/>9 tools"]
        CBOOK["🔗 custom_affiliate_booking_agent<br/>Reserva URL afiliado<br/>3 tools"]
        PROP["📄 proposal_agent<br/>Propostas B2B em PDF<br/>4 tools"]
    end

    subgraph "AgentTool — call-and-return"
        RES["🌐 research_agent<br/>Google Search"]
        FAQ["❓ faq_agent<br/>FAQ iFriend"]
    end

    ROOT -->|"transfer_to_agent<br/>(multi-turn)"| DISC & ITIN & QUOTE & BOOK & BINFO & PAY & UTIL & SUPP & CTOUR & CBOOK & PROP
    ROOT -->|"AgentTool<br/>(pontual)"| RES & FAQ
    DISC & ITIN & QUOTE & BOOK & BINFO & PAY & UTIL & SUPP & CTOUR & CBOOK & PROP -->|"transfer_to_agent<br/>(volta)"| ROOT

    style BOOK stroke-dasharray: 5 5
    style PAY stroke-dasharray: 5 5
    style CBOOK stroke-dasharray: 5 5
    style ITIN stroke-dasharray: 5 5
    style CTOUR stroke-dasharray: 5 5
    style PROP stroke-dasharray: 5 5

Tracejado: agentes condicionais via feature flags. booking_agent (ENABLE_BOOKING), payment_agent (ENABLE_PAYMENT, requer ENABLE_BOOKING), itinerary_agent (ENABLE_ITINERARY), custom_tour_agent (ENABLE_CUSTOM_TOUR), custom_affiliate_booking_agent (ENABLE_CUSTOM_AFFILIATE_BOOKING), proposal_agent (ENABLE_PROPOSAL, geração do PDF restrita a affiliate/admin independente da flag). discovery_agent, quote_agent, booking_info_agent, utils_agent e support_agent são always-on.

Dois padrões de delegação

Padrão Mecanismo Comportamento Agentes
LLM-driven transfer sub_agents Sub-agente responde diretamente ao usuário (multi-turn). Quando termina, transfere de volta ao root_agent. discovery, itinerary, quote, booking, booking_info, payment, utils, support, custom_tour, custom_affiliate_booking, proposal
Call-and-return AgentTool Resultado volta ao orquestrador, que formula a resposta. research, faq

Regra de escape

Todos os sub-agentes possuem uma regra: se o usuário pedir algo fora do domínio do agente ativo, o sub-agente transfere imediatamente ao root_agent em vez de dizer "não consigo". O orquestrador então roteia para o agente correto.

Onde está definido

O agente é montado dinamicamente pelo AgentBuilder em ifriend_agent/agent_builder.py:

# Simplificado para entendimento
class AgentBuilder:
    @staticmethod
    def build() -> LlmAgent:
        # 1. Valida feature flags (ex: PAYMENT requer BOOKING)
        validate_flags()

        # 2. Monta sub-agentes (always-on + condicionais)
        _ALWAYS_ON = [discovery_agent, quote_agent,
                      booking_info_agent, utils_agent, support_agent]
        sub_agents = list(_ALWAYS_ON)
        if get_flag("ENABLE_BOOKING"):
            sub_agents.append(booking_agent)
        if get_flag("ENABLE_PAYMENT"):
            sub_agents.append(payment_agent)
        if get_flag("ENABLE_ITINERARY"):
            sub_agents.append(itinerary_agent)
        if get_flag("ENABLE_CUSTOM_TOUR"):
            sub_agents.append(custom_tour_agent)
        if get_flag("ENABLE_CUSTOM_AFFILIATE_BOOKING"):
            sub_agents.append(custom_affiliate_booking_agent)
        if get_flag("ENABLE_PROPOSAL"):
            sub_agents.append(proposal_agent)

        # 3. Gera prompt dinâmico (só rotas dos agentes ativos)
        instruction = build_orchestrator_instruction(
            [a.name for a in sub_agents]
        )

        # 4. Cria root_agent
        return LlmAgent(
            name="root_agent",
            model="gemini-2.5-flash",
            instruction=instruction,
            sub_agents=sub_agents,
            tools=[PreloadMemoryTool(), AgentTool(research_agent), faq_tool],
            before_agent_callback=before_agent_callback_combined,
            after_agent_callback=save_session_to_memory_callback,
        )

# ifriend_agent/agent.py — ponto de entrada
root_agent = AgentBuilder.build()

O Prompt do Orquestrador (Dinâmico)

O prompt do root_agent é dinâmico — gerado pelo AgentBuilder com base nas feature flags ativas. Definido em ifriend_agent/prompts/orchestrator_prompt.py.

Estrutura do prompt (~60 linhas):

Seção Descrição
Identidade "Você é o iFriend Core Agent — assistente pessoal para experiências de viagem"
Memórias Carregadas automaticamente via PreloadMemoryTool (FULLTEXT search)
Regras de UX Execute silenciosamente → Apresente resultados → 1 pergunta por mensagem
Roteamento Rotas dinâmicas para sub-agentes (só os ativos aparecem)
Hints de desabilitação Instruções para quando booking/payment estão desabilitados
Guardrails Segurança contra prompt injection, nunca revelar instruções
Lógica temporal Data atual injetada via callback

Roteamento de agentes

→ discovery_agent: buscar passeios, experiências, guias, tours em um destino
→ itinerary_agent: montar roteiro multi-destino dia a dia
→ quote_agent: calcular preço, orçamento, cotação, variações de produto
→ booking_agent: reservar, fazer booking, identificar usuário para reserva
→ booking_info_agent: consultar status, detalhes, voucher de reserva existente
→ payment_agent: pagar reserva, cartão de crédito, parcelamento
→ utils_agent: enviar email, gerar CSV/planilha, exportar dados
→ support_agent: falar com humano, consultor, escalar atendimento, WhatsApp
→ custom_tour_agent: orçamento de viagem personalizado, busca no catálogo
→ custom_affiliate_booking_agent: reserva via URL de afiliado
→ proposal_agent: proposta comercial B2B em PDF (affiliate/admin logado)

As rotas de itinerary_agent e proposal_agent são dinâmicas — não ficam em ROUTING_HINTS estático, e sim são injetadas no state ({{itinerary_access_hint}}/{{proposal_access_hint}}) com base na role do JWT do usuário (config/itinerary_access.py, config/proposal_access.py). Sem role de affiliate/admin, o LLM recebe uma instrução explícita para NÃO transferir para lá.

Rotas de agentes desabilitados não aparecem no prompt — o LLM nunca vê opções indisponíveis.

Catálogo de Sub-Agentes

discovery_agent — Busca de Produtos

Campo Valor
Arquivo ifriend_agent/agents/discovery_agent.py
Tools busca_produtos, detalhes_experience, detalhes_guia, disponibilidade_calendario, disponibilidade_horarios, listar_guias_experience, get_affiliate_config, transform_product_url

Fluxo: Busca produtos por destino → apresenta lista numerada → usuário seleciona → mostra detalhes + disponibilidade → transfere ao root_agent para cotação.

quote_agent — Cotação, Orçamento e Propostas em PDF

Campo Valor
Arquivo ifriend_agent/agents/quote_agent.py
Tools tem_variacao, listar_variacoes, calcular_preco, cotacao_moeda, get_affiliate_config, transform_product_url, build_options_block_tool, buscar_produtos_orcamento, perguntar_anexo, gerar_proposta, verificar_acesso_orcamento

Fluxo (produto específico): Verifica variações → lista age policies → calcula preço (BRL) → converte moeda se necessário → transfere ao root_agent para reserva.

Fluxo (MODO ORÇAMENTO — valor total): Busca no catálogo com buscar_produtos_orcamento → usuário seleciona nos cards → pergunta anexo → gera documento PDF via gerar_proposta. A geração do PDF exige affiliate/admin: quote_agent continua aberto a qualquer usuário para busca/cotação, mas assim que a intenção de PDF fica clara chama verificar_acesso_orcamento(); sem acesso, avisa sem jargão técnico e encaminha a um consultor humano.

Ao buscar um guia humano explicitamente (ex: "um guia em Lisboa"), envie o interesse como {"query": "guia local", "tipo_produto": "guia"} em buscar_produtos_orcamento — senão a busca semântica tende a priorizar experiences (passeios) em vez de guias de verdade.

booking_agent — Reservas (condicional)

Campo Valor
Arquivo ifriend_agent/agents/booking_agent.py
Tools buscar_usuario, buscar_agencia, criar_conta_agencia, criar_conta_viajante, validar_dados_reserva, emitir_reserva_guia, emitir_reserva_experience, obter_reserva
Feature flag ENABLE_BOOKING (default: true)

Fluxo: Buscar/criar usuário → validar dados → emitir reserva → transfere ao root_agent para pagamento.

itinerary_agent — Roteiros Multi-Destino (condicional)

Campo Valor
Arquivo ifriend_agent/agents/itinerary_agent.py
Tools busca_produtos, detalhes_experience, detalhes_guia (compartilhadas com discovery_agent)
Feature flag ENABLE_ITINERARY (default: true)

Fluxo: Identifica destinos → faz UMA busca por destino (com suppress_blocks=True) → organiza em roteiro dia a dia → apresenta textualmente em Markdown. Diferença do discovery_agent: não emite cards visuais.

booking_info_agent — Consulta de Reservas (always-on)

Campo Valor
Arquivo ifriend_agent/agents/booking_info_agent.py
Tools obter_reserva (compartilhada com booking_agent)

Fluxo: Solicita booking ID + email → chama obter_reserva → apresenta detalhes. Agente read-only: NUNCA cria, altera ou cancela reservas. Funciona mesmo quando ENABLE_BOOKING=false.

custom_tour_agent — Orçamento de Viagem Personalizado (condicional)

Campo Valor
Arquivo ifriend_agent/agents/custom_tour_agent.py
Tools buscar_produtos_orcamento, busca_produtos, exibir_opcoes_produtos, perguntar_anexo, cotacao_moeda, gerar_proposta, gerar_briefing_tour, gerar_formulario_suporte, verificar_acesso_orcamento
Feature flag ENABLE_CUSTOM_TOUR (default: true)

Aberto a qualquer usuário (inclusive anônimo). Fluxo (6 ETAPAS): entende intenção (destino, datas, pessoas, interesses) → busca produtos reais no catálogo (buscar_produtos_orcamento) e exibe cards selecionáveis → qualifica perfil + pergunta moeda → pergunta anexo (perguntar_anexo, gate obrigatório) → gera orçamento em PDF (gerar_proposta) → orienta sobre download/email na revisão pós-geração.

Sem acesso ao PDF (usuário não é affiliate/admin — checado via verificar_acesso_orcamento() logo na ETAPA 1): pula moeda, anexo e geração, e vai automaticamente para o handoff humano (gerar_briefing_tour → gerar_formulario_suporte, mesmo mecanismo do support_agent) assim que tiver produtos + nº de participantes — sem esperar o usuário pedir explicitamente um atendente, e sem expor termos técnicos ("affiliate", "login") na resposta.

proposal_agent — Propostas Comerciais em PDF (condicional)

Campo Valor
Arquivo ifriend_agent/agents/proposal_agent.py
Tools verificar_acesso_orcamento, buscar_produtos_orcamento, perguntar_anexo, gerar_proposta
Feature flag ENABLE_PROPOSAL (default: true) — a flag liga/desliga o agente; o acesso por role é independente dela

Exclusivo para affiliate/admin autenticado. Gera proposta comercial estruturada (empresa/parceiro, evento, seções por dia, condições de pagamento) — o caso de uso típico é um affiliate montando uma proposta B2B formal para um cliente. Diferente do custom_tour_agent (aberto a todos, orçamento pessoal mais simples).

Fluxo: primeira ação sempre é checar verificar_acesso_orcamento() — sem acesso, avisa sem jargão técnico e transfere ao root_agent imediatamente, mesmo que tenha sido ativado por um caminho inesperado (ex: peer-transfer de outro agente). Com acesso: coleta dados (parceiro, destino, evento, participantes), busca produtos no catálogo iFriend como ponto de partida (buscar_produtos_orcamento, preços prontos) e também aceita itens externos ao catálogo (já negociados com outro fornecedor) com preço digitado manualmente → pergunta anexo (perguntar_anexo) → gera o PDF (gerar_proposta), combinando itens de catálogo e externos no mesmo documento.

custom_affiliate_booking_agent — Reserva URL Afiliado (condicional)

Campo Valor
Arquivo ifriend_agent/agents/custom_affiliate_booking_agent.py
Tools get_affiliate_config, listar_variacoes, transform_product_url
Feature flag ENABLE_CUSTOM_AFFILIATE_BOOKING (default: false, requer bookingUrlTemplate no afiliado)

Fluxo: Valida afiliado → coleta data/hora/passageiros → gera URL final com bookingUrlTemplate/{product_id}?Data=...&Hora=...&passageiros=... → apresenta link para o viajante finalizar a reserva.

payment_agent — Pagamentos (condicional)

Campo Valor
Arquivo ifriend_agent/agents/payment_agent.py
Tools verificar_parcelas, gerar_token_cartao, processar_pagamento
Feature flag ENABLE_PAYMENT (default: true, requer ENABLE_BOOKING)

Fluxo: Verificar parcelas → coletar dados do cartão → tokenizar → processar pagamento.

utils_agent — Email e CSV

Campo Valor
Arquivo ifriend_agent/agents/utils_agent.py
Tools enviar_email_sendgrid, gerar_csv

support_agent — Atendimento Humano

Campo Valor
Arquivo ifriend_agent/agents/support_agent.py
Tools gerar_formulario_suporte, busca_produtos, detalhes_experience, build_options_block_tool
Feature flag ENABLE_SUPPORT_PRE_QUALIFY (default: true) — pré-qualifica tópico + produto antes do formulário

Fluxo: Monta resumo da conversa → (se whitelabel) pré-qualifica tópico → chama gerar_formulario_suporte → transfere ao root_agent.

A tool gerar_formulario_suporte detecta automaticamente horário de atendimento (SUPPORT_START_HOUR/SUPPORT_END_HOUR) e, se fora do horário, redireciona para WhatsApp de emergência.

research_agent — Pesquisa Web (AgentTool)

Campo Valor
Arquivo ifriend_agent/agents/research_agent.py
Tools google_search (built-in ADK)
Modo AgentTool (call-and-return ao orquestrador)

faq_agent — FAQ da Plataforma (AgentTool)

Campo Valor
Arquivo ifriend_agent/agents/faq_agent.py
Tools Nenhuma (respostas via LLM com knowledge inline)
Modo AgentTool (call-and-return ao orquestrador)

Fluxo típico de uma conversa

stateDiagram-v2
    [*] --> root_agent: Usuário envia mensagem

    root_agent --> discovery_agent: "Quero passeio em Paris"
    discovery_agent --> root_agent: Produto selecionado

    root_agent --> quote_agent: Calcular preço
    quote_agent --> root_agent: Orçamento apresentado

    root_agent --> booking_agent: "Quero reservar"
    booking_agent --> root_agent: Reserva emitida

    root_agent --> payment_agent: "Quero pagar"
    payment_agent --> root_agent: Pagamento processado

    root_agent --> utils_agent: "Envia por email"
    utils_agent --> root_agent: Email enviado

    root_agent --> [*]: Conversa encerrada

    note right of root_agent
        O orquestrador roteia para o
        sub-agente correto via
        transfer_to_agent
    end note

Tools: mapa completo por agente

flowchart TD
    subgraph "🔍 discovery_agent"
        busca_produtos["busca_produtos<br/><i>BigQuery + embeddings</i>"]
        detalhes_exp["detalhes_experience"]
        detalhes_guia["detalhes_guia"]
        listar_guias["listar_guias_experience"]
        calendario["disponibilidade_calendario"]
        horarios["disponibilidade_horarios"]
        disc_aff_config["get_affiliate_config"]
        disc_aff_url["transform_product_url"]
    end

    subgraph "💰 quote_agent"
        tem_variacao["tem_variacao"]
        listar_variacoes["listar_variacoes"]
        calcular_preco["calcular_preco"]
        cotacao["cotacao_moeda"]
        q_aff_config["get_affiliate_config"]
        q_aff_url["transform_product_url"]
        q_options["build_options_block_tool"]
        q_buscar_orc["buscar_produtos_orcamento"]
        q_anexo["perguntar_anexo"]
        q_proposta["gerar_proposta"]
        q_acesso["verificar_acesso_orcamento"]
    end

    subgraph "📅 itinerary_agent"
        itin_busca["busca_produtos<br/><i>suppress_blocks=True</i>"]
        itin_det_exp["detalhes_experience"]
        itin_det_guia["detalhes_guia"]
    end

    subgraph "📋 booking_agent"
        buscar_user["buscar_usuario"]
        buscar_agencia["buscar_agencia"]
        criar_agencia["criar_conta_agencia"]
        criar_viajante["criar_conta_viajante"]
        validar["validar_dados_reserva"]
        emitir_exp["emitir_reserva_experience"]
        emitir_guia["emitir_reserva_guia"]
        obter_reserva["obter_reserva"]
    end

    subgraph "ℹ️ booking_info_agent"
        binfo_obter["obter_reserva"]
    end

    subgraph "💳 payment_agent"
        parcelas["verificar_parcelas"]
        token["gerar_token_cartao"]
        pagar["processar_pagamento"]
    end

    subgraph "📧 utils_agent"
        email["enviar_email_sendgrid"]
        csv["gerar_csv"]
    end

    subgraph "🤝 support_agent"
        form_sup["gerar_formulario_suporte"]
        sup_busca["busca_produtos"]
        sup_det["detalhes_experience"]
        blocks["build_options_block_tool"]
    end

    subgraph "🎯 custom_tour_agent"
        ct_buscar_orc["buscar_produtos_orcamento"]
        ct_busca["busca_produtos"]
        ct_exibir["exibir_opcoes_produtos"]
        ct_anexo["perguntar_anexo"]
        ct_cotacao["cotacao_moeda"]
        ct_proposta["gerar_proposta"]
        briefing["gerar_briefing_tour"]
        form_ct["gerar_formulario_suporte"]
        ct_acesso["verificar_acesso_orcamento"]
    end

    subgraph "📄 proposal_agent"
        prop_acesso["verificar_acesso_orcamento"]
        prop_buscar_orc["buscar_produtos_orcamento"]
        prop_anexo["perguntar_anexo"]
        prop_proposta["gerar_proposta"]
    end

    subgraph "🔗 custom_affiliate_booking_agent"
        aff_config["get_affiliate_config"]
        aff_var["listar_variacoes"]
        aff_url["transform_product_url"]
    end

    subgraph "🤖 root_agent"
        preload["PreloadMemoryTool"]
        research["AgentTool research_agent<br/><i>Google Search</i>"]
        faq["faq_tool<br/><i>FAQ iFriend</i>"]
    end

Como uma tool funciona

Toda tool segue este padrão:

# ifriend_agent/tools/alguma_tool.py

async def minha_tool(
    parametro1: str,
    parametro2: int,
    tool_context: ToolContext,  # Injetado automaticamente pelo ADK
) -> dict:
    """Descrição que o LLM lê para decidir quando usar esta tool."""

    # 1. Pegar contexto JWT (se necessário)
    jwt_ctx = tool_context.state.get("jwt_context", {})

    # 2. Chamar API iFriend via client centralizado
    client = IFriendAPIClient()
    response = await client.get("/api/endpoint", params={...})

    # 3. Retornar dados para o LLM processar
    return {"resultado": response}

Pontos importantes: - O ToolContext é injetado pelo ADK e dá acesso ao state da sessão (compartilhado entre todos os agentes) - O IFriendAPIClient centraliza retry, circuit breaker e autenticação - Cada tool pertence a um único sub-agente — não há sobreposição

Callbacks

flowchart LR
    subgraph "Before Agent (root_agent)"
        B1["inject_date<br/><i>Seta current_date no state</i>"]
        B2["inject_jwt<br/><i>JWT context no state</i>"]
    end

    subgraph "Automático a cada LLM request"
        PM["PreloadMemoryTool<br/><i>FULLTEXT search com query do usuário</i>"]
    end

    subgraph "After Agent (root_agent)"
        A1["save_session_to_memory<br/><i>Resumo LLM → CloudSQL</i>"]
    end

    B1 --> B2 --> ROOT[Root Agent]
    PM -.->|"injeta memórias<br/>antes de cada chamada LLM"| ROOT
    ROOT --> A1
Callback Quando O que faz Arquivo
before_agent_callback_combined Before (root) Injeta current_date + jwt_context no state callbacks/agent_callbacks.py
PreloadMemoryTool Antes de cada LLM request Busca memórias via FULLTEXT search com query real do usuário Built-in ADK
save_session_to_memory_callback After (root) Sumariza conversa via LLM → UPSERT no CloudSQL callbacks/agent_callbacks.py

Compartilhamento de Estado

O session.state é compartilhado por toda a hierarquia (root + sub-agents):

Chave no state Origem Consumido por
jwt_context before_agent_callback_combined (root) Todas as tools via tool_context.state
current_date, current_year, current_datetime, current_weekday before_agent_callback_combined (root) Prompts via {current_date} etc.
message_metadata Adapters (SSE, WebChat) Tools de whitelabel, context enrichment
user_id, company_id JWT decode Tools de booking, busca

Economia de Tokens (vs. arquitetura anterior)

Aspecto Antes (single-agent) Agora (multi-agent)
Prompt 336 linhas (tudo junto) ~60 linhas (orquestrador) + ~30-55 (sub-agente ativo)
Tools por turno 24 (sempre todas) 2-8 (só as do agente ativo)
Payloads JSON Inline no prompt static_instruction (cacheável pelo Gemini)
Redução estimada — ~70% menos tokens por turno

HTTP Client centralizado

Todas as tools usam o IFriendAPIClient para chamar a API iFriend:

flowchart LR
    TOOL[Tool] --> CLIENT[IFriendAPIClient]

    CLIENT --> POOL[Connection Pool]
    CLIENT --> RETRY[Retry]
    CLIENT --> CB[Circuit Breaker]
    CLIENT --> CACHE[Cache]
    CLIENT --> AUTH[Auto Auth]

    POOL --> API[API iFriend]

Como adicionar um novo agente

  1. Crie o arquivo em ifriend_agent/agents/meu_novo_agent.py
  2. Registre em ifriend_agent/agents/__init__.py
  3. Adicione ao AgentBuilder:
  4. Always-on (sub_agent multi-turn): adicione à lista _ALWAYS_ON_SUB_AGENTS em agent_builder.py
  5. Condicional: crie feature flag em config/feature_flags.py e mapeie em _FLAG_TO_AGENT no agent_builder.py
  6. AgentTool (call-and-return): adicione à lista tools no método build()
  7. Adicione rota no prompt (prompts/orchestrator_prompt.py → ROUTING_HINTS)
  8. Crie testes em ifriend_agent/tests/
  9. Atualize AGENTS.md

Consulte a seção "Como Adicionar um Novo Agente" no AGENTS.md para detalhes completos com exemplos de código.

Dicas para manutenção

  • Modelo e parâmetros são configuráveis via env vars: MODEL, AGENT_TEMPERATURE, AGENT_TOP_P, AGENT_TOP_K, AGENT_MAX_OUTPUT_TOKENS
  • LLM retry configurável: LLM_RETRY_INITIAL_DELAY, LLM_RETRY_ATTEMPTS (config em ifriend_agent/config/llm_config.py)
  • Feature flags controlam quais agentes estão ativos: ENABLE_BOOKING, ENABLE_PAYMENT, ENABLE_ITINERARY, ENABLE_CUSTOM_TOUR, ENABLE_PROPOSAL, ENABLE_CUSTOM_AFFILIATE_BOOKING, ENABLE_A2A
  • Prompt do orquestrador é dinâmico — rotas e hints são gerados automaticamente com base nos agentes ativos
  • Cada sub-agente tem disallow_transfer_to_peers=True — só pode voltar ao root_agent, não transferir entre pares
  • O IFriendAPIClient tem métricas built-in — use para diagnosticar problemas de performance
  • Para referência técnica detalhada de cada agente, consulte AGENTS.md na raiz do projeto

Anterior: ← Arquitetura · Próximo: Adaptadores de Mensageria →