new feature: mcp pre-validation

This commit is contained in:
2026-08-20 15:13:20 -03:00
parent 6e43cc0158
commit 57df723a24
86 changed files with 9180 additions and 0 deletions

View File

@@ -0,0 +1,166 @@
# Transaction Pre-Validation / Pré-validação Transacional
Esta variante demonstra a capability genérica de **pré-validação MCP antes da confirmação**.
A regra de negócio continua no MCP. O framework apenas orquestra o contrato genérico:
```text
parâmetros completos
MCP validator (read-only / side-effect-free)
eligible?
├─ false → OUT_OF_SCOPE / NOT_ELIGIBLE → responde sem pedir confirmação
└─ true → AWAITING_CONFIRMATION → usuário confirma → tool transacional executa
```
Nenhum LLM adicional é usado pela pré-validação.
## Por que existe
Sem pre-validation, uma aplicação pode pedir confirmação para uma operação que o domínio já
sabe que é inválida. Exemplo: tentar cancelar um pedido já entregue ou contestar uma categoria
que não é elegível para contestação.
O framework **não contém essas regras de negócio**. Ele apenas consulta uma tool MCP declarada
na policy e interpreta o campo genérico `eligible`.
## Policy
`config/tool_policies.yaml`:
```yaml
tool_policies:
cancelar_pedido:
operation_type: transactional
require_confirmation: true
requires: [order_id]
pre_validation:
enabled: true
tool: validar_cancelamento_pedido
fail_open: false
```
A tool `validar_cancelamento_pedido` é read-only/internal e deve ser side-effect-free.
## Contrato MCP esperado
Elegível:
```json
{
"eligible": true,
"status": "ELIGIBLE",
"order_id": "PED-1001"
}
```
Não elegível:
```json
{
"eligible": false,
"status": "NOT_ELIGIBLE",
"order_id": "PED-ENTREGUE",
"reason": "Pedido já entregue não pode ser cancelado por esta operação."
}
```
## Cenário de teste
Suba o Retail MCP de exemplo:
```bash
cd agent_framework_oci/mcp/servers/retail_mcp_server
uvicorn main:app --host 0.0.0.0 --port 8200
```
Em outro terminal:
```bash
cd agent_framework_oci/Tuning-Performance/Transaction_Pre_Validation/agent_template_backend
pip install -e ../../../libs/agent_framework
pip install -r requirements.txt
python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
```
### Caso elegível
```text
quero cancelar o pedido PED-1001
```
Esperado:
```text
validar_cancelamento_pedido(PED-1001)
→ eligible=true
→ AWAITING_CONFIRMATION
→ nenhuma execução de cancelar_pedido ainda
```
Após `sim`, `cancelar_pedido` é executada.
### Caso não elegível
```text
quero cancelar o pedido PED-ENTREGUE
```
Esperado:
```text
validar_cancelamento_pedido(PED-ENTREGUE)
→ eligible=false
→ OUT_OF_SCOPE
→ NÃO entra em AWAITING_CONFIRMATION
→ cancelar_pedido NÃO é executada
```
## Telemetria
Procure pelos eventos:
- `IC.TRANSACTION_PREVALIDATION_REQUESTED`
- `IC.TRANSACTION_PREVALIDATION_PASSED`
- `IC.TRANSACTION_PREVALIDATION_REJECTED`
- `IC.TRANSACTION_CONFIRMATION_REQUIRED` somente após pre-validation aprovada.
No estado/metadata, `transaction_pre_validation` registra o validator utilizado e o resultado.
## Fail-open x fail-closed
`fail_open: false` é o padrão recomendado para operações sensíveis: se o validator estiver
indisponível, a transação não avança para confirmação.
`fail_open: true` deve ser usado apenas quando o domínio aceitar explicitamente prosseguir sem
a pré-validação.
## Separação de responsabilidades
**Framework**: ordem das etapas, estado, confirmação, idempotência e telemetria.
**MCP/domínio**: regra de elegibilidade, consulta aos sistemas de registro e motivo da rejeição.
A capability é genérica: pode ser usada para cancelamento, contestação, devolução, troca,
suspensão ou qualquer outra operação transacional que possua uma precondição de domínio.
## Rejeição encerra o estado transacional
Quando o validator retorna `eligible: false`, o framework encerra imediatamente o latch transacional. Isso significa que `selected_tool_call`, `pending_tool_call` e `missing_parameters` são limpos, `confirmation_required=false`, `next_state=null` e `transaction_status=OUT_OF_SCOPE`.
O resultado da pré-validação também é propagado no estado/metadata como `transaction_pre_validation`, por exemplo:
```json
{
"transaction_pre_validation": {
"tool_name": "contestar_cobranca",
"validator_tool": "validar_contestacao",
"eligible": false,
"status": "OUT_OF_SCOPE",
"terminal": true
}
}
```
Assim, o turno seguinte volta ao roteamento normal e não permanece preso em `COLLECTING_*` ou `WAITING_*`. A rejeição não vira `transaction_evidence`, pois a operação de negócio não foi executada.