Correção: Seleção de Guia em Experiências Exclusivas¶
🐛 Problema Identificado¶
Para reservas de experiências exclusivas (exclusive=true, shelfExperience=false), o campo ifriend.id (ID do guia) é OBRIGATÓRIO na API, mas o agente não estava solicitando essa informação ao usuário antes de tentar emitir a reserva.
Cenários afetados:¶
- Experiência exclusiva SEM variação (ID 174 no stage)
- Problema: Não pediu para escolher o guia
-
Consequência: Reserva criada com sucesso (mas deveria ter pedido escolha mesmo com 1 guia apenas)
-
Experiência exclusiva COM variação (ID 900 no stage)
- Problema: Não pediu para selecionar o guia
- Erro retornado: HTTP 500 - "Call to a member function getPrice() on null"
- Causa: API tentou processar reserva sem
ifriend.id
Por que acontecia:¶
O agente não tinha: 1. ❌ Ferramenta para listar guias disponíveis de uma experiência 2. ❌ Instruções no prompt para identificar experiências exclusivas 3. ❌ Lógica para solicitar seleção de guia antes de emitir reserva
✅ Solução Implementada¶
1. Nova Ferramenta: listar_guias_experience_tool¶
Criada ferramenta que: - Verifica se experiência é exclusiva (exclusive=true, shelfExperience=false) - Busca lista de guias disponíveis da experiência via API - Retorna detalhes de cada guia (nome, cidade, rating, idiomas, foto)
Arquivo: listar_guias_experience_tool.py
async def listar_guias_experience_tool(experience_id: int) -> dict:
"""
Lista os guias (iFriends) disponíveis para atender uma experiência exclusiva.
Returns:
dict: {
"experience_id": int,
"exclusive": bool,
"shelf_experience": bool,
"ifriends": [ # Lista de guias disponíveis
{
"id": int,
"name": str,
"city": str,
"rating": float,
"price": str,
"bio": str,
"languages": [str],
"photo": str
}
],
"error": None ou mensagem de erro
}
}
"""
Como funciona:¶
- Busca detalhes da experiência via
GET /experiences/{id} - Verifica campos
exclusiveeshelfExperience - Se não for exclusiva ou for de prateleira → retorna lista vazia
- Extrai IDs dos guias do campo
experienceIfriends - Para cada guia, busca detalhes completos via
GET /ifriends/{id} - Retorna lista formatada com informações relevantes
2. Instruções no Prompt do Sistema¶
Adicionadas instruções no estado QUOTE do system_prompt.py:
⚠️ EXPERIÊNCIAS EXCLUSIVAS - SELEÇÃO DE GUIA:
Quando detalhes_experience retornar exclusive=true e shelfExperience=false:
- SEMPRE chamar listar_guias_experience_tool(experience_id)
- Se retornar MAIS DE 1 guia:
* Apresentar lista numerada dos guias disponíveis
* Parar e aguardar usuário escolher o guia
- Se retornar APENAS 1 guia:
* Usar automaticamente esse guia (não precisa perguntar)
- Após escolha, usar ifriend_id na reserva (campo OBRIGATÓRIO para exclusivas)
3. Instruções no Booking Agent¶
Atualizado booking_agent.py com fluxo detalhado:
⚠️ PARA EXPERIÊNCIAS EXCLUSIVAS (exclusive=true, shelfExperience=false):
→ SEMPRE chamar listar_guias_experience_tool(product_id)
→ Se retornar MAIS DE 1 guia disponível:
* Apresentar lista numerada: "Guias disponíveis:
1. [Nome] - [Cidade] - Rating: [X] - [Idiomas]
2. ...
Qual guia você prefere?"
* Aguardar escolha do usuário
→ Se retornar APENAS 1 guia:
* Usar automaticamente (informar ao usuário): "O guia [Nome] irá atendê-lo."
→ CRÍTICO: ifriend_id é OBRIGATÓRIO para experiências exclusivas!
→ Aplicar MESMO fluxo se experiência exclusiva TEM variação
4. Integração com Root Agent¶
Ferramenta registrada em agent.py:
from ifriend_agent.tools.listar_guias_experience_tool import listar_guias_experience_tool
root_agent = LlmAgent(
...
tools=[
...
listar_guias_experience_tool,
...
]
)
🔄 Fluxo Corrigido¶
Cenário 1: Experiência Exclusiva SEM Variação¶
sequenceDiagram
participant User
participant Agent
participant detalhes_experience
participant listar_guias_experience_tool
User->>Agent: Quero reservar experiência ID 174
Agent->>detalhes_experience: Buscar detalhes
detalhes_experience-->>Agent: exclusive=true, shelfExperience=false
Note over Agent: Identificou: EXCLUSIVA!<br/>Precisa selecionar guia
Agent->>listar_guias_experience_tool: Listar guias (174)
listar_guias_experience_tool-->>Agent: [Guia 1: Maria (Rio)]
Note over Agent: Apenas 1 guia disponível<br/>Usar automaticamente
Agent-->>User: O guia Maria irá atendê-lo.<br/>Vamos prosseguir com a reserva?
Cenário 2: Experiência Exclusiva COM Variação E Múltiplos Guias¶
sequenceDiagram
participant User
participant Agent
participant detalhes_experience
participant listar_guias_experience_tool
participant listar_variacoes_tool
User->>Agent: Quero reservar experiência ID 900
Agent->>detalhes_experience: Buscar detalhes
detalhes_experience-->>Agent: exclusive=true, shelfExperience=false, has variations
Note over Agent: EXCLUSIVA + VARIAÇÃO<br/>Precisa: guia + variação
Agent->>listar_guias_experience_tool: Listar guias
listar_guias_experience_tool-->>Agent: [Guia 1: João, Guia 2: Ana, Guia 3: Pedro]
Agent-->>User: Guias disponíveis:<br/>1. João - SP - 4.8★ - [PT, EN]<br/>2. Ana - RJ - 5.0★ - [PT, ES, EN]<br/>3. Pedro - MG - 4.5★ - [PT]<br/><br/>Qual guia você prefere?
User->>Agent: Quero a Ana (opção 2)
Agent->>listar_variacoes_tool: Listar variações
listar_variacoes_tool-->>Agent: [Variação A, Variação B]
Agent-->>User: Variações disponíveis:<br/>1. Variação A...<br/>2. Variação B...<br/><br/>Qual você gostaria?
📦 Estrutura de Payloads Atualizada¶
Experiência Exclusiva SEM Variação¶
{
"type": "experience",
"experience": {"id": 174},
"ifriend": {"id": 11}, // ✅ OBRIGATÓRIO - obtido via listar_guias_experience_tool
"customer": {"id": 7},
"dates": [{
"day": "2026-03-10",
"period": "10:00",
"numAdult": 3,
"numChild": 0
}],
"pax": [...]
}
Experiência Exclusiva COM Variação¶
{
"type": "experience",
"experience": {"id": 900},
"ifriend": {"id": 25}, // ✅ OBRIGATÓRIO - escolhido pelo usuário
"customer": {"id": 7},
"dates": [{
"day": "2026-03-20",
"period": "08:00",
"numAdult": 2,
"numChild": 1
}],
"providerData": {
"provider": "platform",
"variations": [{
"id": 13,
"quantity": 1,
"agePolicies": [
{"id": 34, "name": "Adulto", "quantity": 2},
{"id": 35, "name": "Criança", "quantity": 1}
]
}]
},
"pax": [...] // 3 passageiros
}
Nota importante: Experiências exclusivas COM variação precisam de:
1. ✅ ifriend.id (guia escolhido)
2. ✅ providerData (variação escolhida com age policies corretas)
🎯 Regras de Identificação¶
Quando é Experiência Exclusiva?¶
is_exclusive = experience_data.get("exclusive") == True
is_shelf = experience_data.get("shelfExperience") == False
needs_guide_selection = is_exclusive and not is_shelf
Quando NÃO precisa selecionar guia?¶
❌ Experiências de Prateleira (shelfExperience=true) - Mesmo que exclusive=true, se for "shelf" não precisa selecionar guia
❌ Experiências Não Exclusivas (exclusive=false)
- Não requerem seleção de guia específico
- Se tiverem variação, usar apenas providerData
✅ Experiências Exclusivas (exclusive=true, shelfExperience=false)
- SEMPRE requerem ifriend.id
- Aplicável tanto para sem variação quanto com variação
🧪 Como Testar¶
Teste 1: Experiência Exclusiva com 1 Guia¶
Usuário: "Quero reservar a experiência ID 174 para amanhã"
Esperado:
1. Agent chama detalhes_experience(174)
2. Identifica: exclusive=true, shelfExperience=false
3. Agent chama listar_guias_experience_tool(174)
4. Retorna: [Guia único]
5. Agent informa: "O guia [Nome] irá atendê-lo."
6. Prossegue com coleta de dados
Teste 2: Experiência Exclusiva com Múltiplos Guias¶
Usuário: "Quero reservar a experiência ID 900"
Esperado:
1. Agent chama detalhes_experience(900)
2. Identifica: exclusive=true, shelfExperience=false
3. Agent chama listar_guias_experience_tool(900)
4. Retorna: [Guia 1, Guia 2, Guia 3]
5. Agent apresenta lista numerada com detalhes
6. Aguarda escolha do usuário
7. Após escolha, se tiver variação, lista variações
8. Após escolher variação, prossegue com reserva
Teste 3: Experiência NÃO Exclusiva com Variação¶
Usuário: "Quero reservar a experiência ID 1929"
Esperado:
1. Agent chama detalhes_experience(1929)
2. Identifica: exclusive=false (ou shelfExperience=true)
3. Agent NÃO chama listar_guias_experience_tool
4. Agent chama listar_variacoes_tool diretamente
5. Prossegue com seleção de variação
6. NÃO inclui ifriend.id na reserva
📋 Checklist de Validação¶
Para experiências exclusivas, garantir que:
- [ ]
detalhes_experienceretornaexclusiveeshelfExperience - [ ] Se exclusive=true e shelfExperience=false → chamar
listar_guias_experience_tool - [ ] Se múltiplos guias → apresentar lista e aguardar escolha
- [ ] Se 1 guia → usar automaticamente e informar usuário
- [ ]
ifriend.idestá presente no payload de reserva - [ ] Fluxo funciona tanto para experiências SEM quanto COM variação
- [ ] Não solicitar guia quando shelfExperience=true ou exclusive=false
🔗 Arquivos Modificados¶
- ✅ listar_guias_experience_tool.py - Nova ferramenta
- ✅ system_prompt.py - Instruções no estado QUOTE
- ✅ booking_agent.py - Fluxo detalhado
- ✅ agent.py - Registro da ferramenta
- ✅ cenarios-teste.md - Documentação dos bugs corrigidos
🚀 Próximos Passos¶
- ✅ Testar em stage com produto ID 174 (exclusiva sem variação, 1 guia)
- ✅ Testar em stage com produto ID 900 (exclusiva com variação, múltiplos guias)
- ⚠️ Validar que experiências de prateleira não solicitam guia indevidamente
- ⚠️ Confirmar que experiências não-exclusivas funcionam normalmente
Data da correção: 06/01/2026
Problema original: cenarios-teste.md
Status: ✅ Implementado e documentado