Files
agent_contas/workflows/invoice_explanation.v2.yaml

227 lines
7.4 KiB
YAML

name: invoice_explanation
version: 2
start: preparar
nodes:
- id: preparar
action: preparar_invoice_explanation
input:
msisdn: $.input.msisdn
customer_id: $.input.customer_id
current_invoice_number: $.input.current_invoice_number
past_invoice_number: $.input.past_invoice_number
current_invoice_due_date: $.input.current_invoice_due_date
past_invoice_due_date: $.input.past_invoice_due_date
channel: $.input.channel
tentativa_anterior: $.vars.preparar.tentativa
invoice_explanation_base: $.input.invoice_explanation_base
- id: formatar
action: formatar_invoice_explanation
input:
explicacao_base: $.vars.preparar.explicacao_base
invoice_detail: $.input.invoice_detail
# A pausa faz parte do contrato do workflow, não da action de formatação.
# Depois de apresentar a explicação, sempre aguardamos SIM/NAO antes de
# entrar em `decisao`. A action `formatar_invoice_explanation` permanece
# responsável apenas por montar a mensagem.
pause:
enabled: true
return_from: $.output.mensagem
expected_input:
key: resposta_usuario
allowed_values: ["SIM", "NAO", "CONTINUAR"]
normalize: upper_strip
reprompt: "Não entendi. Essa explicação resolveu sua dúvida? Responda sim ou não."
semantic_classifier:
enabled: true
include_relevant_context: true
option_actions:
CONTINUAR:
action: contextual_reentry
prompt: |
Classifique a fala do cliente em exatamente UMA das opções de {{ allowed_values }}.
A pergunta pendente é:
{{ pending_prompt }}
Contexto conversacional relevante imediatamente anterior a esta decisão:
{{ relevant_conversation_context }}
A fala atual do cliente é:
{{ user_input }}
Para este workflow:
- SIM: use somente quando o cliente indicar entendimento, aceitação ou encerramento da dúvida,
sem introduzir nova pergunta, hipótese, valor, referência ou fato a validar.
- NAO: use quando o cliente responder negativamente à pergunta pendente ou disser de forma
explícita que a explicação não resolveu sua dúvida. Exemplos: "não", "de jeito nenhum",
"não resolveu", "ainda não entendi".
- CONTINUAR: use quando a fala for compreensível, mas não responder diretamente SIM ou NAO e,
considerando o contexto imediatamente anterior, complementar, especificar ou continuar a
solicitação que originou a pergunta pendente. Inclua novas perguntas, hipóteses, valores,
referências e fatos propostos pelo cliente que ainda precisem ser validados.
Exemplos:
- "sim", "legal", "ok", "beleza", "entendi", "obrigado" => SIM
- "não", "de jeito nenhum", "não resolveu", "ainda não entendi" => NAO
- contexto: "tem uma cobrança aqui que eu não reconheço"; fala: "é a de quatorze e noventa e nove" => CONTINUAR
- "então minha fatura ficaria R$ 275,00, certo?" => CONTINUAR
- "quer dizer que no próximo mês vou pagar menos?" => CONTINUAR
Regras de segurança:
- Nunca trate pergunta, hipótese, valor, referência ou fato proposto pelo cliente como concordância.
- CONTINUAR não confirma nem ratifica nenhum dado dito pelo cliente; apenas solicita reentrada
contextual para nova validação pelas fontes de negócio.
- Retorne somente uma das opções oferecidas em {{ allowed_values }}.
resume_from: decisao
- id: checar_tentativa
action: checar_tentativa_cvn
input:
tentativa: $.vars.preparar.tentativa
- id: texto_intencao_invalida
action: montar_resposta_texto
input:
dados:
texto_usuario: "Não consegui validar sua solicitação. Pode informar novamente sobre a sua fatura?"
- id: fim_intencao_invalida
action: montar_resposta_texto
input:
dados:
texto_usuario: "Não foi possível validar sua solicitação neste momento."
- id: resposta_falha_servico
action: montar_resposta_texto
input:
dados:
texto_usuario: "Para continuar com a sua solicitação, aguarde um instante."
- id: decisao
action: no_op
input: {}
- id: registrar_sim
action: registrar_atendimento_invoice_explanation
input:
resposta_usuario: SIM
- id: registrar_protocolo_aceite
action: registrar_protocolo_inicio
input:
msisdn: $.input.msisdn
scenario: invoice_explanation_aceite_fechado
request_status: Fechado
status: CLOSED
workflow_response_final: true
mensagem_final: "Seu número de protocolo é {protocol}."
- id: registrar_nao
action: registrar_atendimento_invoice_explanation
input:
resposta_usuario: NAO
# Política de jornada do agente Contas: uma negativa à pergunta de confirmação da
# explicação transfere o atendimento para continuidade humana. A primitive de
# HUMAN_HANDOFF é do framework; a decisão e a fraseologia ficam declaradas aqui.
- id: handoff_pos_explicacao_nao
action: preparar_handoff_invoice_explanation
input:
mensagem: "Para continuar com a sua solicitação, aguarde um instante."
reason: invoice_explanation_not_resolved
# A variação foi causada por VAS avulso ou estratégico? Sem VAS variado não há nada que
# o bot resolva, e insistir com o orquestrador só gasta turno (SPEC §9 "Explicação da variação recusada").
- id: checar_vas_variacao
action: checar_vas_variado
input:
invoice_variation: $.input.invoice_variation
invoice_detail: $.input.invoice_detail
# Nó só para nomear o last_node: o backend o mapeia para nao_resolvido em
# auto_finalize_status_map, e a fala vem do NAO_RESOLVIDO_CLOSING.
- id: finalizar_nao_resolvido
action: no_op
input: {}
edges:
- from: preparar
to: formatar
priority: 10
when:
eq: [$.vars.preparar.success, true]
- from: preparar
to: resposta_falha_servico
priority: 20
when:
eq: [$.vars.preparar.service_failed, true]
- from: preparar
to: checar_tentativa
priority: 30
when:
eq: [$.vars.preparar.success, false]
- from: checar_tentativa
to: fim_intencao_invalida
priority: 10
when:
eq: [$.vars.checar_tentativa.limite_excedido, true]
- from: checar_tentativa
to: texto_intencao_invalida
priority: 20
- from: formatar
to: decisao
- from: decisao
to: registrar_sim
priority: 10
when:
eq: [$.input.resposta_usuario, SIM]
- from: decisao
to: registrar_nao
priority: 20
when:
eq: [$.input.resposta_usuario, NAO]
- from: registrar_sim
to: registrar_protocolo_aceite
- from: registrar_protocolo_aceite
to: END
- from: registrar_nao
to: handoff_pos_explicacao_nao
- from: handoff_pos_explicacao_nao
to: END
- from: checar_vas_variacao
to: finalizar_nao_resolvido
priority: 10
when:
eq: [$.vars.checar_vas_variacao.tem_vas_variado, false]
# Tem VAS variado (ou não deu para saber): devolve ao orquestrador, como sempre.
- from: checar_vas_variacao
to: END
priority: 20
- from: finalizar_nao_resolvido
to: END
- from: texto_intencao_invalida
to: END
- from: fim_intencao_invalida
to: END
- from: resposta_falha_servico
to: END