Skill Selector
O módulo SkillSelector fornece funcionalidade inteligente para seleção automática de skills externas usando análise de LLM. Permite que tools automaticamente escolham a melhor skill externa baseada no contexto da conversa.
🚀 Características Principais
- Seleção inteligente - Usa LLM para analisar contexto e escolher a melhor skill
- Verificação de disponibilidade - Checa horários de funcionamento e exceções
- Integração automática - Acessa skills da sessão automaticamente
- Fallback configurável - Permite definir skill de fallback para casos não cobertos
🔧 Disponibilidade Automática
O objeto skill_selector já está automaticamente disponível em seus tools, não sendo necessário instanciá-lo manualmente. Ele vem pré-configurado com todos os atributos necessários (agent, conversation_id, trace, messages) e pronto para uso.
# ✅ Correto - skill_selector já está disponível
available_skills = skill_selector.get_available_external_skills()
# ❌ Não necessário - não precisa instanciar
# skill_selector = actions_sdk.SkillSelector(...)
📋 Métodos Principais
skill_selector.get_available_external_skills()
Converte skills externas do estado da sessão para objetos ExternalSkill.
Retorno:
List[ExternalSkill]: Lista de skills disponíveis da sessão
Quando utilizar:
- Verificar quais skills estão disponíveis na sessão atual
- Obter lista formatada para uso com outros métodos
Exemplo:
# Obter skills disponíveis
available_skills = skill_selector.get_available_external_skills()
if available_skills:
print(f"Skills disponíveis: {[skill.name for skill in available_skills]}")
else:
print("Nenhuma skill externa configurada")
skill_selector.get_current_external_skill()
Retorna a skill externa atualmente ativa na sessão.
Retorno:
Optional[ExternalSkill]: Skill externa atual ouNonese não houver skill ativa
Quando utilizar:
- Verificar se há uma skill externa já ativa antes de fazer transferência
- Implementar comportamentos diferentes baseados na skill atual
- Evitar transferências redundantes
- Criar contexto adicional nas respostas
Exemplo básico:
# Verificar skill atual
current_skill = skill_selector.get_current_external_skill()
if current_skill:
print(f"Usuário está na skill: {current_skill.name} (ID: {current_skill.id})")
else:
print("Nenhuma skill externa ativa")
Exemplo avançado - Evitar transferência redundante:
def transferir_para_vendas():
"""
Transfere para vendas apenas se ainda não estiver lá
"""
# Verificar skill atual
current_skill = skill_selector.get_current_external_skill()
# Se já está em vendas, não transferir novamente
if current_skill and "vendas" in current_skill.name.lower():
return actions_sdk.ResponseToUser(
message="Você já está sendo atendido pela equipe de vendas. Como posso ajudar?",
instruction="Usuário já está na skill de vendas"
)
# Buscar skill de vendas
available_skills = skill_selector.get_available_external_skills()
vendas_skill = next(
(skill for skill in available_skills if "vendas" in skill.name.lower()),
None
)
if vendas_skill:
return actions_sdk.ResponseToUser(
message="Vou transferir você para nossa equipe de vendas.",
functions=[
actions_sdk.TransferToHuman(
reason="Cliente solicitou atendimento de vendas",
external_skill_name=vendas_skill.name,
external_skill_id=str(vendas_skill.id)
)
]
)
else:
return actions_sdk.ResponseToUser(
message="Desculpe, o setor de vendas não está disponível no momento.",
instruction="Skill de vendas não encontrada"
)
skill_selector.is_external_skill_available(external_skill)
Verifica se uma skill externa está disponível baseado em horários de funcionamento e exceções.
Parâmetros:
external_skill(ExternalSkill): Skill a ser verificada
Retorno:
bool: True se disponível, False caso contrário
Lógica de disponibilidade:
- Se
opening_hourseopening_hours_exceptionssão None: sempre disponível - Se
opening_hoursé dict vazio{}: nunca disponível - Se horário atual está em período de exceção: não disponível
- Se horário atual está dentro do horário de funcionamento: disponível
- Caso contrário: não disponível
Exemplo:
skill = actions_sdk.ExternalSkill(
id=uuid4(),
name="Suporte Técnico",
description="Suporte durante horário comercial",
opening_hours={
"1": ["09:00:00.000Z", "18:00:00.000Z"], # Segunda-feira
"2": ["09:00:00.000Z", "18:00:00.000Z"], # Terça-feira
},
opening_hours_exceptions=[
["2025-12-24T00:00:00.000Z", "2025-12-26T23:59:59.999Z"] # Natal
]
)
is_available = skill_selector.is_external_skill_available(skill)
if is_available:
print("Skill disponível no momento")
else:
print("Skill fora do horário de funcionamento")
skill_selector.select_best_skill()
Seleciona a melhor skill externa usando análise de LLM.
Parâmetros:
external_skills(List[ExternalSkill], opcional): Skills disponíveis. Se não fornecido, usa da sessãomessages(List[ConversationMessage], opcional): Mensagens para contextofallback_skill(ExternalSkill, opcional): Skill de fallback como último recursocontext_hint(str, opcional): Contexto adicional para ajudar na seleção
Retorno:
Optional[ExternalSkill]: Skill selecionada ou None se seleção falhar
Quando utilizar:
- Transferir usuário para skill mais adequada baseada no contexto
- Automatizar roteamento baseado na conversa
- Implementar lógica de escalação inteligente
Exemplos:
# Uso automático com skills da sessão
selected = skill_selector.select_best_skill(
context_hint="Cliente relatou problema com login"
)
if selected:
return actions_sdk.ResponseToUser(
message=f"Vou transferir você para {selected.name}",
functions=[
actions_sdk.TransferToHuman(
reason="Problema técnico requer especialista",
external_skill_name=selected.name,
external_skill_id=str(selected.id)
)
]
)
# Uso manual com skills específicas
skills = [
actions_sdk.ExternalSkill(
id=uuid4(),
name="Suporte Técnico",
description="Problemas técnicos e bugs"
),
actions_sdk.ExternalSkill(
id=uuid4(),
name="Vendas",
description="Questões comerciais e orçamentos"
)
]
selected = skill_selector.select_best_skill(
external_skills=skills,
context_hint="Cliente interessado em plano premium"
)
🎯 Exemplo Completo
Transferência Inteligente para Suporte
def transferir_para_suporte_adequado():
"""
Analisa a conversa e transfere para a skill mais adequada
"""
try:
# Obter skills disponíveis (skill_selector já está disponível)
available_skills = skill_selector.get_available_external_skills()
if not available_skills:
return actions_sdk.ResponseToUser(
message="No momento não temos atendimento especializado disponível.",
instruction="Nenhuma skill externa configurada"
)
# Filtrar apenas skills disponíveis no horário atual
available_now = []
for skill in available_skills:
if skill_selector.is_external_skill_available(skill):
available_now.append(skill)
if not available_now:
return actions_sdk.ResponseToUser(
message="Nosso atendimento especializado está fora do horário de funcionamento. Tente novamente em horário comercial.",
instruction="Todas as skills externas estão fora do horário"
)
# Definir skill de fallback (atendimento geral)
fallback = next(
(skill for skill in available_now if "geral" in skill.name.lower()),
available_now[0] # Primeira disponível como fallback
)
# Selecionar melhor skill baseada no contexto
selected = skill_selector.select_best_skill(
external_skills=available_now,
fallback_skill=fallback,
context_hint="Analisar conversa para determinar tipo de atendimento necessário"
)
if selected:
return actions_sdk.ResponseToUser(
message=f"Vou transferir você para nossa equipe de {selected.name}. Eles poderão ajudar melhor com sua solicitação.",
instruction=f"Usuário transferido para skill {selected.name} baseado na análise da conversa",
functions=[
actions_sdk.TransferToHuman(
reason="Transferência automática baseada em análise de contexto",
external_skill_name=selected.name,
external_skill_id=str(selected.id)
)
]
)
else:
return actions_sdk.ResponseToUser(
message="Houve um problema ao determinar o melhor atendimento. Vou transferir você para nossa equipe geral.",
instruction="Falha na seleção automática, usando fallback",
functions=[
actions_sdk.TransferToHuman(
reason="Fallback após falha na seleção automática",
external_skill_name=fallback.name,
external_skill_id=str(fallback.id)
)
]
)
except Exception as e:
return actions_sdk.ResponseToUser(
message="Desculpe, tivemos um problema técnico. Tente novamente em alguns instantes.",
instruction=f"Erro no SkillSelector: {str(e)}",
status=actions_sdk.ResponseStatus.ERROR
)
Verificação de Skill Atual Antes de Transferência
def verificar_e_transferir():
"""
Verifica se já está em uma skill antes de fazer nova transferência.
Usa o novo método get_current_external_skill() (v1.25.0+)
"""
try:
# Primeiro: verificar se já está em alguma skill
current_skill = skill_selector.get_current_external_skill()
if current_skill:
# Já está em uma skill - informar contexto
return actions_sdk.ResponseToUser(
message=f"Você está sendo atendido por {current_skill.name}. "
f"Posso transferir para outro departamento se necessário. "
f"Para qual área você gostaria de ser direcionado?",
instruction=f"Cliente já está na skill {current_skill.name}"
)
# Não está em skill - prosseguir com seleção inteligente
available_skills = skill_selector.get_available_external_skills()
if not available_skills:
return actions_sdk.ResponseToUser(
message="No momento não temos departamentos especializados disponíveis.",
instruction="Nenhuma skill externa configurada"
)
# Filtrar por disponibilidade
available_now = [
skill for skill in available_skills
if skill_selector.is_external_skill_available(skill)
]
if not available_now:
return actions_sdk.ResponseToUser(
message="Nossos departamentos especializados estão fora do horário de atendimento.",
instruction="Todas skills fora do horário"
)
# Selecionar melhor skill
selected = skill_selector.select_best_skill(
external_skills=available_now,
context_hint="Primeira transferência - analisar necessidade do cliente"
)
if selected:
return actions_sdk.ResponseToUser(
message=f"Perfeito! Vou transferir você para {selected.name}.",
functions=[
actions_sdk.TransferToHuman(
reason="Transferência inicial baseada em análise de contexto",
external_skill_name=selected.name,
external_skill_id=str(selected.id)
)
]
)
except Exception as e:
return actions_sdk.ResponseToUser(
message="Desculpe, houve um erro ao processar sua solicitação.",
instruction=f"Erro no SkillSelector: {str(e)}",
status=actions_sdk.ResponseStatus.ERROR
)
Comportamento Condicional por Skill Atual
def processar_solicitacao():
"""
Implementa lógica diferente dependendo da skill atual.
Demonstra uso prático de get_current_external_skill()
"""
current_skill = skill_selector.get_current_external_skill()
if not current_skill:
# Não está em skill específica - comportamento padrão
return actions_sdk.ResponseToUser(
message="Como posso ajudá-lo hoje?",
instruction="Nenhuma skill específica ativa - fluxo geral"
)
# Lógica específica por skill
skill_name_lower = current_skill.name.lower()
if "suporte" in skill_name_lower or "tecnico" in skill_name_lower:
return actions_sdk.ResponseToUser(
message="Estou aqui para ajudar com questões técnicas. Pode descrever o problema?",
instruction=f"Contexto: skill de suporte técnico ({current_skill.name})"
)
elif "vendas" in skill_name_lower or "comercial" in skill_name_lower:
return actions_sdk.ResponseToUser(
message="Ótimo! Vamos conversar sobre nossos produtos e soluções. O que você procura?",
instruction=f"Contexto: skill de vendas ({current_skill.name})"
)
elif "financeiro" in skill_name_lower or "cobranca" in skill_name_lower:
return actions_sdk.ResponseToUser(
message="Estou aqui para questões financeiras e pagamentos. Como posso ajudar?",
instruction=f"Contexto: skill financeiro ({current_skill.name})"
)
else:
# Skill não reconhecida - comportamento genérico
return actions_sdk.ResponseToUser(
message=f"Você está sendo atendido por {current_skill.name}. Como posso ajudar?",
instruction=f"Skill atual: {current_skill.name}"
)
🌍 Horários e Fusos Horários
Formato de Horários
O sistema suporta dois formatos para horários de funcionamento:
# Formato antigo: array simples [abertura, fechamento]
opening_hours = {
"1": ["09:00:00.000Z", "18:00:00.000Z"] # Segunda-feira
}
# Formato novo: array de intervalos [[abertura, fechamento], [abertura2, fechamento2]]
opening_hours = {
"1": [
["09:00:00.000Z", "12:00:00.000Z"], # Manhã
["14:00:00.000Z", "18:00:00.000Z"] # Tarde
]
}
Dias da Semana
"0": Domingo"1": Segunda-feira"2": Terça-feira"3": Quarta-feira"4": Quinta-feira"5": Sexta-feira"6": Sábado
Fuso Horário
Todos os cálculos são feitos no fuso horário America/Sao_Paulo.
💡 Dicas de Uso
- Context hints específicos: Forneça contexto detalhado para melhor seleção
- Fallback sempre: Configure skill de fallback para casos não cobertos
- Verificar disponibilidade: Sempre chece se skills estão no horário antes de transferir
- Trace habilitado: Use trace para debugging da seleção
- LLM dependency: Seleção depende da qualidade do modelo LLM
- Timezone: Sistema usa fuso horário brasileiro (America/Sao_Paulo)
- Error handling: Sempre implemente tratamento de erro para falhas de seleção