{"slug": "why-your-ai-agent-forgets-everything-overnight-from-prompt-to-loop-engineering", "title": "Why Your AI Agent Forgets Everything Overnight — From Prompt to Loop Engineering", "summary": "A developer outlines the evolution from prompt engineering to loop engineering, presenting a 50-line Python agent that persists memory across sessions using OpenAI's API. The agent stores state and memory in JSON files, enabling it to resume tasks after interruptions, addressing the common issue of AI agents forgetting overnight.", "body_md": "The Pain: You spent an afternoon tuning your agent. Next morning, it stares at you blankly — as if yesterday never happened.\n\nWhat You'll Learn: The 4-stage evolution (Prompt → Context → Harness → Loop), and a runnable 50-line Loop Agent that persists memory.\n\n`pip install openai`\n\n(openai ≥ 1.0.0)**Goal**: Copy-paste the code, run it, and see a Loop Agent that doesn't forget.\n\nAt 2 AM, you finally got that multi-step workflow working. The agent followed your carefully designed prompt — data fetching, cleaning, analysis, charting. You close your laptop, satisfied.\n\nNext morning, you open the conversation full of hope — and the agent looks at you blankly, as if none of it ever happened.\n\nYou check the logs. No errors. No exceptions. The agent regenerated everything — it just \"forgot\" where it stopped yesterday.\n\nThis isn't a joke. It's the nightmare every serious Agent developer experiences. The root cause isn't \"the model isn't smart enough.\" It's a more fundamental fact: **your agent was never designed to survive the night.**\n\nTo understand this, let's use a simple evolution framework:\n\n| Stage | What You Do | Fatal Flaw |\n|---|---|---|\nPrompt Engineering |\nWrite task description, examples, format into prompt | Any unexpected input crashes output |\nContext Engineering |\nStuff history + intermediate results into context window | Token cost grows linearly, hits window limit |\nHarness Engineering |\nAdd tool calling, structured output, error capture | Framework built, but agent is still \"one-shot\" |\nLoop Engineering |\nBuild closed loop: state + memory + feedback + retry + persistence | True engineering — agent starts to \"live\" |\n\n**Loop Engineering isn't a rejection of Prompt Engineering — it's a transcendence.** Prompt still matters. But it's the engine, and you can't drive an engine like a car.\n\nHere's the complete, copy-pasteable, runnable Loop Agent. Run it first, then understand it line by line.\n\n``` python\nimport json, os, time\nfrom pathlib import Path\nfrom datetime import datetime\nfrom openai import OpenAI\n\nclient = OpenAI()  # reads OPENAI_API_KEY from env\n\nSTATE_FILE = Path(\"./agent_state.json\")\nMEMORY_FILE = Path(\"./agent_memory.json\")\nMAX_RETRIES = 3\n\ndef load_memory() -> dict:\n    if MEMORY_FILE.exists():\n        return json.loads(MEMORY_FILE.read_text())\n    return {\"facts\": {}, \"errors\": []}\n\ndef save_memory(mem: dict):\n    MEMORY_FILE.write_text(json.dumps(mem, indent=2, ensure_ascii=False))\n\ndef load_state() -> dict:\n    if STATE_FILE.exists():\n        return json.loads(STATE_FILE.read_text())\n    return {\"state\": \"idle\", \"step\": 0}\n\ndef save_state(state: str, step: int):\n    STATE_FILE.write_text(json.dumps({\n        \"state\": state, \"step\": step,\n        \"updated_at\": datetime.now().isoformat()\n    }, indent=2, ensure_ascii=False))\n\ndef execute(task: str, memory: dict, error_ctx: str = \"\") -> str:\n    system = f\"You are a task-execution agent. Known facts: {json.dumps(memory.get('facts', {}), ensure_ascii=False)}\"\n    if error_ctx:\n        system += f\"\\nLast error: {error_ctx}\\nPlease fix.\"\n    resp = client.chat.completions.create(\n        model=\"gpt-4o-mini\",\n        messages=[{\"role\": \"system\", \"content\": system},\n                  {\"role\": \"user\", \"content\": task}]\n    )\n    return resp.choices[0].message.content\n\ndef check(output: str, keywords: list[str]) -> tuple[bool, str]:\n    missing = [kw for kw in keywords if kw not in output]\n    if missing:\n        return False, f\"Missing: {missing}\"\n    if len(output) < 20:\n        return False, \"Output too short\"\n    return True, \"\"\n\ndef run(task: str, keywords: list[str]):\n    memory = load_memory()\n    save_state(\"running\", 0)\n\n    for i in range(1, MAX_RETRIES + 1):\n        error = memory[\"errors\"][-1][\"reason\"] if memory[\"errors\"] else \"\"\n        output = execute(task, memory, error)\n        ok, reason = check(output, keywords)\n\n        if ok:\n            save_state(\"done\", i)\n            memory[\"facts\"][task[:30]] = output[:100]\n            save_memory(memory)\n            return f\"OK on attempt {i}:\\n{output}\"\n        else:\n            save_state(\"retrying\", i)\n            memory[\"errors\"].append(\n                {\"task\": task, \"reason\": reason, \"attempt\": i}\n            )\n            save_memory(memory)\n            print(f\"Retry {i} failed: {reason}\")\n            time.sleep(1)\n\n    save_state(\"failed\", MAX_RETRIES)\n    return f\"All {MAX_RETRIES} attempts failed\"\n\nif __name__ == \"__main__\":\n    result = run(\n        task=\"List 3 Python web frameworks and their features\",\n        keywords=[\"Flask\", \"Django\", \"FastAPI\"]\n    )\n    print(result)\n```\n\nCopy this to `loop_agent.py`\n\nand run it.\n\n```\n# 1. Install\npip install openai\n\n# 2. Set API key\nexport OPENAI_API_KEY=\"sk-...\"\n\n# 3. First run\npython loop_agent.py\n```\n\nExpected output:\n\n```\nOK on attempt 1:\nThe 3 mainstream Python web frameworks:\n1. **Flask**: lightweight micro-framework...\n2. **Django**: full-stack, batteries included...\n3. **FastAPI**: modern async, auto OpenAPI docs...\n```\n\nNow verify persistence — close the terminal, reopen, run again:\n\n```\n# 4. Check state file\ncat agent_state.json\n```\n\nExpected:\n\n```\n{\n  \"state\": \"done\",\n  \"step\": 1,\n  \"updated_at\": \"2026-07-01T12:00:00.000000\"\n}\n# 5. Check memory file\ncat agent_memory.json\n```\n\nExpected: the `facts`\n\ndict contains your task and the output.\n\n```\n# 6. Run again — agent loads memory automatically\npython loop_agent.py\n```\n\nThe agent reads `facts`\n\nfrom `agent_memory.json`\n\nand passes them as known context. **That's the \"remembers overnight\" mechanism.**\n\n| Component | Code Location | Description |\n|---|---|---|\n| Memory Store |\n`load_memory()` / `save_memory()`\n|\nPersist memory to JSON |\n| State Machine |\n`load_state()` / `save_state()`\n|\nPersist state to JSON |\n| Executor | `execute()` |\nCall OpenAI API |\n| Checker | `check()` |\nVerify keywords present |\n| Task Scheduler | `run()` |\nRetry loop + state transitions |\n| Guardrails | `MAX_RETRIES = 3` |\nRetry limit |\n\n**Error 1: ModuleNotFoundError: No module named 'openai'**\n\n```\npip install openai\n```\n\n**Error 2: openai.AuthenticationError: 401**\n\nYou didn't set the API key, or it's invalid.\n\n```\nexport OPENAI_API_KEY=\"sk-...\"\n```\n\n**Error 3: Agent output missing Flask/Django/FastAPI**\n\nThis is normal! LLMs don't always follow instructions perfectly. That's exactly the Loop Agent's value — the Checker detects missing keywords, rejects the output, and auto-retries. You'll see:\n\n```\nRetry 1 failed: Missing: ['Flask', 'Django', 'FastAPI']\nRetry 2 failed: Missing: ['Django']\nOK on attempt 3:\n...\n```\n\n**Error 4: API timeout or rate limit**\n\n`gpt-4o-mini`\n\nis very cheap (~$0.00015/call). If rate-limited, increase `time.sleep(1)`\n\nor check your OpenAI dashboard.\n\nNow you have a complete runnable Loop Agent. It uses plain JSON files for persistence — which is exactly what lets you touch every component by hand.\n\nExtend it:\n\n**Loop Engineering isn't a package you install. It's a shift in architecture thinking.** Starting from these 50 lines, you're standing at the threshold of stage 4.\n\n**Next article**: How Much Memory Does Your Agent Need? — Memory Store Selection Guide\n\n*About the author: Wu Ji (无记) — AI & digitalization practitioner focused on Agent engineering, Loop Engineering, and digital transformation. Practical, hands-on tutorials — follow along and it just works.*", "url": "https://wpnews.pro/news/why-your-ai-agent-forgets-everything-overnight-from-prompt-to-loop-engineering", "canonical_source": "https://dev.to/weiwuji/why-your-ai-agent-forgets-everything-overnight-from-prompt-to-loop-engineering-4b96", "published_at": "2026-08-01 03:01:33+00:00", "updated_at": "2026-08-01 03:38:29.605812+00:00", "lang": "en", "topics": ["artificial-intelligence", "ai-agents", "developer-tools", "large-language-models"], "entities": ["OpenAI", "gpt-4o-mini"], "alternates": {"html": "https://wpnews.pro/news/why-your-ai-agent-forgets-everything-overnight-from-prompt-to-loop-engineering", "markdown": "https://wpnews.pro/news/why-your-ai-agent-forgets-everything-overnight-from-prompt-to-loop-engineering.md", "text": "https://wpnews.pro/news/why-your-ai-agent-forgets-everything-overnight-from-prompt-to-loop-engineering.txt", "jsonld": "https://wpnews.pro/news/why-your-ai-agent-forgets-everything-overnight-from-prompt-to-loop-engineering.jsonld"}}