DEV Community

weiwuji
weiwuji

Posted on

Why Your AI Agent Forgets Everything Overnight — From Prompt to Loop Engineering

The Pain: You spent an afternoon tuning your agent. Next morning, it stares at you blankly — as if yesterday never happened.
What You'll Learn: The 4-stage evolution (Prompt → Context → Harness → Loop), and a runnable 50-line Loop Agent that persists memory.


0. Prerequisites

  • Python ≥ 3.10
  • pip install openai (openai ≥ 1.0.0)
  • OpenAI API Key
  • OS: macOS / Linux / Windows WSL

Goal: Copy-paste the code, run it, and see a Loop Agent that doesn't forget.


1. The Pain: Why Does Your Agent Forget Overnight?

At 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.

Next morning, you open the conversation full of hope — and the agent looks at you blankly, as if none of it ever happened.

You check the logs. No errors. No exceptions. The agent regenerated everything — it just "forgot" where it stopped yesterday.

This 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.


2. Four-Stage Evolution: Prompt → Context → Harness → Loop

4-Stage Evolution: Prompt to Context to Harness to Loop
4-Stage Evolution — each stage solves the previous flaw but adds its own constraint.

To understand this, let's use a simple evolution framework:

Stage What You Do Fatal Flaw
Prompt Engineering Write task description, examples, format into prompt Any unexpected input crashes output
Context Engineering Stuff history + intermediate results into context window Token cost grows linearly, hits window limit
Harness Engineering Add tool calling, structured output, error capture Framework built, but agent is still "one-shot"
Loop Engineering Build closed loop: state + memory + feedback + retry + persistence True engineering — agent starts to "live"

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.


3. Minimal Runnable Loop Agent (50 lines)

Here's the complete, copy-pasteable, runnable Loop Agent. Run it first, then understand it line by line.

import json, os, time
from pathlib import Path
from datetime import datetime
from openai import OpenAI

client = OpenAI()  # reads OPENAI_API_KEY from env

STATE_FILE = Path("./agent_state.json")
MEMORY_FILE = Path("./agent_memory.json")
MAX_RETRIES = 3

def load_memory() -> dict:
    if MEMORY_FILE.exists():
        return json.loads(MEMORY_FILE.read_text())
    return {"facts": {}, "errors": []}

def save_memory(mem: dict):
    MEMORY_FILE.write_text(json.dumps(mem, indent=2, ensure_ascii=False))

def load_state() -> dict:
    if STATE_FILE.exists():
        return json.loads(STATE_FILE.read_text())
    return {"state": "idle", "step": 0}

def save_state(state: str, step: int):
    STATE_FILE.write_text(json.dumps({
        "state": state, "step": step,
        "updated_at": datetime.now().isoformat()
    }, indent=2, ensure_ascii=False))

def execute(task: str, memory: dict, error_ctx: str = "") -> str:
    system = f"You are a task-execution agent. Known facts: {json.dumps(memory.get('facts', {}), ensure_ascii=False)}"
    if error_ctx:
        system += f"\nLast error: {error_ctx}\nPlease fix."
    resp = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "system", "content": system},
                  {"role": "user", "content": task}]
    )
    return resp.choices[0].message.content

def check(output: str, keywords: list[str]) -> tuple[bool, str]:
    missing = [kw for kw in keywords if kw not in output]
    if missing:
        return False, f"Missing: {missing}"
    if len(output) < 20:
        return False, "Output too short"
    return True, ""

def run(task: str, keywords: list[str]):
    memory = load_memory()
    save_state("running", 0)

    for i in range(1, MAX_RETRIES + 1):
        error = memory["errors"][-1]["reason"] if memory["errors"] else ""
        output = execute(task, memory, error)
        ok, reason = check(output, keywords)

        if ok:
            save_state("done", i)
            memory["facts"][task[:30]] = output[:100]
            save_memory(memory)
            return f"OK on attempt {i}:\n{output}"
        else:
            save_state("retrying", i)
            memory["errors"].append(
                {"task": task, "reason": reason, "attempt": i}
            )
            save_memory(memory)
            print(f"Retry {i} failed: {reason}")
            time.sleep(1)

    save_state("failed", MAX_RETRIES)
    return f"All {MAX_RETRIES} attempts failed"

if __name__ == "__main__":
    result = run(
        task="List 3 Python web frameworks and their features",
        keywords=["Flask", "Django", "FastAPI"]
    )
    print(result)
Enter fullscreen mode Exit fullscreen mode

Copy this to loop_agent.py and run it.


4. Verification

# 1. Install
pip install openai

# 2. Set API key
export OPENAI_API_KEY="sk-..."

# 3. First run
python loop_agent.py
Enter fullscreen mode Exit fullscreen mode

Expected output:

OK on attempt 1:
The 3 mainstream Python web frameworks:
1. **Flask**: lightweight micro-framework...
2. **Django**: full-stack, batteries included...
3. **FastAPI**: modern async, auto OpenAPI docs...
Enter fullscreen mode Exit fullscreen mode

Now verify persistence — close the terminal, reopen, run again:

# 4. Check state file
cat agent_state.json
Enter fullscreen mode Exit fullscreen mode

Expected:

{
  "state": "done",
  "step": 1,
  "updated_at": "2026-07-01T12:00:00.000000"
}
Enter fullscreen mode Exit fullscreen mode
# 5. Check memory file
cat agent_memory.json
Enter fullscreen mode Exit fullscreen mode

Expected: the facts dict contains your task and the output.

# 6. Run again — agent loads memory automatically
python loop_agent.py
Enter fullscreen mode Exit fullscreen mode

The agent reads facts from agent_memory.json and passes them as known context. That's the "remembers overnight" mechanism.


5. Six Components Mapped to the Code

Component Code Location Description
Memory Store load_memory() / save_memory() Persist memory to JSON
State Machine load_state() / save_state() Persist state to JSON
Executor execute() Call OpenAI API
Checker check() Verify keywords present
Task Scheduler run() Retry loop + state transitions
Guardrails MAX_RETRIES = 3 Retry limit

6. Common Errors

Error 1: ModuleNotFoundError: No module named 'openai'

pip install openai
Enter fullscreen mode Exit fullscreen mode

Error 2: openai.AuthenticationError: 401
You didn't set the API key, or it's invalid.

export OPENAI_API_KEY="sk-..."
Enter fullscreen mode Exit fullscreen mode

Error 3: Agent output missing Flask/Django/FastAPI
This 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:

Retry 1 failed: Missing: ['Flask', 'Django', 'FastAPI']
Retry 2 failed: Missing: ['Django']
OK on attempt 3:
...
Enter fullscreen mode Exit fullscreen mode

Error 4: API timeout or rate limit
gpt-4o-mini is very cheap (~$0.00015/call). If rate-limited, increase time.sleep(1) or check your OpenAI dashboard.


7. Next Steps From the 50 Lines

Now 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.

Extend it:

  • Swap ChromaDB for JSON → vector memory
  • Hook Celery → real async task queue
  • Add Feishu/Slack webhook → completion notifications
  • Add structured logs + Trace ID → observability

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.


Next article: How Much Memory Does Your Agent Need? — Memory Store Selection Guide

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.

Top comments (0)