Pular para o conteúdo principal
Self-Refine transforma a saída bruta de qualquer worker em versão polida via um ciclo deliberado de crítica → reescrita. O RefinerAgent é um worker pure-reasoning (zero tool access) que opera apenas sobre texto, e pode ser invocado diretamente pelo orquestrador ou automaticamente pelo RefineHook como post-processamento.
Self-Refine é opt-in. Com CHATCLI_QUALITY_REFINE_ENABLED=false (default), o RefineHook não é adicionado ao pipeline e zero overhead é introduzido.

Protocolo do RefinerAgent

O modelo recebe TASK + DRAFT e emite dois blocos XML-ish:
<critique>
- Bullet 1: logical gap identificado
- Bullet 2: vagueness ou falta de exemplos
- Bullet 3: claim não suportado
</critique>

<revised>
…versão reescrita, endereçando cada bullet da crítica,
pronta para ir ao usuário…
</revised>
Regras no system prompt:
  • Output APENAS os dois blocos — nada antes, nada depois.
  • Se o draft já está excelente, <revised> repete verbatim e <critique> diz “no material issues”.
  • Nunca inventa novos requisitos fora da TASK.
  • Mantém o mesmo formato do draft (código → código, prosa → prosa).
O parser tolerante: se o modelo violar o protocolo, RefinerAgent.Execute retorna o response inteiro como output — Reflexion picks up a violação como sinal de baixa qualidade.

Fluxo do RefineHook

1

Worker termina

Um agente qualquer (CoderAgent, FileAgent, …) produz result.Output.
2

PostRun do RefineHook é invocado

if result.Error != nil { return }  // erros vão para Reflexion, não Refine
if !cfg.Refine.Enabled { return }
if !AppliesToAgent(agent, cfg.ExcludeAgents) { return }
if len(draft) < cfg.MinDraftBytes { return }  // skip outputs curtos
3

Multi-pass loop

Para cada pass até MaxPasses:
  • Dispatch workers.AgentCall{Agent: refiner, Task: RefineDirective + "Task: ...\n\nDraft: ..."}
  • Recebe res.Output com o conteúdo de <revised>
  • Se convergedRefine(currentDraft, res.Output, EpsilonChars) → break
4

Substitui result.Output

result.Output = currentDraft (só se houve mudança).

Convergência

convergedRefine é um check barato que detecta quando duas revisões consecutivas são “praticamente iguais”:
func convergedRefine(a, b string, epsilon int) bool {
    if abs(len(a) - len(b)) > epsilon { return false }
    mismatches := 0
    for i := 0; i < min(len(a), len(b)); i++ {
        if a[i] != b[i] {
            mismatches++
            if mismatches > epsilon { return false }
        }
    }
    return true
}
Com EpsilonChars=50 (default), o loop para quando duas passadas diferem por menos de 50 caracteres — sinal claro de estabilização. Isso evita gastar tokens iterando em um output que o modelo já considera pronto.

Exclude lists (anti-recursão e agents mecânicos)

O default ExcludeAgents:
ExcludeAgents: []string{"formatter", "deps", "refiner", "verifier"}
AgenteRazão
formatterOutput mecânico (arquivo formatado), refinar não agrega
depsOutput é interpretação determinística de go list, npm ls, etc.
refinerAnti-recursão: refinar a saída do refiner criaria loop infinito
verifierMesma razão — verifier já entrega output polido
Adicione mais via env:
export CHATCLI_QUALITY_REFINE_EXCLUDE="formatter,deps,refiner,verifier,shell,git"

/refine — session toggle

Em vez de editar env vars e reiniciar, use o slash:
/refine on
# → self-refine ON for this session
O override de sessão mora em cli.qualityOverrides.Refine como *bool:
  • nil → defer ao /config quality
  • &true → força on
  • &false → força off
É aplicado em cima do env no momento que AgentMode.Run() constrói seu qualityConfig.

Variáveis de ambiente

Env varDefaultO que faz
CHATCLI_QUALITY_REFINE_ENABLEDfalseMaster switch
CHATCLI_QUALITY_REFINE_MAX_PASSES1Hard cap de passes (recomendo 1-2)
CHATCLI_QUALITY_REFINE_MIN_BYTES200Não refina outputs menores
CHATCLI_QUALITY_REFINE_EPSILON50Threshold de convergência em chars
CHATCLI_QUALITY_REFINE_EXCLUDEformatter,deps,refiner,verifierCSV de agents que NÃO são refinados

Override do refiner agent

O RefinerAgent tem defaults de model="" e effort="medium". Override:
# Use Haiku para refine barato
export CHATCLI_AGENT_REFINER_MODEL="claude-haiku-4-5"
export CHATCLI_AGENT_REFINER_EFFORT="low"

# Ou gpt-5 com high effort para máxima qualidade
export CHATCLI_AGENT_REFINER_MODEL="gpt-5"
export CHATCLI_AGENT_REFINER_EFFORT="high"

Exemplo: refine em resposta de documentação

# HTTP Client

The HTTP client is used for making requests. You can use it with various providers.

## Usage

Just call the Do method with a request and you get a response back.
Score qualitativo: vago, sem exemplo, “just” dismissivo.

Invocação direta pelo orquestrador

Além do hook automático, o orquestrador pode chamar o refiner via <agent_call>:
<agent_call agent="refiner" task="Polish this draft doc section: [paste draft here]" />
Útil quando:
  • Você quer refinar uma saída específica sem ligar o hook global.
  • A tarefa em si é “melhorar este texto”.
  • Chains complexas: coder escreve → reviewer analisa → refiner poliaça a análise antes de entregar.

Custo e latência

ConfigCalls LLM extras por turnLatência típica
MaxPasses=1 (default)+11-3s com Haiku, 3-8s com Sonnet
MaxPasses=2+1 a +2 (converge pode parar em 1)até 2x
MaxPasses=3+Raramente converge → gastoEvitar
Refine brilha em tarefas de escrita: documentação, summaries, relatórios. É menos útil em tool-heavy workflows (shell, git, file) porque outputs já são mecânicos.

Leia também

#6 CoVe

Chain-of-Verification complementa refine com checagem factual.

#3 Reflexion

Se refine flagga low-quality em múltiplos turns, Reflexion persiste a lição.

ReviewerAgent

Agent pré-pipeline que faz code review. Refiner é complementar: um analisa, o outro reescreve.

Configuração

Todos os CHATCLI_QUALITY_REFINE_* num lugar só.