Pular para o conteúdo principal
Chain-of-Verification (Dhuliawala et al., 2023) é a técnica canônica para reduzir hallucination em outputs LLM. O fluxo: produzir resposta → gerar perguntas de verificação sobre as claims → responder cada pergunta independentemente (sem ver a resposta original) → reconciliar discrepâncias. O ChatCLI implementa via VerifierAgent (pure reasoning, zero tools) + VerifyHook (PostHook do pipeline). Quando discrepância é detectada, o flag verified_with_discrepancy é gravado em result.Metadata, ativando o Reflexion downstream.
CoVe é opt-in. Com CHATCLI_QUALITY_VERIFY_ENABLED=false (default), zero overhead. Quando ligado, adiciona +1 chamada LLM por ponto de uso com effort alto (default effort="high").

Protocolo do VerifierAgent

O modelo recebe TASK + DRAFT e emite cinco blocos:
<status>verified-clean OR verified-with-corrections</status>

<questions>
- Q1: claim específica 1 verificável
- Q2: claim específica 2 verificável
- Q3: claim específica 3 verificável
</questions>

<answers>
- A1: resposta independente a Q1 (sem olhar DRAFT)
- A2: resposta independente a Q2
- A3: resposta independente a Q3
</answers>

<discrepancies>
- descrição da discrepância, OU "none"
</discrepancies>

<final>
…resposta pronta para entregar ao usuário (repete DRAFT se verified-clean,
ou reescreve se verified-with-corrections)…
</final>

Regra crítica: respostas INDEPENDENTES

O protocolo instrui o modelo a responder cada Q<n> sem referenciar o DRAFT. Isso é o coração de CoVe — se as respostas independentes contradizem o draft, há claim suspeito.
Modelos que simplesmente regurgitam o draft nas respostas defeat o padrão. O system prompt enfatiza isso explicitamente; use modelos capazes de “self-distance” (Claude Sonnet, GPT-4+).

Fluxo do VerifyHook

1

Worker termina

Qualquer agente produz result.Output.
2

PostRun do VerifyHook

if result.Error != nil { return }
if !cfg.Verify.Enabled { return }
if !AppliesToAgent(agent, cfg.ExcludeAgents) { return }
if result.Output == "" { return }
3

Dispatch VerifierAgent

body := VerifyDirective + fmt.Sprintf(" [NUM_QUESTIONS=%d]\n", numQ) +
        "Task:\n" + task + "\n\n" +
        "Draft:\n" + result.Output
res := dispatch(ctx, AgentCall{Agent: verifier, Task: body})
4

ParseVerifierOutput

Extrai os 5 blocos. Tolerante a ordem, bullets com - ou *.
5

HasDiscrepancy check

Status=="verified-with-corrections" OU Discrepancies!="none".
6

Se discrepância + RewriteOnDiscrepancy

result.SetMetadata("verified_with_discrepancy", "true")
result.SetMetadata("verifier_discrepancies", parsed.Discrepancies)
if cfg.RewriteOnDiscrepancy {
    result.Output = parsed.Final
}
7

Reflexion consome o flag

Na mesma execução do pipeline, ReflexionHook.PostRun vê o metadata e, se OnHallucination=true, dispara lesson generation.

Exclude list (anti-recursão + agents não-textuais)

ExcludeAgents: []string{"formatter", "deps", "shell", "refiner", "verifier"}
AgenteRazão
formatterOutput é código formatado, não claims
depsOutput é lista determinística de pacotes
shellOutput é stdout/stderr, não claims verificáveis
refinerOutput já passou por crítica; verify seria redundante
verifierAnti-recursão — verificar o verifier criaria loop

/verify — session toggle

/verify on

Variáveis de ambiente

Env varDefaultO que faz
CHATCLI_QUALITY_VERIFY_ENABLEDfalseMaster switch
CHATCLI_QUALITY_VERIFY_NUM_QUESTIONS3Quantas perguntas de verificação
CHATCLI_QUALITY_VERIFY_REWRITEtrueReescrever output em discrepância
CHATCLI_QUALITY_VERIFY_EXCLUDEformatter,deps,shell,refiner,verifierCSV de exclusões

Override do verifier

# Use modelo mais forte só para verify
export CHATCLI_AGENT_VERIFIER_MODEL="claude-opus-4-7"
export CHATCLI_AGENT_VERIFIER_EFFORT="max"

# Ou mais questions para workflows críticos
export CHATCLI_QUALITY_VERIFY_NUM_QUESTIONS=5

Exemplo: catching hallucination sobre API

O http.Client do Go tem um campo DefaultTimeout que você pode setar globalmente. Basta fazer http.DefaultClient.DefaultTimeout = 30 * time.Second no init do programa.
Erro: DefaultTimeout não existe. É Timeout (e não há “DefaultTimeout” na stdlib).
Flag gravado em result.Metadata["verified_with_discrepancy"]=true. Se Reflexion está on (default), uma lesson é gerada em background:
LESSON: Citing Go stdlib API fields
MISTAKE: Invented "DefaultTimeout" field on http.Client
CORRECTION: Verify symbol exists via go doc or grep before citing
TRIGGER: hallucination

Integração com Refine

Quando Refine + Verify estão ambos ligados, a ordem importa:
// cli/agent/quality/builder.go
if cfg.Refine.Enabled && deps.Dispatch != nil {
    p.AddPost(NewRefineHook(...))      // primeiro
}
if cfg.Verify.Enabled && deps.Dispatch != nil {
    p.AddPost(NewVerifyHook(...))      // depois do refine
}
Refine melhora a qualidade estilística primeiro; Verify checa factual accuracy sobre o output já refinado. Ordem oposta (verify → refine) funcionaria, mas a reescrita do refine poderia introduzir claims não verificados.
Se você só liga um dos dois, prefira Verify para workflows factual (docs técnicas, código com API calls) e Refine para workflows estilísticos (summaries, relatórios).

Invocação direta

<agent_call agent="verifier" task="[VERIFY_ANSWER] Task: X Draft: Y" />
Ou com tool call direta ao verifier na orquestração de passos críticos:
# Chain: search → coder → verifier before user sees

Custo e latência

ConfigCalls extrasLatência
NumQuestions=3 (default)+1 verifier call3-8s com Sonnet
NumQuestions=5+1 (mesmo call, mais questions)5-12s
NumQuestions=7++1 + modelo pode quebrar contratoEvitar
CoVe com modelos fracos gera perguntas superficiais ou “verificações” que só parafraseiam o draft. Use Sonnet, Opus, ou GPT-4+ como CHATCLI_AGENT_VERIFIER_MODEL.

Leia também

#3 Reflexion

Consome o signal verified_with_discrepancy para gerar lessons sobre hallucination.

#5 Self-Refine

Complemento estilístico: Refine poliaça, CoVe verifica factualmente.

Paper original (Dhuliawala et al.)

Chain-of-Verification Reduces Hallucination in Large Language Models

Configuração

Env vars e slashes num lugar só.