cd /news/artificial-intelligence/why-your-ai-agent-forgets-everything… · home topics artificial-intelligence article
[ARTICLE · art-82716] src=dev.to ↗ pub= topic=artificial-intelligence verified=true sentiment=· neutral

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

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.

read5 min views1 publishedAug 1, 2026

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.

pip install openai

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

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.

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.

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)

Copy this to loop_agent.py

and run it.

pip install openai

export OPENAI_API_KEY="sk-..."

python loop_agent.py

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

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

cat agent_state.json

Expected:

{
  "state": "done",
  "step": 1,
  "updated_at": "2026-07-01T12:00:00.000000"
}
cat agent_memory.json

Expected: the facts

dict contains your task and the output.

python loop_agent.py

The agent reads facts

from agent_memory.json

and passes them as known context. That's the "remembers overnight" mechanism.

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

Error 1: ModuleNotFoundError: No module named 'openai'

pip install openai

Error 2: openai.AuthenticationError: 401

You didn't set the API key, or it's invalid.

export OPENAI_API_KEY="sk-..."

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

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.

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:

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.

── more in #artificial-intelligence 4 stories · sorted by recency
── more on @openai 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/why-your-ai-agent-fo…] indexed:0 read:5min 2026-08-01 ·