11 KiB
Relatório técnico — políticas alternativas de operação por linha
1. Objetivo
O Agent Contas possui duas políticas alternativas para controlar operações em uma linha (MSISDN) diferente da linha identificada/autenticada no início do atendimento.
A implementação permanece no Agent Contas/MCP Contas, sem regra TIM hardcoded no core do agent_framework_oci.
A política ativa entregue no projeto continua sendo a ALT1 — somente a linha autenticada.
A ALT2 foi evoluída para não inferir autorização a partir de fatura, billing ou texto do cliente. Ela depende de uma fonte explícita de autorização: a nova tool MCP mock consultar_linhas_autorizadas.
2. Políticas disponíveis
2.1 ALT1 — authenticated_line_only — PADRÃO
Fonte:
contas_mcp/servers/contas_mcp_server/line_policy_alt1.py
Comportamento:
- a linha operacional continua sendo a linha identificada pelo
business_contextda chamada; - uma linha citada em texto livre não substitui a identidade da sessão;
- se o cliente mencionar explicitamente outra linha — número completo ou referência como
final 4321— a execução é bloqueada antes de qualquer operação de domínio; - o bloqueio é terminal para o turno e interrompe as tools seguintes;
- a mensagem devolvida é:
Por segurança, este atendimento só permite consultar ou realizar operações na linha identificada na chamada. Não posso usar outra linha informada na conversa.
Exemplo:
linha autenticada: 11999999999
cliente: "quero cancelar o streaming do número da minha esposa, final quatro três dois um"
resultado:
LINE_POLICY_BLOCKED / other_line_not_allowed
nenhuma consulta/cancelamento é executado para a outra linha
2.2 ALT2 — authorized_related_lines
Fonte:
contas_mcp/servers/contas_mcp_server/line_policy_alt2.py
Comportamento:
- a linha autenticada continua sendo a origem de confiança;
- uma outra linha só pode ser usada se for retornada pelo serviço explícito
consultar_linhas_autorizadas; - referências como
final 4321são resolvidas somente contra as linhas autorizadas retornadas por esse serviço; - se houver exatamente uma correspondência, ela vira o
effective_msisdnda operação; - se não houver correspondência, a operação é bloqueada;
- se houver mais de uma correspondência, o fluxo exige esclarecimento;
- se o serviço de linhas autorizadas falhar, o ALT2 opera em fail-closed: somente a linha autenticada permanece autorizada;
- a presença de um MSISDN em
invoice_detail,billing_analysisou outra evidência de cobrança não concede autorização operacional; - um número pronunciado pelo cliente também não concede autorização.
Exemplo:
linha autenticada: 11999999999
consultar_linhas_autorizadas retorna:
- 11999999999 (titular)
- 11988884321 (dependente autorizado)
cliente: "quero cancelar o TIM Fashion da linha final 4321"
resultado ALT2:
requested reference = 4321
effective_msisdn = 11988884321
operação pode prosseguir nessa linha
3. Novo serviço MCP mock — consultar_linhas_autorizadas
3.1 Objetivo
Foi criada uma tool MCP side-effect-free para representar a integração que, em produção, deve consultar um serviço de identidade/conta e responder quais linhas o atendimento autenticado está autorizado a operar.
Tool:
consultar_linhas_autorizadas
Registro MCP:
contas_mcp/servers/contas_mcp_server/main.py
Implementação mock:
contas_mcp/servers/contas_mcp_server/authorized_lines_service.py
Fixture mock:
app/domain/contas/fixtures/authorized_lines.json
3.2 Contrato de entrada
A consulta parte da identidade já autenticada no atendimento. O cliente não informa qual linha deve ser autorizada.
Exemplo:
{
"msisdn": "11999999999",
"customer_key": "11999999999",
"contract_key": "3000131180"
}
O msisdn acima é a linha autenticada/original da chamada.
3.3 Contrato de saída mock
{
"success": true,
"status": "SUCCESS",
"source": "mock",
"authenticated_msisdn": "11999999999",
"authorized_lines": [
{
"msisdn": "11999999999",
"relationship": "titular",
"status": "ACTIVE",
"authorized": true
},
{
"msisdn": "11988884321",
"relationship": "dependente",
"status": "ACTIVE",
"authorized": true
}
],
"authorized_msisdns": [
"11999999999",
"11988884321"
]
}
3.4 Por que existe uma tool MCP separada
O objetivo é deixar explícita a arquitetura de produção:
identidade autenticada da chamada
↓
consultar_linhas_autorizadas
↓
serviço legado/CRM/IAM/conta
↓
lista de linhas realmente autorizadas
↓
line_policy_alt2
↓
resolve referência conversacional
↓
0 matches → bloqueia/clarifica
1 match → effective_msisdn
>1 matches → clarifica
A autorização não pertence ao LLM. O LLM/text extractor pode interpretar final 4321, mas não decide se 4321 é uma linha autorizada.
3.5 Comportamento em produção
O arquivo authorized_lines_service.py é propositalmente um mock de referência. Em produção, ele deve ser substituído por um adapter que consulte o serviço corporativo responsável pela relação titular/dependentes/linhas autorizadas.
O contrato recomendado deve preservar pelo menos:
success
authenticated_msisdn
authorized_lines[].msisdn
authorized_lines[].status
authorized_lines[].authorized
authorized_lines[].relationship
authorized_msisdns
Se a integração real falhar ou não puder provar a autorização da outra linha, o comportamento esperado do ALT2 é fail-closed.
4. Fluxo ALT2 atualizado
O fluxo completo ficou:
mensagem do cliente
↓
extrai requested_line_reference
ex.: suffix=4321
↓
business_context mantém 11999999999
↓
MCP detecta ALT2 ativo
↓
consultar_linhas_autorizadas(11999999999)
↓
authorized_lines_evidence
↓
line_policy_alt2
↓
resolve 4321 somente contra authorized_lines_evidence
↓
effective_msisdn = 11988884321
↓
só então a tool/workflow de negócio é executada
A ALT2 não usa mais invoice_detail, billing_analysis ou complete_invoices_payload como fonte de autorização de linha.
5. Política ativa
O MCP importa sempre:
contas_mcp/servers/contas_mcp_server/line_policy.py
No pacote entregue, line_policy.py é uma cópia exata de line_policy_alt1.py.
Portanto, o comportamento corrente permanece bloqueando operações em outra linha.
O /health informa a política carregada:
{
"line_policy": "authenticated_line_only",
"line_policy_description": "Somente a linha identificada/autenticada na chamada pode ser consultada ou alterada."
}
6. Como ativar ALT1
Forma recomendada:
python scripts/select_line_policy.py alt1
Depois reinicie o backend/MCP Server.
Linux/macOS:
cp contas_mcp/servers/contas_mcp_server/line_policy_alt1.py \
contas_mcp/servers/contas_mcp_server/line_policy.py
PowerShell:
Copy-Item `
contas_mcp/servers/contas_mcp_server/line_policy_alt1.py `
contas_mcp/servers/contas_mcp_server/line_policy.py -Force
7. Como ativar ALT2
python scripts/select_line_policy.py alt2
Depois reinicie o backend/MCP Server.
Ao iniciar com ALT2, o MCP passa a consultar automaticamente consultar_linhas_autorizadas quando houver uma referência explícita a linha no turno.
Não é necessário inserir manualmente:
context["authorized_msisdns"] = [...]
nem:
args["authorized_msisdns"] = [...]
A lista vem do serviço MCP de autorização.
8. Como alterar o mock para testes
Para ilustrar outra linha autorizada, edite apenas:
app/domain/contas/fixtures/authorized_lines.json
Exemplo:
{
"msisdn": "11977771234",
"relationship": "dependente",
"status": "ACTIVE",
"authorized": true
}
Não altere line_policy_alt2.py para cadastrar linhas.
Esse desenho deixa claro que a política apenas consome autorização; ela não é o cadastro das linhas autorizadas.
9. Abrangência
A política é aplicada no ponto único _invoke() do MCP Contas antes da execução de domínio. Dessa forma cobre as tools/serviços baseados em MSISDN, inclusive quando passam por workflows.
Cobertura funcional inclui:
consultar_faturasconsultar_planoinvoice_explanationconsultar_vasconsultar_historico_vascancelar_vas_avulsotratar_vas_estrategicovalidar_vas_subjectvalidar_contestacaocontestar_cobrancapro_ratatermino_descontovalor_divergenteconsultar_status_solicitacaoenviar_smsrecuperar_fatura_pdffinalizar_atendimento
consultar_linhas_autorizadas é a fonte de autorização da ALT2 e não passa pela própria política para evitar dependência circular.
buscar_informacao não depende de linha e retomar_workflow apenas retoma execução já iniciada.
10. Arquivos alterados/criados
Política de linha
contas_mcp/servers/contas_mcp_server/line_policy.py
contas_mcp/servers/contas_mcp_server/line_policy_alt1.py
contas_mcp/servers/contas_mcp_server/line_policy_alt2.py
Novo serviço MCP de autorização
contas_mcp/servers/contas_mcp_server/authorized_lines_service.py
app/domain/contas/fixtures/authorized_lines.json
contas_mcp/servers/contas_mcp_server/main.py
Referência conversacional e seleção da política
app/domain/contas/line_reference.py
scripts/select_line_policy.py
Testes e documentação
tests/migration/test_line_policy_alternatives.py
docs/RELATORIO_POLITICAS_DE_LINHA_ALT1_ALT2.md
11. Validação
Testes específicos da política e do novo mock:
12 passed
Smoke ALT2:
policy = authorized_related_lines
authorized = [11999999999, 11988884321]
requested = final 4321
allowed = true
effective = 11988884321
Após o smoke, ALT1 foi restaurado e validado como política ativa entregue.
Suíte completa de migração com ALT1 ativa:
765 passed
12. Decisão arquitetural
Responsabilidades finais:
| Camada | Responsabilidade |
|---|---|
| Framework | identidade/contexto, execução genérica, terminalidade e short-circuit de tools |
| Agent/MCP Contas | política ALT1/ALT2 e integração de autorização |
consultar_linhas_autorizadas |
informar quais linhas a identidade autenticada está autorizada a operar |
| Backend real futuro | fonte de verdade de titular/dependentes/autorização |
| LLM | interpretar a referência conversacional; nunca conceder autorização |
A principal regra arquitetural é:
linha mencionada ≠ linha autorizada
A autorização precisa vir de uma fonte explícita e confiável. Na versão demonstrativa essa fonte é o mock MCP consultar_linhas_autorizadas; em produção, deve ser substituída pela integração corporativa correspondente.