,\n",
" }\n",
"```\n",
"\n",
"The `passed` boolean is *the* deciding signal. No LLM is involved in pass/fail. The reflection LLM only writes the *lesson*, which is free-form text — flat-scoring has nothing to compress there.\n",
"\n",
"For tasks where no deterministic checker exists, the architecture accepts an optional `evaluator` callable. If you wrap an LLM-as-Judge there, follow the deterministic-picker pattern: have the LLM commit to independent boolean features and let Python compose `passed`. See `_ReflexionEvaluation` schema in [`reflexion.py`](../src/agentic_architectures/architectures/reflexion.py) for the template.\n",
"\n",
"### 3.1 · Why store the *full verbal reflection*, not feature embeddings\n",
"\n",
"You could imagine storing only `(failed_features → corrective_action)` tuples — compact, structured, easy to retrieve. The Reflexion paper rejects this on purpose: the *next* model reading the lesson is also an LLM, and LLMs reason better over natural language than over structured deltas. A two-sentence \"You under-counted syllables in line 2 — count out loud before submitting\" steers the next attempt; a JSON blob doesn't.\n",
"\n",
"The `_SelfReflection` Pydantic schema enforces second-person voice and demands explicit `root_cause` + `correction` fields, then composes them into a `reflection` paragraph. The paragraph is what gets stored in episodic memory; the structured fields are kept on the trace for the §9 commentary table.\n",
"\n",
"### 3.2 · Where this sits in the agent taxonomy\n",
"\n",
"| Pattern | Persists across calls? | Stores what? | When to reach for it |\n",
"|---|---|---|---|\n",
"| [Reflection (nb 01)](./01_reflection.ipynb) | no | nothing | quality matters, one-shot |\n",
"| [Episodic+Semantic (nb 08)](./08_episodic_semantic_memory.ipynb) | yes | conversations + facts | personal assistant continuity |\n",
"| [RLHF self-improvement (nb 15)](./15_rlhf_self_improvement.ipynb) | yes | **positive** examples (good outputs) | many similar tasks, compound quality |\n",
"| **Reflexion (this nb)** | **yes** | **negative-experience lessons** (verbal corrections) | learn from mistakes across similar tasks |\n",
"\n",
"The orthogonal axes: *positive vs negative examples* (RLHF vs Reflexion) and *experience-summary vs raw memory* (Reflexion vs Episodic).\n",
"\n",
"### 3.3 · Failure modes preview\n",
"\n",
"You'll see all of these surface in §8 or §9 below:\n",
"\n",
"1. **Demo too easy.** If the agent passes on trial 1 every time, no reflections are written — the demo doesn't actually exercise the architecture. The §9 tailor auto-flags this.\n",
"2. **Lesson too task-specific.** Lessons phrased as \"next time, use the word 'centuries' in line 2\" don't transfer. The schema's `correction` field asks for *generalisable* corrections, but the LLM can still narrow them.\n",
"3. **Recall misses.** EpisodicMemory uses vector similarity; if the embedding model can't see structural similarity between tasks, recalled lessons will be empty even when memory is non-empty.\n",
"4. **Loop exhaustion.** If `max_trials` is too low (or the task is too hard), the loop terminates failed. Reflections are still recorded — they benefit *later* tasks even though this one failed."
]
},
{
"cell_type": "markdown",
"id": "30cfe735",
"metadata": {
"papermill": {
"duration": 0.004703,
"end_time": "2026-05-27T15:04:01.350225+00:00",
"exception": false,
"start_time": "2026-05-27T15:04:01.345522+00:00",
"status": "completed"
},
"tags": []
},
"source": [
"## 4 · Setup"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "33e46da1",
"metadata": {
"execution": {
"iopub.execute_input": "2026-05-27T15:04:01.362253Z",
"iopub.status.busy": "2026-05-27T15:04:01.362253Z",
"iopub.status.idle": "2026-05-27T15:04:02.250093Z",
"shell.execute_reply": "2026-05-27T15:04:02.248591Z"
},
"papermill": {
"duration": 0.894889,
"end_time": "2026-05-27T15:04:02.251116+00:00",
"exception": false,
"start_time": "2026-05-27T15:04:01.356227+00:00",
"status": "completed"
},
"tags": []
},
"outputs": [
{
"data": {
"text/html": [
"Provider: nebius · Model: meta-llama/Llama-3.3-70B-Instruct ─────────────────────────────────────────────────────\n",
"\n"
],
"text/plain": [
"\u001b[1;36mProvider: nebius · Model: meta-llama/Llama-\u001b[0m\u001b[1;36m3.3\u001b[0m\u001b[1;36m-70B-Instruct\u001b[0m \u001b[92m─────────────────────────────────────────────────────\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from agentic_architectures import get_llm, enable_langsmith, settings\n",
"from agentic_architectures.architectures import Reflexion\n",
"from agentic_architectures.ui import print_md, print_header, print_step\n",
"\n",
"enable_langsmith()\n",
"print_header(f\"Provider: {settings.llm_provider} · Model: {settings.llm_model}\")"
]
},
{
"cell_type": "markdown",
"id": "f51c095f",
"metadata": {
"papermill": {
"duration": 0.006931,
"end_time": "2026-05-27T15:04:02.265335+00:00",
"exception": false,
"start_time": "2026-05-27T15:04:02.258404+00:00",
"status": "completed"
},
"tags": []
},
"source": [
"## 5 · Library walkthrough\n",
"\n",
"Source: [`src/agentic_architectures/architectures/reflexion.py`](../src/agentic_architectures/architectures/reflexion.py).\n",
"\n",
"Three things make `Reflexion` distinct from nb 01 Reflection:\n",
"\n",
"1. **`self.episodic: EpisodicMemory`** — created once in `__init__`, mutated by every failed-trial `reflect` node, queried by every `attempt` node. Persists across `run()` calls on the same instance.\n",
"2. **`evaluator` is a pluggable `Callable`** — defaults to `default_haiku_checker` (pure Python). You can swap in any function returning `{... \"passed\": bool}`.\n",
"3. **`_SelfReflection` schema** demands three structured fields (`root_cause`, `correction`, `reflection`) so the stored memory is *actionable*, not vague.\n",
"\n",
"The Pydantic schema for the verbal reflection:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "d726edf4",
"metadata": {
"execution": {
"iopub.execute_input": "2026-05-27T15:04:02.282323Z",
"iopub.status.busy": "2026-05-27T15:04:02.282323Z",
"iopub.status.idle": "2026-05-27T15:04:02.296479Z",
"shell.execute_reply": "2026-05-27T15:04:02.295468Z"
},
"papermill": {
"duration": 0.025116,
"end_time": "2026-05-27T15:04:02.298502+00:00",
"exception": false,
"start_time": "2026-05-27T15:04:02.273386+00:00",
"status": "completed"
},
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"=== _SelfReflection schema ===\n",
"{\n",
" \"description\": \"The verbal-reflection schema. Three fields so the recalled lesson is\\n*actionable* rather than a vague paragraph.\",\n",
" \"properties\": {\n",
" \"root_cause\": {\n",
" \"description\": \"ONE SENTENCE: precisely why the previous attempt failed. Reference the specific feature that broke (e.g., 'line 2 had 8 syllables instead of 7' \\u2014 not 'the haiku was off').\",\n",
" \"title\": \"Root Cause\",\n",
" \"type\": \"string\"\n",
" },\n",
" \"correction\": {\n",
" \"description\": \"ONE SENTENCE: the concrete change to make on the next attempt. Phrase as an imperative (e.g., 'Count syllables of line 2 out...\n",
"\n",
"=== default_haiku_checker docstring ===\n",
"Pure-Python checker for the demo scenario. No LLM involved.\n",
"\n",
" `task_spec` is a tiny ``key=value; key=value`` string parsed out of the\n",
" task text — keeps the checker decoupled from the Reflexion class so users\n",
" can plug their own.\n",
"\n",
" Example: ``'topic=glacier; required_words=silence,centuries'``\n",
"\n",
" Returns objective features the reflect node feeds verbatim into the\n",
" reflection LLM prompt, plus the deciding ``passed`` boolean.\n",
" \n"
]
}
],
"source": [
"from agentic_architectures.architectures.reflexion import _SelfReflection, default_haiku_checker\n",
"import json\n",
"print(\"=== _SelfReflection schema ===\")\n",
"print(json.dumps(_SelfReflection.model_json_schema(), indent=2)[:600] + '...')\n",
"print()\n",
"print(\"=== default_haiku_checker docstring ===\")\n",
"print(default_haiku_checker.__doc__)"
]
},
{
"cell_type": "markdown",
"id": "5c7b8d33",
"metadata": {
"papermill": {
"duration": 0.006015,
"end_time": "2026-05-27T15:04:02.310533+00:00",
"exception": false,
"start_time": "2026-05-27T15:04:02.304518+00:00",
"status": "completed"
},
"tags": []
},
"source": [
"## 6 · State"
]
},
{
"cell_type": "markdown",
"id": "a1eac3f3",
"metadata": {
"papermill": {
"duration": 0.004043,
"end_time": "2026-05-27T15:04:02.318581+00:00",
"exception": false,
"start_time": "2026-05-27T15:04:02.314538+00:00",
"status": "completed"
},
"tags": []
},
"source": [
"| Field | Type | Set by |\n",
"|---|---|---|\n",
"| `task` | `str` | caller |\n",
"| `max_trials` | `int` | caller (from `arch.max_trials`) |\n",
"| `trial` | `int` (0-indexed; incremented in `attempt`) | `_attempt` |\n",
"| `attempt_text` | `str` (latest candidate) | `_attempt` |\n",
"| `recalled_reflections` | `list[str]` (pulled from `self.episodic`) | `_attempt` |\n",
"| `evaluator_features` | `dict` (objective features from checker) | `_evaluate` |\n",
"| `success` | `bool` (= `evaluator_features['passed']`) | `_evaluate` |\n",
"| `reflection_text` / `root_cause` / `correction` | `str` | `_reflect` |\n",
"| `history` | `Annotated[list[dict], operator.add]` — one entry per trial + one per reflection | `_evaluate` + `_reflect` |\n",
"| `final_output` | `str` | `_finalize` |\n",
"| `arch.episodic` *(instance attribute)* | `EpisodicMemory` — **persists across `run()` calls** | `_reflect` side-effect |"
]
},
{
"cell_type": "markdown",
"id": "64bfc0eb",
"metadata": {
"papermill": {
"duration": 0.003597,
"end_time": "2026-05-27T15:04:02.327178+00:00",
"exception": false,
"start_time": "2026-05-27T15:04:02.323581+00:00",
"status": "completed"
},
"tags": []
},
"source": [
"## 7 · Build the graph"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "f90a4db2",
"metadata": {
"execution": {
"iopub.execute_input": "2026-05-27T15:04:02.342739Z",
"iopub.status.busy": "2026-05-27T15:04:02.341687Z",
"iopub.status.idle": "2026-05-27T15:04:08.061047Z",
"shell.execute_reply": "2026-05-27T15:04:08.059034Z"
},
"papermill": {
"duration": 5.730102,
"end_time": "2026-05-27T15:04:08.063372+00:00",
"exception": false,
"start_time": "2026-05-27T15:04:02.333270+00:00",
"status": "completed"
},
"tags": []
},
"outputs": [
{
"data": {
"image/png": "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",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from IPython.display import Image, display\n",
"arch = Reflexion(max_trials=3, reflections_to_recall=3)\n",
"graph = arch.build()\n",
"display(Image(graph.get_graph().draw_mermaid_png()))"
]
},
{
"cell_type": "markdown",
"id": "1fa5060a",
"metadata": {
"papermill": {
"duration": 0.007023,
"end_time": "2026-05-27T15:04:08.082927+00:00",
"exception": false,
"start_time": "2026-05-27T15:04:08.075904+00:00",
"status": "completed"
},
"tags": []
},
"source": [
"## 8 · Live run — 3 structurally-similar haiku tasks\n",
"\n",
"We run **three constrained-haiku tasks** through ONE `Reflexion` instance so failed-trial reflections accumulate. Each task: write a haiku on a different topic, containing two required words, in strict 5-7-5 syllables. The deterministic checker validates all three constraints.\n",
"\n",
"**Watch for:**\n",
"- Trial count **drops** across tasks if memory transfers (task 2 / task 3 should benefit from task 1's lessons).\n",
"- `REFLECTIONS_RECALLED` should be **≥1** on tasks 2 and 3 (assuming memory was populated).\n",
"- If task 1 passes on trial 1, the demo is uninstructive — no reflections were written. The §9 tailor flags this."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "3d8f87be",
"metadata": {
"execution": {
"iopub.execute_input": "2026-05-27T15:04:08.102369Z",
"iopub.status.busy": "2026-05-27T15:04:08.102369Z",
"iopub.status.idle": "2026-05-27T15:04:35.326935Z",
"shell.execute_reply": "2026-05-27T15:04:35.324601Z"
},
"papermill": {
"duration": 27.236027,
"end_time": "2026-05-27T15:04:35.326935+00:00",
"exception": false,
"start_time": "2026-05-27T15:04:08.090908+00:00",
"status": "completed"
},
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"TASK_TAG: glacier\n",
" TRIALS_USED: 1\n",
" SUCCESS: True\n",
" REFLECTIONS_RECALLED: 0\n",
" REFLECTIONS_IN_MEMORY_AFTER: 0\n",
" SYLLABLES_PER_TRIAL: [[5, 7, 5]]\n",
" WORDS_PRESENT_PER_TRIAL: [True]\n",
" FINAL: Frozen silence deep / Centuries of slow descent / Glacial morning calm\n",
"\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"TASK_TAG: subway\n",
" TRIALS_USED: 3\n",
" SUCCESS: False\n",
" REFLECTIONS_RECALLED: 0\n",
" REFLECTIONS_IN_MEMORY_AFTER: 2\n",
" SYLLABLES_PER_TRIAL: [[5, 6, 4], [5, 6, 4], [5, 6, 4]]\n",
" WORDS_PRESENT_PER_TRIAL: [True, True, True]\n",
" FINAL: Midnight subway dark / Rumble of the trains beneath / City's gentle hum\n",
"\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"TASK_TAG: library\n",
" TRIALS_USED: 1\n",
" SUCCESS: True\n",
" REFLECTIONS_RECALLED: 2\n",
" REFLECTIONS_IN_MEMORY_AFTER: 2\n",
" SYLLABLES_PER_TRIAL: [[5, 7, 5]]\n",
" WORDS_PRESENT_PER_TRIAL: [True]\n",
" FINAL: Silent paper halls / Dust settles on forgotten / Ancient wisdom sleeps\n",
"\n",
"TRIALS_PER_TASK: [1, 3, 1] total_reflections_in_memory=2\n"
]
}
],
"source": [
"TASKS = [\n",
" {\"tag\": \"glacier\", \"topic\": \"glacier\", \"required_words\": [\"silence\", \"centuries\"]},\n",
" {\"tag\": \"subway\", \"topic\": \"subway\", \"required_words\": [\"midnight\", \"rumble\"]},\n",
" {\"tag\": \"library\", \"topic\": \"library\", \"required_words\": [\"paper\", \"dust\"]},\n",
"]\n",
"\n",
"arch = Reflexion(max_trials=3, reflections_to_recall=3)\n",
"\n",
"trials_per_task = []\n",
"for t in TASKS:\n",
" w1, w2 = t[\"required_words\"]\n",
" task_text = (\n",
" f'Write a haiku about a {t[\"topic\"]}. '\n",
" f'The haiku MUST contain the words \"{w1}\" and \"{w2}\". '\n",
" f'It MUST follow strict 5-7-5 syllables. '\n",
" f'spec=topic={t[\"topic\"]}; required_words={w1},{w2}'\n",
" )\n",
" r = arch.run(task_text)\n",
" feats = r.metadata[\"evaluator_features\"]\n",
" # Collect per-trial syllable counts + word-presence flags from trace events\n",
" per_trial_syllables = [h[\"features\"][\"syllable_counts\"] for h in r.trace if h.get(\"type\") == \"trial\"]\n",
" per_trial_words = [h[\"features\"][\"required_words_present\"] for h in r.trace if h.get(\"type\") == \"trial\"]\n",
" print(f\"TASK_TAG: {t['tag']}\")\n",
" print(f\" TRIALS_USED: {r.metadata['total_trials']}\")\n",
" print(f\" SUCCESS: {r.metadata['succeeded']}\")\n",
" print(f\" REFLECTIONS_RECALLED: {r.metadata['reflections_recalled_first_trial']}\")\n",
" print(f\" REFLECTIONS_IN_MEMORY_AFTER: {r.metadata['total_reflections_in_memory']}\")\n",
" print(f\" SYLLABLES_PER_TRIAL: {per_trial_syllables}\")\n",
" print(f\" WORDS_PRESENT_PER_TRIAL: {per_trial_words}\")\n",
" print(f\" FINAL: {r.output.strip().replace(chr(10), ' / ')}\")\n",
" print()\n",
" trials_per_task.append(r.metadata[\"total_trials\"])\n",
"\n",
"print(f\"TRIALS_PER_TASK: {trials_per_task} total_reflections_in_memory={len(arch.episodic.episodes)}\")"
]
},
{
"cell_type": "markdown",
"id": "827d79a7",
"metadata": {
"papermill": {
"duration": 0.016594,
"end_time": "2026-05-27T15:04:35.343529+00:00",
"exception": false,
"start_time": "2026-05-27T15:04:35.326935+00:00",
"status": "completed"
},
"tags": []
},
"source": [
"### 8.0 · What just happened, briefly\n",
"\n",
"Three signals to read:\n",
"\n",
"1. **`TRIALS_PER_TASK` should trend downward** if reflection memory is transferring. A pattern like `[2, 1, 1]` means task 1 needed reflection, then later tasks benefitted. A flat `[1, 1, 1]` means the demo was too easy; a flat `[3, 3, 3]` means reflections aren't actually helping.\n",
"2. **`REFLECTIONS_RECALLED` ≥ 1 on tasks 2 and 3.** If it's 0 when memory is non-empty, FAISS recall isn't finding the lessons — usually means the embedding model is too weak for the task texts.\n",
"3. **`SUCCESS` per task.** Reflexion isn't magic — if max_trials runs out, the loop terminates failed. Reflections are still written and benefit *future* tasks."
]
},
{
"cell_type": "markdown",
"id": "9d41595b",
"metadata": {
"papermill": {
"duration": 0.016506,
"end_time": "2026-05-27T15:04:35.360035+00:00",
"exception": false,
"start_time": "2026-05-27T15:04:35.343529+00:00",
"status": "completed"
},
"tags": []
},
"source": [
"### 8.1 · Inspect the lesson library"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "3b9f6125",
"metadata": {
"execution": {
"iopub.execute_input": "2026-05-27T15:04:35.360035Z",
"iopub.status.busy": "2026-05-27T15:04:35.360035Z",
"iopub.status.idle": "2026-05-27T15:04:35.394067Z",
"shell.execute_reply": "2026-05-27T15:04:35.391688Z"
},
"papermill": {
"duration": 0.035066,
"end_time": "2026-05-27T15:04:35.395101+00:00",
"exception": false,
"start_time": "2026-05-27T15:04:35.360035+00:00",
"status": "completed"
},
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Total lessons stored: 2\n",
"\n",
"[lesson 1] (recorded on task='Write a haiku about a subway. The haiku MUST conta...', trial=1)\n",
" root_cause: You under-counted syllables in the second line of the haiku, which had 6 syllables instead of 7.\n",
" correction: Count syllables of each line out loud before submitting and trim or add if not meeting the 5-7-5 requirement.\n",
" reflection: You under-counted syllables in the second line of the haiku, which had 6 syllables instead of 7. To avoid this mistake in the future, count syllables of each line out loud before submitting and trim or add if not meeting the 5-7-5 requirement. This will help you create a haiku that follows the traditional syllable count and is more effective in conveying the intended message. In similar tasks, make sure to pay close attention to the syllable count of each line to ensure that it meets the required structure.\n",
"\n",
"[lesson 2] (recorded on task='Write a haiku about a subway. The haiku MUST conta...', trial=2)\n",
" root_cause: You under-counted syllables in the second line of the haiku, which had 6 syllables instead of 7.\n",
" correction: Count syllables of each line out loud before submitting and trim or add if not meeting the 5-7-5 requirement.\n",
" reflection: You under-counted syllables in the second line of the haiku, which had 6 syllables instead of 7. To avoid this mistake in the future, count syllables of each line out loud before submitting and trim or add if not meeting the 5-7-5 requirement. This will help you create a haiku that follows the traditional syllable count and is more effective in conveying the intended message. In similar tasks, make sure to pay close attention to the syllable count of each line to ensure that it meets the required specifications.\n",
"\n"
]
}
],
"source": [
"print(f\"Total lessons stored: {len(arch.episodic.episodes)}\")\n",
"print()\n",
"for i, ep in enumerate(arch.episodic.episodes, 1):\n",
" md_block = ep.metadata or {}\n",
" print(f\"[lesson {i}] (recorded on task='{md_block.get('task', '?')[:50]}...', trial={md_block.get('trial')})\")\n",
" print(f\" root_cause: {md_block.get('root_cause', '(missing)')}\")\n",
" print(f\" correction: {md_block.get('correction', '(missing)')}\")\n",
" print(f\" reflection: {ep.content}\")\n",
" print()"
]
},
{
"cell_type": "markdown",
"id": "3d9aa9c6",
"metadata": {
"papermill": {
"duration": 0.018952,
"end_time": "2026-05-27T15:04:35.414053+00:00",
"exception": false,
"start_time": "2026-05-27T15:04:35.395101+00:00",
"status": "completed"
},
"tags": []
},
"source": [
"## 9 · What we just observed\n",
"\n",
"The cells above ran **3 structurally-similar haiku tasks** through one `Reflexion` instance, then re-ran task 1 with a fresh instance for a cold-start contrast. The deterministic Python checker decided pass/fail; the reflection LLM wrote a verbal lesson on every failure; lessons accumulated in `arch.episodic`.\n",
"\n",
"### 9.1 · Per-task trial-count + reflection-transfer table\n",
"\n",
"| Tag | Trials used | Success | Reflections recalled (first attempt) | Memory size after | Final haiku |\n",
"|---|---|---|---|---|---|\n",
"| glacier | 1 | ✓ | 0 | 0 | Frozen silence deep / Centuries of slow descent / Glacial morning calm |\n",
"| subway | 3 | ✗ | 0 | 2 | Midnight subway dark / Rumble of the trains beneath / City's gentle hum |\n",
"| library | 1 | ✓ | 2 | 2 | Silent paper halls / Dust settles on forgotten / Ancient wisdom sleeps |\n",
"\n",
"**Summary:** trials per task `[1, 3, 1]`, total lessons in memory after all 3 runs: **2**.\n",
"\n",
"### 9.2 · Did the reflection memory help?\n",
"\n",
"| Comparison | Trials | Reflections recalled | Success |\n",
"|---|---|---|---|\n",
"| Task 1 (`glacier`, no prior memory) | 1 | 0 | ✓ |\n",
"| Task 3 (`library`, 2 lessons recalled) | 1 | 2 | ✓ |\n",
"| Cold-start re-run of `glacier` (fresh Reflexion, empty memory) | 1 | 0 | ✓ |\n",
"\n",
"### 9.3 · Patterns surfaced in this run\n",
"\n",
"- **⚠️ Task 1 (`glacier`) passed on the FIRST trial** — no reflection was written for it, so the agent had nothing in memory when starting task 2. The demo's lesson-transfer effect therefore depends entirely on whatever lessons tasks 2+ produce. If you want to see transfer onto task 2, pick task-1 constraints Llama actually struggles with (e.g., 4-syllable required words that crowd a 5-syllable line).\n",
"\n",
"- **⚠️ Task(s) `subway` exhausted `max_trials` without passing.** Reflexion isn't magic — when reflections don't surface a correction that the next attempt can actually act on, the agent loops failing. The lessons are still stored and can benefit *later* tasks even though this one failed.\n",
"\n",
"- **✅ Memory transferred to task 3 (`library`).** It passed on the first trial with 2 prior lessons recalled — the agent started the task already primed by lessons learned on earlier tasks. This is the architecture's headline behaviour.\n",
"\n",
"- **🔁 All 2 stored lessons share the same `root_cause`** — the agent kept failing the same way and produced near-duplicate reflections. Real production use would dedup on cosine similarity (§ 11.3 extension #2) to avoid memory bloat.\n",
"\n",
"- **⚠️ Cold-start contrast inconclusive**: cold run of `glacier` took 1 trials, same as warm — task 1 was easy enough that memory wasn't the differentiator. The clearer signal is task 3 (above) where 2 recalls + trial-1 pass shows the memory pipeline is wired correctly.\n",
"\n",
"### 9.4 · Verbatim final outputs\n",
"\n",
"**`glacier`** (pass, trial 1, syllables `[[5, 7, 5]]`)\n",
"\n",
"> Frozen silence deep\n",
"> Centuries of slow descent\n",
"> Glacial morning calm\n",
"\n",
"**`subway`** (FAIL, trial 3, syllables `[[5, 6, 4], [5, 6, 4], [5, 6, 4]]`)\n",
"\n",
"> Midnight subway dark\n",
"> Rumble of the trains beneath\n",
"> City's gentle hum\n",
"\n",
"**`library`** (pass, trial 1, syllables `[[5, 7, 5]]`)\n",
"\n",
"> Silent paper halls\n",
"> Dust settles on forgotten\n",
"> Ancient wisdom sleeps\n",
"\n",
"### 9.5 · The lesson library that built up\n",
"\n",
"**Lesson 1** *(from task `Write a haiku about a subway. The haiku MUST conta...…`, trial 1)*\n",
"\n",
"- **root_cause:** You under-counted syllables in the second line of the haiku, which had 6 syllables instead of 7.\n",
"- **correction:** Count syllables of each line out loud before submitting and trim or add if not meeting the 5-7-5 requirement.\n",
"- **stored verbatim:** You under-counted syllables in the second line of the haiku, which had 6 syllables instead of 7. To avoid this mistake in the future, count syllables of each line out loud before submitting and trim or add if not meeting the 5-7-5 requirement. This will help you create a haiku that follows the traditional syllable count and is more effective in conveying the intended message. In similar tasks, mak…\n",
"\n",
"**Lesson 2** *(from task `Write a haiku about a subway. The haiku MUST conta...…`, trial 2)*\n",
"\n",
"- **root_cause:** You under-counted syllables in the second line of the haiku, which had 6 syllables instead of 7.\n",
"- **correction:** Count syllables of each line out loud before submitting and trim or add if not meeting the 5-7-5 requirement.\n",
"- **stored verbatim:** You under-counted syllables in the second line of the haiku, which had 6 syllables instead of 7. To avoid this mistake in the future, count syllables of each line out loud before submitting and trim or add if not meeting the 5-7-5 requirement. This will help you create a haiku that follows the traditional syllable count and is more effective in conveying the intended message. In similar tasks, mak…\n",
"\n",
"### 9.6 · The takeaway\n",
"\n",
"Reflexion only works when **three** things are true simultaneously:\n",
"\n",
"1. **The evaluator is precise enough to surface a *specific* failure feature.** The pure-Python haiku checker covers this (it reports exact syllable counts and which required words are missing, so the reflection LLM has concrete material to write about).\n",
"2. **The reflection LLM phrases the lesson in *transferable* form.** The `_SelfReflection` schema's `correction` field asks for a general imperative (\"count syllables out loud before submitting\"), not a task-specific patch (\"use the word 'centuries' in line 2\").\n",
"3. **The recall step actually finds the relevant lessons.** That's just FAISS doing its job — if it returns 0 episodes when memory is non-empty (auto-flagged above when it happens), the embedding model is too weak for the task texts.\n",
"\n",
"Watch the §9.1 table and the §9.3 flags every run. The architecture's headline behaviour is most visible in the **`Reflections recalled (first attempt)`** column — non-zero on a non-first task = memory pipeline is alive; trial-1 pass on a non-first task = memory pipeline is *effective*."
]
},
{
"cell_type": "markdown",
"id": "07088976",
"metadata": {
"papermill": {
"duration": 0.005614,
"end_time": "2026-05-27T15:04:35.427657+00:00",
"exception": false,
"start_time": "2026-05-27T15:04:35.422043+00:00",
"status": "completed"
},
"tags": []
},
"source": [
"## 10 · Contrast — same task with EMPTY memory\n",
"\n",
"To make the memory-transfer effect concrete, re-run **task 1** with a brand-new `Reflexion()` instance (empty episodic memory) and compare trial count to what the warm-memory run did."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "d91b15fc",
"metadata": {
"execution": {
"iopub.execute_input": "2026-05-27T15:04:35.439669Z",
"iopub.status.busy": "2026-05-27T15:04:35.439669Z",
"iopub.status.idle": "2026-05-27T15:04:37.525095Z",
"shell.execute_reply": "2026-05-27T15:04:37.524059Z"
},
"papermill": {
"duration": 2.094366,
"end_time": "2026-05-27T15:04:37.527077+00:00",
"exception": false,
"start_time": "2026-05-27T15:04:35.432711+00:00",
"status": "completed"
},
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"COLD_START_TASK: glacier\n",
"COLD_START_TRIALS: 1\n",
"COLD_START_SUCCESS: True\n",
"COLD_START_REFLECTIONS_RECALLED: 0\n",
"\n",
"(For comparison: warm-memory run of task 'glacier' used 1 trials with the warm `arch` instance.)\n"
]
}
],
"source": [
"fresh = Reflexion(max_trials=3, reflections_to_recall=3)\n",
"t = TASKS[0]\n",
"w1, w2 = t[\"required_words\"]\n",
"task_text = (\n",
" f'Write a haiku about a {t[\"topic\"]}. '\n",
" f'The haiku MUST contain the words \"{w1}\" and \"{w2}\". '\n",
" f'It MUST follow strict 5-7-5 syllables. '\n",
" f'spec=topic={t[\"topic\"]}; required_words={w1},{w2}'\n",
")\n",
"r_cold = fresh.run(task_text)\n",
"print(f\"COLD_START_TASK: {t['tag']}\")\n",
"print(f\"COLD_START_TRIALS: {r_cold.metadata['total_trials']}\")\n",
"print(f\"COLD_START_SUCCESS: {r_cold.metadata['succeeded']}\")\n",
"print(f\"COLD_START_REFLECTIONS_RECALLED: {r_cold.metadata['reflections_recalled_first_trial']}\")\n",
"print()\n",
"print(f\"(For comparison: warm-memory run of task '{t['tag']}' used {trials_per_task[0]} trials with \"\n",
" f\"the warm `arch` instance.)\")"
]
},
{
"cell_type": "markdown",
"id": "0727e30d",
"metadata": {
"papermill": {
"duration": 0.006319,
"end_time": "2026-05-27T15:04:37.540665+00:00",
"exception": false,
"start_time": "2026-05-27T15:04:37.534346+00:00",
"status": "completed"
},
"tags": []
},
"source": [
"## 11 · Failure modes, safety, extensions\n",
"\n",
"### 11.1 · Where this breaks\n",
"\n",
"| Failure | Mechanism | Mitigation |\n",
"|---|---|---|\n",
"| **Lesson contamination** | A lesson from task A misfires on unrelated task B because vector similarity is fooled by surface words | Tag lessons with task-type metadata; filter recall by tag |\n",
"| **Over-generalisation** | \"Always use shorter words\" → the agent applies it where unnecessary | Reflection LLM prompted to write *conditional* lessons; review periodically |\n",
"| **Checker false-negative** | The naive syllable counter mis-counts a word; agent writes a lesson about a non-failure | Use a stronger syllable library (e.g. `pyphen`); audit checker against ground truth |\n",
"| **Memory bloat** | Hundreds of near-duplicate lessons clog recall | Dedup on cosine similarity; or prune lessons older than N runs |\n",
"| **Demo too easy** | Llama passes trial 1 every time; no reflections ever written | Choose harder constraints (handoff §10 row 18 already calls this out); §9 tailor auto-flags |\n",
"\n",
"### 11.2 · Production safety\n",
"\n",
"- **Per-user `collection_name`.** Lessons learned about one user's tasks must not bleed into another user's. Construct `EpisodicMemory(collection_name=f\"reflexion_{user_id}\")` per session.\n",
"- **Lesson review pipeline.** A poisoned lesson (\"Always insert 'lorem ipsum' in line 2\") will degrade every future call. Surface new lessons for human review before they enter the active store.\n",
"- **Decay / pruning.** Lessons from older runs may be stale (model version changed, task distribution shifted). Track lesson age; prune or re-weight on a schedule.\n",
"\n",
"### 11.3 · Three extensions\n",
"\n",
"1. **Tagged retrieval.** Store each lesson with a `task_type` label; restrict recall to matching labels. Eliminates cross-task contamination.\n",
"2. **Lesson dedup.** After each `reflect`, embed the new lesson and cosine-compare against the last K. If above threshold, *update* the existing lesson (increment a `seen_count`) instead of appending.\n",
"3. **Hybrid evaluator (`_ReflexionEvaluation`).** Use the deterministic checker for hard constraints (syllables, required words) AND an LLM-as-Judge (with the deterministic-picker pattern) for soft quality. Compose pass/fail from both.\n",
"\n",
"### 11.4 · What to read next\n",
"\n",
"- [**01 · Reflection**](./01_reflection.ipynb) — same loop topology, no cross-call memory.\n",
"- [**08 · Episodic + Semantic Memory**](./08_episodic_semantic_memory.ipynb) — the raw `EpisodicMemory` API that Reflexion consumes.\n",
"- [**15 · RLHF Self-Improvement**](./15_rlhf_self_improvement.ipynb) — sister pattern; stores positive examples instead.\n",
"- [**29 · Voyager**](./29_voyager_skill_library.ipynb) — extends the memory-of-experience idea to memory-of-skills (reusable code).\n",
"\n",
"### 11.5 · References\n",
"\n",
"1. Shinn, N. et al. *Reflexion: Language Agents with Verbal Reinforcement Learning.* NeurIPS 2023. [arXiv:2303.11366](https://arxiv.org/abs/2303.11366)\n",
"2. Madaan, A. et al. *Self-Refine: Iterative Refinement with Self-Feedback.* NeurIPS 2023. [arXiv:2303.17651](https://arxiv.org/abs/2303.17651) — the underlying self-critique loop.\n",
"3. Park, J. S. et al. *Generative Agents.* UIST 2023. [arXiv:2304.03442](https://arxiv.org/abs/2304.03442) — episodic memory + reflection pattern in agent simulations.\n",
"4. Wang, G. et al. *Voyager: An Open-Ended Embodied Agent with Large Language Models.* 2023. [arXiv:2305.16291](https://arxiv.org/abs/2305.16291) — skill-library extension."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.0"
},
"papermill": {
"default_parameters": {},
"duration": 39.204476,
"end_time": "2026-05-27T15:04:38.532706+00:00",
"environment_variables": {},
"exception": null,
"input_path": "all-agentic-architectures/notebooks/18_reflexion.ipynb",
"output_path": "all-agentic-architectures/notebooks/18_reflexion.ipynb",
"parameters": {},
"start_time": "2026-05-27T15:03:59.328230+00:00",
"version": "2.7.0"
}
},
"nbformat": 4,
"nbformat_minor": 5
}