Skill Selector
O SkillSelector seleciona automaticamente a skill externa mais adequada para o contexto da conversa usando o LLM. Use quando o agente tem múltiplas skills externas e precisa decidir para qual encaminhar o usuário.
Inicialização
from actions_sdk.core.types.action_context import ActionContext
from actions_sdk.features.conversational.skill_selector import SkillSelector
ctx: ActionContext
selector = SkillSelector(ctx)
# Com timezone para verificação de horário de atendimento
selector = SkillSelector(ctx, timezone="America/Sao_Paulo")
O SkillSelector extrai ctx.external_skills e ctx.messages automaticamente no construtor, e cria internamente um LLMClient.
Parâmetros do construtor:
| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
ctx | ActionContext | — | Contexto de execução |
timezone | str | "UTC" | Fuso horário para verificação de horário de atendimento das skills |
Métodos
select_best_skill()
Seleciona a skill mais adequada para o contexto da conversa usando LLM.
selector = SkillSelector(ctx)
skill_selecionada = selector.select_best_skill()
if skill_selecionada:
return ResponseToAgent(
status=ResponseStatus.SUCCESS,
instruction=f"Encaminhar o usuário para: {skill_selecionada.name}",
functions=[RedirectToSkill(
skill_name=skill_selecionada.name,
reason="Skill selecionada automaticamente.",
)],
)
Parâmetros:
| Parâmetro | Tipo | Descrição |
|---|---|---|
external_skills | list[ExternalSkillConfig] | None | Skills candidatas. Se None, usa as skills do construtor (ctx.external_skills) |
messages | list[Message] | None | Histórico da conversa. Se None, usa ctx.messages |
context_hint | str | None | Dica adicional de contexto para auxiliar a seleção |
fallback_skill | ExternalSkillConfig | None | Skill de último recurso se nenhuma outra se encaixar |
Retorna: ExternalSkillConfig | None
Se a seleção falhar (LLM indisponível, erro interno), retorna None silenciosamente — não lança exceção.
get_available_external_skills()
Lista as skills externas disponíveis no momento atual (respeitando horários de atendimento).
skills_disponiveis = selector.get_available_external_skills()
print([s.name for s in skills_disponiveis])
Retorna: list[ExternalSkillConfig]
ExternalSkillConfig
Estrutura que representa uma skill externa:
| Campo | Tipo | Descrição |
|---|---|---|
name | str | Nome da skill |
description | str | Descrição usada pelo LLM para seleção |
opening_hours | dict | None | Horários de atendimento por dia da semana |
opening_hours_exceptions | list | None | Exceções de horário |
Erros e Exceções
O SkillSelector é fail-safe: todos os erros internos são capturados e retornam None em vez de lançar exceções. Verifique sempre se o retorno de select_best_skill() é None antes de usar.
skill = selector.select_best_skill()
if skill is None:
return ResponseToAgent(
status=ResponseStatus.ERROR,
instruction="Não foi possível selecionar uma skill automaticamente.",
)
Exemplo completo
Baseado na action skill_selector_selecionar do agente de homologação:
import traceback
from actions_sdk.core.types.action_context import ActionContext
from actions_sdk.core.types.responses import (
RedirectToSkill,
ResponseStatus,
ResponseToAgent,
)
from actions_sdk.features.conversational.skill_selector import SkillSelector
from actions_sdk.features.conversational.state import StateManager
from actions_sdk.features.tracing import ActionSpan
ctx: ActionContext
CHAVE_PROGRESSO = "action.skill_selector.progresso"
def selecionar_skill():
span = ActionSpan(ctx)
state = StateManager(ctx)
span.event("action.skill_selector.inicio", {})
try:
selector = SkillSelector(ctx, timezone="America/Sao_Paulo")
skill = selector.select_best_skill(
context_hint="O usuário parece ter uma dúvida técnica.",
)
if skill is None:
state.update(CHAVE_PROGRESSO, "SEM_SKILL")
return ResponseToAgent(
status=ResponseStatus.ERROR,
instruction="Nenhuma skill adequada encontrada para o contexto atual.",
state_updates=state.get_full_state(),
)
state.update(CHAVE_PROGRESSO, "SUCESSO ✓")
span.event("action.skill_selector.sucesso", {"skill": skill.name})
return ResponseToAgent(
status=ResponseStatus.SUCCESS,
instruction=f"Skill selecionada: {skill.name}. Encaminhar o usuário.",
functions=[
RedirectToSkill(
skill_name=skill.name,
reason=f"Skill '{skill.name}' selecionada automaticamente por LLM.",
)
],
state_updates=state.get_full_state(),
)
except Exception as erro:
state.update(CHAVE_PROGRESSO, "ERRO ✗")
span.event("action.skill_selector.erro", {"erro": str(erro)})
return ResponseToAgent(
status=ResponseStatus.ERROR,
instruction=f"Falha no seletor de skill: {traceback.format_exc()}",
state_updates=state.get_full_state(),
)