Skip to main content
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:
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

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 — cascade semântico

O Self-Refine usa um cascade char → Jaccard → embedding pra decidir quando parar. O heurístico char-level antigo (convergedCharHeuristic, ainda fallback) só pegava igualdade literal; o cascade pega mesmo significado em palavras diferentes, que é o caso real da maioria dos rewrites.

Os três scorers

Quality regression guard

Além de detectar convergência, o hook compara cada nova revisão contra o draft original. Se a similaridade começa a cair entre passes (rewrite está drift-ando pra pior), reverte ao melhor draft visto e marca refine_rolled_back=true no metadata — sinal que Reflexion consome:
Isso previne o modelo de iterar até uma resposta pior quando a crítica superinterpreta.

Cache LRU com TTL

Embedding é caro ($). O cascade cacheia vetores por sha256(text) numa LRU bounded (default 256 entries, 5min TTL) — durante um loop multi-pass, a mesma string aparece em comparações consecutivas e o hit evita chamada duplicada.

Circuit breaker por scorer

Se o embedder retorna 3 erros consecutivos (provider 429/503/timeout), o breaker abre por 30s — o cascade degrada graciosamente pro Jaccard com DegradedFrom="embedding_unavailable" no Score. Zero stall no refine.

Modo strict vs permissive

Strict é pra workloads de alta-stakes (contratos legais, código de segurança) onde false-positive convergence = ship output não-polido.

Fallback legado

Quando nenhum checker é wirado (ou CONVERGENCE_ENABLED=false), cai no heurístico char-level original:
Com EpsilonChars=50 (default), para quando duas passadas diferem por menos de 50 caracteres. Barato mas cego a paráfrase — por isso o cascade é o default enterprise.

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

O default ExcludeAgents:
Adicione mais via env:

/refine — session toggle

Em vez de editar env vars e reiniciar, use o slash:
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

Básicos

Cascade semântico de convergência

Pra habilitar o embedding: CHATCLI_QUALITY_REFINE_CONVERGENCE_EMBEDDING=1 + qualquer provider de embeddings (CHATCLI_EMBED_PROVIDER=voyage / openai / bedrock). O cascade reutiliza o mesmo provedor do HyDE — zero infra duplicada. Veja RAG + HyDE para detalhes por provider.

Override do refiner agent

O RefinerAgent tem defaults de model="" e effort="medium". Override:

Exemplo: refine em resposta de documentação

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>:
Ú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

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ó.