1. Введение
В Части 1 я разобрал ReAct — паттерн, где агент чередует рассуждение и действие. В Части 2 — Plan-and-Execute, где отдельный Planner строит N-шаговый план. Оба паттерна объединяет один недостаток: агент не учится на своих ошибках. Каждый запуск — с чистого листа. Reflexion-паттерн решает эту проблему: агент совершает попытку, оценивает результат, рефлексирует — и при следующей попытке использует накопленный опыт.
2. Что такое Reflexion
История
В декабре 2022 года Anthropic опубликовала Constitutional AI — подход, где языковая модель критикует собственные ответы и переписывает их для снижения вредности. Это был первый масштабный пример self-critique-паттерна: generate → self-critique → revise. Но Constitutional AI использовала критику для обучения (finetuning через RLAIF), а не для инференса.
В марте 2023 года Madaan et al. опубликовали Self-Refine — итеративное улучшение через self-feedback. Та же LLM выступает в трёх ролях: генератор, критик и рефайнер. Результат: ~20% average improvement на 7 задачах (Madaan et al., 2023). Но есть нюанс — на задачах рассуждения (Math Reasoning) улучшение 0%: модель не способна надёжно определить, правильное у неё рассуждение или нет.
И тут начинается самое интересное. В том же марте 2023 года Shinn et al. опубликовали Reflexion — и решили главную проблему Self-Refine: добавили эпизодическую память и внешнюю оценку. Вместо одного цикла critique-refine — мульти-триальный процесс, где агент накапливает вербальные «уроки» и использует их при следующих попытках. Результат: 91% pass@1 на HumanEval (против 80% у GPT-4) и +22% absolute на AlfWorld (Shinn et al., 2023).
Аналогия с разработчиком
Представьте: джун пишет код, запускает тесты — падают. Что он делает? Не переписывает с нуля — он читает ошибку, понимает причину, записывает «в следующий раз проверю edge-case с nil». Это и есть рефлексия: не просто исправить, а извлечь урок на будущее. ReAct — джун без памяти: каждый раз наступает на те же грабли. Plan-and-Execute — джун с планом, но без ретроспективы. Reflexion — джун, который ведёт дневник ошибок.
Формальное определение
Reflexion работает в три фазы, повторяющиеся циклически:
- Act: Actor (LLM) генерирует действия и получает наблюдения из среды.
- Evaluate: Evaluator оценивает результат — скалярной оценкой или свободным текстом.
- Reflect: Self-Reflection модель генерирует вербальную обратную связь — что пошло не так и как исправить. Рефлексия сохраняется в episodic memory.
При следующей попытке Actor получает содержимое эпизодической памяти в контексте — и может избежать повторения ошибок.
3. Какую задачу решает
Проблема ReAct: нет обучения на ошибках
ReAct, как я показал в Части 1, чередует Thought-Action-Observation в одном цикле. Если задача не решена — агент просто начинает заново. Прошлый опыт? Утрачен. Каждый запуск — первый и последний.
Проблема Plan-and-Execute: нет ретроспективы
Plan-and-Execute строит план и выполняет его. Reviser корректирует план при необходимости — но внутри одного запуска. Между запусками — чистый лист. На прошлых ошибках не учимся.
Проблема Self-Refine: нет памяти между попытками
Self-Refine делает critique-refine в одном вызове LLM. Улучшение есть на задачах генерации (стиль, формат) — но на задачах рассуждения 0%, потому что модель не может надёжно оценить правильность собственного рассуждения без внешнего арбитра (Madaan et al., 2023, Table 1: Math Reasoning).
Что обеспечивает Reflexion
| Проблема | Решение Reflexion |
|---|---|
| Нет обучения на ошибках | Episodic memory хранит вербальные уроки между попытками |
| Ненадёжная самооценка | Evaluator — внешний арбитр (тесты, компилятор, среда) |
| Нет ретроспективы | Каждая попытка обогащается рефлексиями из прошлых |
| Myopic исправления | Рефлексия фокусируется на причине ошибки, а не на симптоме |
4. Архитектура
Actor → Evaluator → Reflector → Memory → retry
sequenceDiagram
participant U as User
participant A as Actor
participant E as Evaluator
participant R as Reflector
participant M as Episodic Memory
U->>A: Task + reflections from memory
A->>A: Generate actions (ReAct loop)
A->>E: Trajectory (actions + observations)
alt Result is correct
E-->>U: ✅ Success
else Result has errors
E->>R: Trajectory + evaluation
R->>R: Generate verbal reflection
"I failed because..."
R->>M: Store reflection
M-->>A: Enriched context for next attempt
Note over A,M: Retry with accumulated experience
end
Компоненты
Actor — LLM, генерирующая действия. Может быть ReAct-агентом или простой ChatModel. Ключевое отличие от обычного ReAct: Actor получает содержимое эпизодической памяти в system prompt, что позволяет учитывать прошлые ошибки.
Evaluator — оценивает результат Actor. Может быть:
- Детерминированным: unit tests, компилятор, game environment — даёт объективную оценку
- LLM-based: другая языковая модель оценивает качество — менее надёжно, но применимо для open-ended задач
Почему это важно? Именно внешний верификатор решает проблему Self-Refine, где модель не способна оценить собственную правильность.
Self-Reflection model — LLM, генерирующая вербальную рефлексию. Получает: траекторию Actor (actions + observations), оценку Evaluator, прошлые рефлексии из памяти. Генерирует текст вида: «Я допустил ошибку в обработке edge-case с пустым списком. В следующий раз нужно проверить len() > 0 перед доступом к элементу».
Episodic Memory — хранилище рефлексий. Простая структура: список текстовых строк, которые инжектируются в контекст Actor при следующей попытке. Чем больше попыток — тем богаче память.
5. Эволюция self-critique
Три паттерна self-critique появились за 3 месяца — и каждый решал проблему предыдущего:
flowchart TD
CAI["🛡️ Constitutional AI
Dec 2022 • Bai/Anthropic
Self-critique → revise
для обучения (finetuning)
Цель: harmlessness"]
SRF["🔄 Self-Refine
Mar 2023 • Madaan/CMU
Same LLM: generate → critique → refine
для инференса (1 вызов)
~20% improvement на генерации"]
REF["🧠 Reflexion
Mar 2023 • Shinn/Princeton+NEU
Actor → Evaluator → Reflector
для инференса (N попыток)
+ Episodic Memory"]
HUANG["⚠️ Huang et al.
Oct 2023 • ICLR 2024
LLMs Cannot Self-Correct
Reasoning Yet
Без external feedback — не работает"]
RRR["🚀 Reflect, Retry, Reward
May 2025 • Bensal/Writer
RL-тренировка рефлексий
1.5B-7B бьёт 10x модели"]
CAI -->|"добавил
inference-time
critique"| SRF
SRF -->|"добавил
episodic memory
+ external eval"| REF
REF -->|"показал
ограничения
без верификатора"| HUANG
HUANG -->|"RL-тренировка
лучших рефлексий"| RRR
style CAI fill:#2e7d32,color:#fff
style SRF fill:#1565c0,color:#fff
style REF fill:#e65100,color:#fff
style HUANG fill:#c62828,color:#fff
style RRR fill:#6a1b9a,color:#fff
Сравнение трёх паттернов
| Аспект | Constitutional AI | Self-Refine | Reflexion |
|---|---|---|---|
| Дата | Dec 2022 | Mar 2023 | Mar 2023 |
| Цель | Harmlessness (safety) | Качество вывода | Качество вывода + обучение |
| Критика | Self-critique | Self-feedback | External evaluator + self-reflection |
| Память | Нет | Нет | Episodic memory |
| Попытки | 1 | 1 (итерации внутри) | N (мульти-триальный) |
| Применение | Finetuning (offline) | Инференс (online) | Инференс (online) |
| Результат | Улучшение harmlessness | +20% на генерации, 0% на рассуждении | +11% HumanEval (91% vs 80% GPT-4), +22% AlfWorld |
| Тип оценки | RLAIF (RL от AI-судьи) | Self-judge | External verifier |
Закономерность очевидна: каждый следующий паттерн добавляет то, чего не хватало предыдущему. Constitutional AI не было памяти и мульти-триальности. Self-Refine добавил inference-time critique, но без памяти и без внешнего верификатора. Reflexion замкнул петлю: внешний верификатор решает проблему ненадёжной самооценки, а эпизодическая память позволяет учиться между попытками.
6. Когда работает / когда нет
Зачем отдельная секция про ограничения? Потому что в октябре 2023 года Huang et al. опубликовали «Large Language Models Cannot Self-Correct Reasoning Yet» — и доказали, что self-correction без внешней обратной связи ухудшает результат.
flowchart TD
START[Задача агента] --> Q{Есть внешний
верификатор?}
Q -->|Да| Q2{Низкая начальная
точность?}
Q -->|Нет| FAIL["❌ Reflexion не поможет
Self-correction ухудшит результат
(Huang et al., 2023)"]
Q2 -->|Да| WORKS["✅ Reflexion работает
+11-22% improvement
(HumanEval, AlfWorld)"]
Q2 -->|Нет| WARN["⚠️ Может не окупиться
Риск ухудшения на простых задачах
Diminishing returns"]
WORKS --> REC1["Рекомендация:
max 3-5 попыток,
оценивай cost/benefit"]
WARN --> REC2["Рекомендация:
не более 2 попыток,
мониторь качество"]
style FAIL fill:#c62828,color:#fff
style WORKS fill:#2e7d32,color:#fff
style WARN fill:#e65100,color:#fff
Цифры Huang et al.
Без внешнего верификатора (intrinsic self-correction), качество падает на всех моделях:
| Модель | GSM8K (было → стало) | CommonSenseQA (было → стало) |
|---|---|---|
| GPT-3.5 | 75.9 → 74.7 | 75.8 → 41.8 |
| GPT-4 | 95.5 → 89.0 | 82.0 → 80.0 |
| Llama-2-70b | 62.0 → 36.5 | 64.0 → 36.5 |
Причины: LLM чаще меняет правильный ответ на неправильный, чем наоборот. Фундаментальная проблема — модель не способна надёжно оценить правильность собственного рассуждения (Huang et al., 2023, Figure 1).
Когда Reflexion работает
| Условие | Почему |
|---|---|
| Внешний верификатор (тесты, компилятор, env) | Объективная оценка → точная рефлексия |
| Низкая начальная точность | Есть пространство для улучшения |
| Мульти-триальный сценарий | Память накапливает уроки |
| Задачи с объективным критерием успеха | Чёткий сигнал об ошибке |
Когда Reflexion НЕ работает
| Условие | Почему |
|---|---|
| Нет внешнего верификатора | Модель не может оценить свою правильность |
| Высокая начальная точность | Риск ухудшения (correct → incorrect) |
| Open-ended задачи без критерия | Нечего оценивать → неточная рефлексия |
| Простые задачи | Cost рефлексии не окупается |
7. Варианты реализации на Eino
Eino не предоставляет готового reflection.NewAgent() — в отличие от react.NewAgent() из Части 1 или planexecute.NewAgent() из Части 2. Но это и к лучшему: Reflexion — это не отдельный тип агента, а паттерн компоновки, который можно реализовать несколькими способами.
Вариант A: compose.Graph с циклом
Eino Graph поддерживает циклы через AddEdge из узла в себя же + WithMaxRunSteps для ограничения итераций. Это наиболее естественная реализация Reflexion:
flowchart LR
START(("START")) --> Actor["🎬 Actor
(react.Agent)"]
Actor --> Evaluator["🔍 Evaluator
(Lambda: run tests)"]
Evaluator --> Branch{"Pass?"}
Branch -->|Yes| END(("END"))
Branch -->|No| Reflector["🪞 Reflector
(ChatModel)"]
Reflector --> Memory["💾 Memory
(State: []string)"]
Memory --> Actor
style START fill:#2e7d32,color:#fff
style END fill:#2e7d32,color:#fff
style Branch fill:#e65100,color:#fff
style Actor fill:#1565c0,color:#fff
style Evaluator fill:#1565c0,color:#fff
style Reflector fill:#6a1b9a,color:#fff
style Memory fill:#ad1457,color:#fff
Плюсы: явный цикл retry, поддержка ветвления, checkpoint через WithCheckPointStore, можно встроить ReAct-агента через ExportGraph().
Минусы: Graph API использует неявную передачу данных (весь output → весь input), нужно аккуратно управлять state.
Вариант B: compose.Workflow (линейный, без цикла)
Workflow — декларативный граф с явным маппингом полей. Проблема: Workflow не поддерживает циклы — всегда AllPredecessor. Для Reflexion это фатально: нет retry-loop.
Но если цикл реализовать снаружи (в Go-коде), а Workflow использовать для одной итерации Actor → Evaluator → Reflector — это работает:
// Внешний retry-loop
for attempt := 0; attempt < maxAttempts; attempt++ {
result, err := workflow.Invoke(ctx, input)
if result.Passed { break }
memory = append(memory, result.Reflection)
// Инжектируем память в следующий вызов
input.Reflections = memory
}
Плюсы: явный field mapping, типобезопасность, проще тестировать одну итерацию.
Минусы: нет встроенного цикла — пришлось реализовывать вручную, нет checkpoint между итерациями.
Вариант C: deer-go паттерн (State Graph)
deer-go — Go-реализация ByteDance DEER-flow на Eino Graph. Использует Goto-маршрутизацию: каждый узел записывает следующий целевой узел в state.Goto, а agentHandOff-функция направляет выполнение.
Для Reflexion можно добавить Critic-узел и ребро Critic → Actor (retry). Это расширяет существующую архитектуру, но deer-go не содержит готовых паттернов рефлексии — только re-planning loop.
Плюсы: готовая архитектура state graph, checkpoint, human-in-the-loop через InterruptAndRerun.
Минусы: сложнее, требует HTTP-сервер и MCP tools, избыточно для простых сценариев.
Сравнение вариантов
| Аспект | Graph + цикл | Workflow + внешний loop | deer-go |
|---|---|---|---|
| Цикл retry | Встроенный | Внешний (Go-код) | Через Goto |
| Checkpoint | ✅ WithCheckPointStore | ❌ Вручную | ✅ Встроенный |
| Сложность | Средняя | Низкая | Высокая |
| Field mapping | Неявный | Явный | Через State |
| Готовность к prod | Высокая | Средняя | Высокая |
Мой выбор для примера: compose.Graph — нативная поддержка циклов, checkpoint, и прямое встраивание react.Agent через ExportGraph().
8. Код-пример
Реализую Reflexion на compose.Graph: Actor (ReAct-агент) генерирует Go-код, Evaluator запускает тесты, Reflector анализирует ошибки, Memory накапливает рефлексии.
flowchart TD
START(("START")) --> Actor["🎬 Actor
react.Agent
+ write_code tool"]
Actor --> Evaluator["🔍 Evaluator
Lambda: go test"]
Evaluator --> Branch{"Tests pass?"}
Branch -->|Yes| END(("END ✅"))
Branch -->|No| Reflector["🪞 Reflector
ChatModel: analyze
test failures"]
Reflector --> Memory["💾 Append reflection
to episodic memory"]
Memory --> Actor
style START fill:#2e7d32,color:#fff
style END fill:#2e7d32,color:#fff
style Branch fill:#e65100,color:#fff
package main
import (
"context"
"fmt"
"github.com/cloudwego/eino/compose"
"github.com/cloudwego/eino/components/tool"
"github.com/cloudwego/eino/components/tool/utils"
"github.com/cloudwego/eino-ext/components/model/openai"
"github.com/cloudwego/eino/flow/agent/react"
"github.com/cloudwego/eino/schema"
)
// reflexionState — разделяемое состояние для одного выполнения Reflexion.
// Создаётся заново при каждом Invoke.
type reflexionState struct {
// Task — исходная задача (например, "write a function that sorts a list")
Task string
// Reflections — накопленные вербальные рефлексии из прошлых попыток
Reflections []string
// Attempt — текущий номер попытки (1-based)
Attempt int
// MaxAttempts — максимальное число попыток
MaxAttempts int
// Code — сгенерированный код (выход Actor)
Code string
// TestResult — результат запуска тестов (выход Evaluator)
TestResult string
// Passed — флаг: тесты пройдены?
Passed bool
}
// writeCodeTool — инструмент для Actor: "записывает" код в файл.
// В реальном приложении здесь будет запись на диск.
type writeCodeTool struct{}
func (t *writeCodeTool) Info(ctx context.Context) (*schema.ToolInfo, error) {
return &schema.ToolInfo{
Name: "write_code",
Desc: "Write Go code to solve the task. The code will be tested automatically.",
}, nil
}
func (t *writeCodeTool) InvokableRun(ctx context.Context, args string, opts ...tool.Option) (string, error) {
// В реальном приложении: записать args в .go файл
return fmt.Sprintf("Code written (%d bytes)", len(args)), nil
}
func main() {
ctx := context.Background()
// 1. Создаём модель для Actor и Reflector
chatModel, err := openai.NewChatModel(ctx, &openai.ChatModelConfig{
Model: "gpt-4o",
})
if err != nil {
panic(err)
}
// 2. Создаём ReAct-агента как Actor
// ExportGraph() позволяет встроить его в compose.Graph
codeTool := utils.NewTool(&writeCodeTool{}, nil)
actor, err := react.NewAgent(ctx, &react.AgentConfig{
ToolCallingModel: chatModel,
ToolsConfig: compose.ToolsNodeConfig{
Tools: []tool.BaseTool{codeTool},
},
MaxStep: 5,
})
if err != nil {
panic(err)
}
// 3. Строим Reflexion Graph
g := compose.NewGraph[string, string](
compose.WithGenLocalState(func(ctx context.Context) *reflexionState {
return &reflexionState{
MaxAttempts: 3,
}
}),
compose.WithMaxRunSteps(20), // ограничение на циклы
)
// Actor: встроим ReAct-агента через ExportGraph
actorGraph, actorOpts := actor.ExportGraph()
g.AddGraphNode("actor", actorGraph, actorOpts...)
g.AddEdge(compose.START, "actor")
// Evaluator: Lambda-узел, который "запускает тесты"
g.AddLambdaNode("evaluator",
compose.InvokableLambda(func(ctx context.Context, code string) (string, error) {
// В реальном приложении: exec.Command("go", "test", "./...")
// Здесь: симуляция
if len(code) > 10 {
return "PASS: all tests passed", nil
}
return "FAIL: TestSortEmpty - expected [], got nil", nil
}),
)
g.AddEdge("actor", "evaluator")
// Reflector: ChatModel анализирует ошибки
g.AddChatModelNode("reflector", chatModel)
g.AddEdge("evaluator", "reflector")
// Conditional Branch: pass → END, fail → back to Actor
g.AddBranch("evaluator", compose.NewGraphBranch(
func(ctx context.Context, testResult string) (string, error) {
// Читаем state для проверки числа попыток
if err := compose.ProcessState[*reflexionState](ctx,
func(ctx context.Context, s *reflexionState) error {
s.Attempt++
s.TestResult = testResult
// Простой эвристический критерий
s.Passed = len(testResult) > 4 && testResult[:4] == "PASS"
},
); err != nil {
return "", err
}
var target string
_ = compose.ProcessState[*reflexionState](ctx,
func(ctx context.Context, s *reflexionState) error {
if s.Passed || s.Attempt >= s.MaxAttempts {
target = compose.END
} else {
target = "reflector" // сначала рефлексируем, потом retry
}
return nil
},
)
return target, nil
},
map[string]bool{compose.END: true, "reflector": true},
))
// Reflector → Actor: retry с рефлексией в контексте
g.AddEdge("reflector", "actor")
// END
g.AddEdge(compose.END, compose.END)
// 4. Компилируем и запускаем
runnable, err := g.Compile(ctx)
if err != nil {
panic(fmt.Sprintf("compile error: %v", err))
}
result, err := runnable.Invoke(ctx, "Write a function that sorts a slice of integers")
if err != nil {
panic(fmt.Sprintf("invoke error: %v", err))
}
fmt.Println("Result:", result)
}
Что здесь происходит
Состояние —
reflexionStateхранит текущую попытку, рефлексии и результат оценки. Создаётся черезWithGenLocalStateпри каждом запуске графа.Actor — встроен через
ExportGraph(). ReAct-агент с инструментомwrite_code. При повторном заходе (после рефлексии) получает обновлённый контекст.Evaluator — Lambda-узел, который «запускает тесты». В реальном приложении —
exec.Command("go", "test"). В примере — симуляция: если код длиннее 10 байт — PASS.Reflector — ChatModel, анализирующая ошибки. Получает результат тестов и генерирует вербальную рефлексию.
Branch — условное ветвление после Evaluator: PASS → END, FAIL → Reflector → Actor (retry). Проверяет
Attempt < MaxAttempts.Цикл —
g.AddEdge("reflector", "actor")замыкает петлю.WithMaxRunSteps(20)ограничивает общее число шагов (защита от бесконечного цикла).
9. Инженерный сценарий
Кодогенерация с тестами — идеальный сценарий для Reflexion. Почему? Потому что есть объективный внешний верификатор: компилятор и unit-тесты. Это не субъективная LLM-оценка, а бинарный PASS/FAIL.
TDD для агента
sequenceDiagram
participant Dev as Developer
participant A as Actor Agent
participant T as go test
participant R as Reflector
participant M as Memory
Dev->>A: "Write sort([]int)"
Note over A: Attempt 1
A->>T: sort.go
T-->>A: ❌ FAIL: TestSortEmpty
expected [], got nil
A->>R: Trajectory + test failure
R->>R: "Forgot to handle
empty slice"
R->>M: Store reflection #1
Note over A: Attempt 2 (with reflection)
M-->>A: "Check empty slice first"
A->>T: sort_v2.go
T-->>A: ❌ FAIL: TestSortStable
unstable sort on equal elements
A->>R: Trajectory + test failure
R->>R: "Used unstable sort,
need stable"
R->>M: Store reflection #2
Note over A: Attempt 3 (with 2 reflections)
M-->>A: "Check empty slice first
Use stable sort"
A->>T: sort_v3.go
T-->>A: ✅ PASS: all tests passed
A-->>Dev: sort_v3.go ✅
Почему это работает лучше Self-Refine
Self-Refine в том же сценарии дал бы 0% improvement на Math Reasoning (Madaan et al., 2023). Почему? Без тестов модель не отличает sort([]int{}) от sort([]int{1}) — ей не хватает объективного сигнала. Reflexion с go test как Evaluator решает эту проблему: тесты дают точную диагностику ошибки → рефлексия фокусируется на реальной проблеме → Actor исправляет именно то, что нужно.
Production-реализация
В production сценарий расширяется:
| Компонент | Пример | В production |
|---|---|---|
| Actor | react.NewAgent с write_code | + read_file, search_docs, lint_code |
| Evaluator | go test ./... | + go vet, golangci-lint, coverage ≥ 80% |
| Reflector | ChatModel «analyze failures» | Промпт с конкретными паттернами ошибок |
| Memory | []string в state | Redis / файл с reflection history |
| Max attempts | 3 | 5 (HumanEval: 91% достигнуто за 12 попыток, но 3-5 обычно достаточно) |
10. Практические рекомендации
Когда применять Reflexion
| Сценарий | Применимость | Обоснование |
|---|---|---|
| Кодогенерация + тесты | ✅ Отлично | Объективный верификатор (компилятор/тесты) |
| Game-агенты | ✅ Отлично | Среда даёт чёткий reward signal |
| Data pipeline с валидацией | ✅ Хорошо | Schema validation как верификатор |
| Code review автоматизация | ⚠️ Осторожно | LLM-оценка менее надёжна, чем тесты |
| Креативное письмо | ⚠️ Осторожно | Нет объективного критерия успеха |
| Математика / рассуждение | ❌ Не рекомендуется | Без внешнего верификатора — ухудшает результат |
Настройка гиперпараметров
Max attempts: 3-5 для задач с быстрым верификатором (тесты). HumanEval достиг 91% за 12 попыток, но diminishing returns начинается после 3-5. Больше — дороже, но не лучше.
Episodic memory size: храните последние 5-10 рефлексий. Слишком много — контекст разрастается, модель теряет фокус. Слишком мало — не учитывает давние ошибки.
Evaluator choice: детерминированный верификатор (тесты, компилятор) всегда лучше LLM-based. Если верификатор ненадёжный — Reflexion превращается в Self-Refine с его проблемами.
Reflector prompt: конкретный > абстрактный. Не «проанализируй ошибку», а «идентифицируй: (1) какой тест упал, (2) какой вход вызвал падение, (3) какое предположение было неверным, (4) что изменить в коде».
Cost management
Каждая попытка Reflexion = полный цикл Actor + Evaluator + Reflector. При 3 попытках — 3x cost. Mitigation:
- Использовать дешёвую модель для Evaluator (детерминированная проверка не требует GPT-4)
- Рано останавливаться: если 2 попытки не помогли — третья вряд ли поможет
- Кешировать рефлексии для похожих задач
11. Итоги
Reflexion-паттерн — это ReAct + самооценка + эпизодическая память. Ключевые выводы:
Внешний верификатор — обязателен. Без него self-correction ухудшает результат (Huang et al., 2023). С ним — Reflexion даёт +11% на HumanEval и +22% на AlfWorld.
Эпизодическая память — ключевое отличие от Self-Refine. Не просто critique-refine, а накопление вербальных уроков между попытками. Это превращает одноразового агента в обучающегося.
Не панацея. Reflexion не работает на задачах без объективного критерия успеха и может ухудшить результат при высокой начальной точности.
В Eino — compose.Graph с циклом. Workflow не подходит (нет циклов). Graph +
AddEdge("reflector", "actor")+WithMaxRunSteps— естественная реализация.
Что дальше? В Части 4 — Multi-Agent паттерны: когда один агент не справляется, и нужна команда. А тему памяти агентов — долгосрочной, эпизодической, семантической — я подробно разберу в Части 6.