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:- 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).
Fluxo do RefineHook
Multi-pass loop
Para cada pass até
MaxPasses:- Dispatch
workers.AgentCall{Agent: refiner, Task: RefineDirective + "Task: ...\n\nDraft: ..."} - Recebe
res.Outputcom o conteúdo de<revised> - Se
convergedRefine(currentDraft, res.Output, EpsilonChars)→ break
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
| Scorer | Custo | Pega | Confiança |
|---|---|---|---|
| Char | μs | Igualdade literal, length delta | Alta nos extremos, baixa no meio |
| Jaccard | ms | Sets de tokens normalizados (lowercase, stop-words PT/EN, sem pontuação) — captura reordenação | Cresce com tamanho do corpus |
| Embedding | 100-500ms + $ | Cosine similarity via embedding.Provider (Voyage/OpenAI) — captura paráfrase + sinônimos | Alta, autoritativa |
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 marcarefine_rolled_back=true no metadata — sinal que Reflexion consome:
Cache LRU com TTL
Embedding é caro ($). O cascade cacheia vetores porsha256(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 comDegradedFrom="embedding_unavailable" no Score. Zero stall no refine.
Modo strict vs permissive
| Modo | Embedder fora | Comportamento |
|---|---|---|
| permissive (default) | Degrada pra Jaccard | Marca DegradedFrom no trail, continua |
| strict | Recusa convergência | Trata embedding como autoridade; sem ela, Converged=false |
Fallback legado
Quando nenhum checker é wirado (ouCONVERGENCE_ENABLED=false), cai no heurístico char-level original:
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 defaultExcludeAgents:
| Agente | Razão |
|---|---|
| formatter | Output mecânico (arquivo formatado), refinar não agrega |
| deps | Output é interpretação determinística de go list, npm ls, etc. |
| refiner | Anti-recursão: refinar a saída do refiner criaria loop infinito |
| verifier | Mesma razão — verifier já entrega output polido |
/refine — session toggle
Em vez de editar env vars e reiniciar, use o slash:
cli.qualityOverrides.Refine como *bool:
nil→ defer ao/config quality&true→ força on&false→ força off
AgentMode.Run() constrói seu qualityConfig.
Variáveis de ambiente
Básicos
| Env var | Default | O que faz |
|---|---|---|
CHATCLI_QUALITY_REFINE_ENABLED | false | Master switch |
CHATCLI_QUALITY_REFINE_MAX_PASSES | 1 | Hard cap de passes (recomendo 1-2) |
CHATCLI_QUALITY_REFINE_MIN_BYTES | 200 | Não refina outputs menores |
CHATCLI_QUALITY_REFINE_EPSILON | 50 | Threshold char do fallback |
CHATCLI_QUALITY_REFINE_EXCLUDE | formatter,deps,refiner,verifier | CSV de agents que NÃO são refinados |
Cascade semântico de convergência
| Env var | Default | Efeito |
|---|---|---|
CHATCLI_QUALITY_REFINE_CONVERGENCE_ENABLED | true | Master switch do cascade. false = fallback pro char heurístico |
CHATCLI_QUALITY_REFINE_CONVERGENCE_EMBEDDING | false | Inclui embedding scorer — opt-in porque custa $ |
CHATCLI_QUALITY_REFINE_CONVERGENCE_STRICT | false | Strict mode: recusa convergência sem embedding |
CHATCLI_QUALITY_REFINE_CONVERGENCE_CHAR_HIGH | 0.99 | Sim ≥ X pelo char → short-circuit CONVERGIU |
CHATCLI_QUALITY_REFINE_CONVERGENCE_CHAR_LOW | 0.3 | Sim < X pelo char → short-circuit DIVERGIU |
CHATCLI_QUALITY_REFINE_CONVERGENCE_JACCARD_HIGH | 0.95 | Sim ≥ X pelo Jaccard (com confiança ≥ 0.6) → CONVERGIU |
CHATCLI_QUALITY_REFINE_CONVERGENCE_EMBEDDING_SIM | 0.92 | Threshold final do embedding |
CHATCLI_QUALITY_REFINE_CONVERGENCE_CACHE_SIZE | 256 | Entries do LRU cache de embeddings |
CHATCLI_QUALITY_REFINE_CONVERGENCE_CACHE_TTL_MIN | 5 | TTL do cache em minutos |
CHATCLI_QUALITY_REFINE_CONVERGENCE_BREAKER_THRESHOLD | 3 | Falhas consecutivas do embedder antes do breaker abrir |
Override do refiner agent
ORefinerAgent tem defaults de model="" e effort="medium". Override:
Exemplo: refine em resposta de documentação
- Draft (CoderAgent output)
- Critique
- Revised
Invocação direta pelo orquestrador
Além do hook automático, o orquestrador pode chamar o refiner via<agent_call>:
- 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
| Config | Calls LLM extras por turn | Latência típica |
|---|---|---|
MaxPasses=1 (default) | +1 | 1-3s com Haiku, 3-8s com Sonnet |
MaxPasses=2 | +1 a +2 (converge pode parar em 1) | até 2x |
MaxPasses=3+ | Raramente converge → gasto | Evitar |
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ó.