Agent Loop - Outcomes Hardening (Production-Grade)
Visão Geral
Este documento descreve as melhorias implementadas para tornar o sistema de matching retrospectivo de outcomes production-grade e antifrágil.
Problema Original
O sistema de backfill original tinha limitações:
- ❌ Não registrava como o match foi feito (sem auditabilidade)
- ❌ Não tinha score de confiança (risco de falsos positivos)
- ❌ Não usava action_id como fallback (link mais forte)
- ❌ Não preenchia decision_log_id em tempo real
Solução Implementada
1️⃣ Metadados de Matching (Auditabilidade)
Campos adicionados:
- match_method: Método usado (ACTION_ID, ENTITY+POLICY+TIME, ENTITY+TIME, etc.)
- match_score: Score de confiança (0-100)
- matched_at: Quando o match foi feito
- matched_by: Quem/processo que fez o match
- match_debug_json: JSON com detalhes para debug
Benefícios:
- ✅ Explicabilidade: sabe-se exatamente como cada outcome foi vinculado
- ✅ Reversibilidade: pode-se identificar matches de baixa confiança
- ✅ Debug: JSON com todos os detalhes do matching
2️⃣ Score de Confiança
Sistema de pontuação:
- +60 pontos: Match por entidade (obrigatório)
- subject_type = entity_type
- subject_ref = entity_ref
- +25 pontos: Policy code aparece em decision_id (substring)
- decision_id LIKE '%policy_code%'
- +10 pontos: Policy code bate em subject_ref
- subject_ref = policy_code
- +5 pontos: Decisão muito próxima do action_taken_at (< 6 horas)
- TIMESTAMPDIFF(HOUR, decision_created_at, action_taken_at) <= 6
Limiar configurável:
- Padrão: 80 pontos (pode ser ajustado via parâmetro)
- Apenas matches com score >= limiar são aceitos
Benefícios:
- ✅ Reduz falsos positivos quando há múltiplas decisões
- ✅ Prioriza matches mais confiáveis
- ✅ Permite ajuste fino do limiar
3️⃣ Fallback por action_id
Estratégia:
1. Primeiro: Tenta match via action_id (score 100)
- Join direto com execution_action_ledger
- Link mais forte e confiável
2. Depois: Matching retrospectivo com scoring
- Usa os 3 critérios originais + scoring
Benefícios:
- ✅ Usa o link mais forte quando disponível
- ✅ Fallback automático quando action_id não está disponível
- ✅ Zero refatoração necessária
4️⃣ Preenchimento em Tempo Real
Nova procedure: sp_ctx_record_outcome
Recebe decision_log_id e action_id como parâmetros e preenche automaticamente:
- Metadados de matching (match_method, match_score, etc.)
- Links diretos (decision_log_id, action_id)
Benefícios:
- ✅ Zero backfill necessário para novos outcomes
- ✅ Links diretos desde a criação
- ✅ Score 100 garantido quando parâmetros são fornecidos
Estrutura de Dados
Tabela ctx_policy_outcomes (campos adicionados)
ALTER TABLE csuite_context.ctx_policy_outcomes
ADD COLUMN match_method VARCHAR(40) NULL,
ADD COLUMN match_score INT NULL,
ADD COLUMN matched_at DATETIME NULL,
ADD COLUMN matched_by VARCHAR(80) NULL,
ADD COLUMN match_debug_json JSON NULL,
ADD COLUMN action_id BIGINT UNSIGNED NULL;
Procedures
sp_ctx_backfill_outcome_decision_log_id_v2
Versão melhorada do backfill com:
- Scoring de confiança
- Fallback por action_id
- Metadados de matching
- Estatísticas detalhadas
Parâmetros:
- p_org_id: ID da organização (0 = todas)
- p_days_back: Quantos dias para trás processar
- p_limit: Limite de outcomes a processar
- p_min_score: Score mínimo para aceitar match (padrão: 80)
Retorna:
- outcomes_updated: Quantos foram atualizados
- total_outcomes_without_decision_log_id: Quantos ainda faltam
- matched_via_action_id: Quantos foram matchados via action_id
- matched_via_retrospective: Quantos foram matchados via matching retrospectivo
- avg_match_score: Score médio dos matches
sp_ctx_record_outcome
Cria outcome com links diretos em tempo real.
Parâmetros principais:
- p_org_id, p_policy_code, p_entity_type, p_entity_ref
- p_action_taken, p_action_taken_at
- p_decision_log_id (opcional, mas recomendado)
- p_action_id (opcional, mas recomendado)
- p_created_by
Preenche automaticamente:
- match_method: 'ACTION_ID' ou 'DIRECT' (score 100)
- match_score: 100 quando links disponíveis
- matched_at, matched_by
Views
vw_outcomes_matching_stats
Estatísticas agregadas por método de matching:
- Total de outcomes
- Score médio, mínimo, máximo
- Quantos estão matched vs unmatched
API
POST /api/executive/dashboard/backfill-outcomes
Parâmetros:
- org_id: ID da organização (0 = todas)
- days_back: Quantos dias para trás processar (padrão: 30)
- limit: Limite de outcomes a processar (padrão: 1000)
- min_score: Score mínimo para aceitar match (padrão: 80)
- use_v2: Usar versão v2 com scoring (padrão: True)
Resposta (v2):
{
"status": "success",
"data": {
"outcomes_updated": 150,
"total_outcomes_without_decision_log_id": 50,
"matched_via_action_id": 100,
"matched_via_retrospective": 50,
"avg_match_score": 92.5
},
"timestamp": "2024-01-15T10:30:00"
}
Uso Recomendado
1. Para Novos Outcomes (Tempo Real)
No código da aplicação:
# Após executar ação e ter decision_log_id e action_id
cursor.execute("""
CALL csuite_context.sp_ctx_record_outcome(
:org_id,
:policy_code,
:entity_type,
:entity_ref,
:entity_name,
:action_taken,
NOW(),
:expected_outcome,
:metric_before,
30,
:decision_log_id, -- ✅ Link direto
:action_id, -- ✅ Link direto
'application'
)
""", {
"org_id": org_id,
"policy_code": policy_code,
"entity_type": entity_type,
"entity_ref": entity_ref,
"action_taken": action_taken,
"decision_log_id": decision_log_id,
"action_id": action_id,
# ... outros parâmetros
})
2. Para Backfill Histórico
Via API:
curl -X POST "http://localhost:8000/api/executive/dashboard/backfill-outcomes?org_id=0&days_back=30&limit=1000&min_score=80&use_v2=true"
Via SQL:
CALL csuite_context.sp_ctx_backfill_outcome_decision_log_id_v2(0, 30, 1000, 80);
3. Monitoramento
Ver estatísticas:
SELECT * FROM csuite_context.vw_outcomes_matching_stats;
Ver outcomes com baixo score:
SELECT
outcome_id,
policy_code,
entity_type,
entity_ref,
match_method,
match_score,
match_debug_json
FROM csuite_context.ctx_policy_outcomes
WHERE match_score < 80
AND match_score IS NOT NULL
ORDER BY match_score ASC;
Melhorias Futuras
- Machine Learning para Scoring
- Treinar modelo baseado em matches confirmados
-
Ajustar pesos dinamicamente
-
Matching Multi-Pass
- Tentar múltiplas estratégias em ordem de confiança
-
Combinar resultados quando houver ambiguidade
-
Feedback Loop
- Permitir correção manual de matches
-
Usar feedback para melhorar scoring
-
Alertas Automáticos
- Alertar quando muitos outcomes têm score baixo
- Sugerir revisão manual
Conclusão
Com essas melhorias, o sistema de matching de outcomes é:
- ✅ Auditável: Sabe-se como cada match foi feito
- ✅ Confiável: Score de confiança reduz falsos positivos
- ✅ Robusto: Fallback por action_id quando disponível
- ✅ Eficiente: Preenchimento em tempo real elimina necessidade de backfill futuro