Após erro, alucinação ou qualidade baixa, uma chamada LLM destila uma lição estruturada (situation / mistake / correction) e persiste em memory.Fact. Próximas tarefas similares a recuperam via RAG — fechando o loop sem retreinamento.
Reflexion fecha o loop de aprendizado: quando um agente falha ou produz saída de baixa qualidade, em vez de perder a experiência, o pipeline gera uma Lesson estruturada e persiste na memória de longo prazo. Na próxima tarefa similar, essa lição emerge naturalmente via RAG+HyDE.
Reflexion é o único post-hook ligado por default — porque só dispara em condições excepcionais (erro, discrepância) e o lesson generator roda em goroutine detached, nunca bloqueando o turn do usuário.
type Lesson struct { Situation string // "Quando preciso editar arquivo Go grande..." Mistake string // "Tentei reescrever o arquivo todo de uma vez" Correction string // "Use Edit tool com old_string/new_string específicos" Tags []string // ["go", "edit-file", "large-file", "reflexion"] Trigger string // "error" | "hallucination" | "low_quality" | "manual" CreatedAt time.Time}
Ao persistir em memory.Fact, o Content fica:
LESSON: Quando preciso editar arquivo Go grandeMISTAKE: Tentei reescrever o arquivo todo de uma vezCORRECTION: Use Edit tool com old_string/new_string específicosTRIGGER: error
A categoria do Fact é lesson e as tags incluem reflexion + trigger:<x> + os tags específicos do domínio. Isso permite queries precisas: “me mostre todas as lições sobre edit-file” se torna uma pesquisa normal da memória.
ReflexionHook.PostRun(ctx, hc, result) inspeciona result.Metadata + result.Error para decidir o trigger.
2
Se trigger matched, spawn goroutine
go h.runReflexion(context.Background(), req)return nil // PostRun retorna imediatamente
Context detached deliberado: o ctx do turn vai ser cancelado quando a resposta chega no usuário, mas queremos a lição gerada mesmo assim.
3
GenerateLesson via LLM
O LLM recebe o system prompt + a tarefa + o attempt + o outcome, e emite blocos XML-like (<situation>, <mistake>, <correction>, <tags>, ou <skip> se não há lição útil).
4
Parse + persist
parseLesson valida que pelo menos situation e correction estão presentes. Se <skip>nothing actionable</skip>, retorna nil sem persistir.
5
memory.Facts.AddFactWithSource
Persiste em ~/.chatcli/memory/memory_index.json com categoria=lesson e tags incluindo o workspace atual como source.
O system prompt instrui o modelo a ser geral, não one-off:
Rules:- A "lesson" must be GENERAL enough to apply next time a similar task comes up — not one-off and not a play-by-play.- If there is genuinely nothing to learn (e.g. the task was trivial and the failure was a transient network blip), reply with exactly: <skip>nothing actionable</skip>- Otherwise emit ALL of the following blocks. Keep each to ONE line.- "tags" is a comma-separated list of 2-5 short keywords (lowercase, hyphenated if needed) that future similar tasks will likely contain.OUTPUT:<situation>brief description of when this lesson applies</situation><mistake>what went wrong this time</mistake><correction>what to do differently next time</correction><tags>tag1, tag2, tag3</tags>
O bloco <skip> existe justamente para evitar pollution da memória com “lições” de falhas transientes. O modelo pode recusar gerar lição com custo zero de persistência.
Quando você sabe a lição e não precisa do LLM destilando:
/reflect quando editar arquivos Go grandes use Edit, não rewrite total
Isso entra direto em memory.Fact:
LESSON: quando editar arquivos Go grandes use Edit, não rewrite totalMISTAKE: (user-supplied lesson; no automatic mistake detection)CORRECTION: quando editar arquivos Go grandes use Edit, não rewrite totalTRIGGER: manual
/coder refactor pkg/engine to extract Close method
2
CoderAgent tenta rewrite total
Arquivo tem 2000 linhas, provider responde com timeout.
3
PostRun detecta result.Error != nil
OnError trigger matched.
4
goroutine: GenerateLesson
Model emite:
<situation>Refactoring large Go files (>1000 lines)</situation><mistake>Attempted full rewrite via @coder write</mistake><correction>Use @coder patch or Edit tool for surgical changes</correction><tags>go, refactor, large-file, edit-tool</tags>
5
Persiste em memory.Fact
Categoria=lesson, workspace=current project.
6
Próxima semana, usuário pede refactor similar
/coder refactor pkg/auth/manager.go split into smaller files
7
RAG+HyDE traz a lesson
Tags refactor + large-file matchem. Lesson aparece no system prompt.
8
Coder escolhe abordagem correta de primeira
Emite múltiplos @coder patch ao invés de write. Task concluída sem timeout.
# Todas as lições/memory longterm | grep -A3 "^LESSON:"# Ou diretamente no arquivocat ~/.chatcli/memory/memory_index.json | jq '.[] | select(.category=="lesson")'# Ou via /config/config quality# → mostra total de hooks post registrados (reflexion aparece se Enabled=true)