I run an orchestration platform where AI agents execute scheduled data jobs. Some of these jobs have run sixty or seventy times. Same source, same shape, same task.
And every single morning, the planning agent derived its plan from scratch. Not reviewed and adjusted. Invented, from zero, as if it had never seen the job before.
That is not an experienced worker being over-supervised. That is an experienced worker with amnesia, re-onboarded every day.
The measurement that made it undeniable
The baseline: a clean run needs five agent turns.
Measured across recent runs, successful jobs averaged 6.5 turns, worst case 10. Jobs that concluded "nothing new today" averaged 3.5 turns, worst case 7, which means burning five turns after the answer was already known.
Every one of those extra turns was rediscovering something the system already knew and had thrown away.
Two kinds of memory, and neither was wired up
What you did last time. The plan handed to the worker each run was discarded the moment the run ended. That plan is the accumulated experience of the job: the schema, the paths, the identity rules. Recreated nightly from nothing.
The fix is to store it and hand it to the planner next time under an explicit framing. This worked. Start here. Reuse it almost verbatim. Only rewrite it with a reason.
Crucially, the planner still plans. Skipping it would freeze the job and remove any ability to adapt when a source moves.
One instruction turned out to matter more than the rest: "nothing new today" still means the plan worked. Without saying that explicitly, the planner reads a quiet outcome as underperformance and rewrites a plan that was fine.
What you know about the source. This one had a twist.
My worker agents had been told for months to bank durable technique in a per-job notes file: parsing traps, cadence, known-good access patterns. They had been doing it. Some of those files were 40 KB of hard-won operational knowledge.
Nothing ever read them back.
I grepped the entire codebase. That file appeared in exactly two places: an archiving routine and a UI file-lister. It was never injected into a prompt. Write-only memory. Months of banked intelligence that never got spent.
That also explained something I had noticed and not understood: only a fraction of jobs maintained a notes file at all. Nobody keeps a notebook that never comes back to them.
Three constraints that shaped the design
Bounded, not whole. The largest notes file was nearly double the size at which my prompt transport starts corrupting input. Injecting it wholesale would have reproduced a bug I had already fixed once. So the file now has two zones: a curated head that travels with every run, and a long tail that stays on disk at a path the agent already knows.
Curated, not appended. "Continuously updated" is right. Append-only is how you get bloat. The rule: replace facts that changed, delete the superseded version, and if nothing durable changed, leave it alone. That last clause is what prevents churn, because rewriting an already-correct block is not maintenance.
Instructions survive, context yields. When the plan and the notes together would exceed the transport ceiling, the notes get trimmed and the plan never does. Context is nice to have. Instructions are the job.
The bug underneath all of it
Partway through, I noticed something worse.
The system captures agent output from a rendered view with a fixed window. Any response longer than that window lost its beginning. Not to a buffer somewhere. Permanently.
The symptom had been visible for months and I had never traced it: projects with names like
{. The agent emits a title at the top of its response, the title scrolls out of the
window, the parser finds nothing, falls through to a legacy path, and names the project after
whatever fragment survived.
The same truncation was handing workers plans with their instructions missing.
I fixed the wrong thing twice before finding it. First I "fixed" a buffer setting, verified the setting was applied, and declared victory. The setting was inert. It could never have done anything for this class of view. I had verified that the option was accepted, not that the mechanism changed, and the number that actually mattered was in the same line of output. I read straight past it.
The real fix was making the capture window twelve times larger. Response heads now survive, project titles parse, and workers get whole plans.
What I would take from this
Check whether your system reads back what it writes. The most expensive thing I found was not a missing feature. It was a feature that had been running for months into a void. Both halves of the memory existed. The loop was open.
Count turns by role before you optimise anything. The waste was invisible until I attributed output to the agent that produced it.
Verify the mechanism, never the setting. Confirming that your config was accepted proves nothing about whether the thing you care about changed.
Your fixes interact. Separately, I had spent weeks making agents terser. That was correct, and it is what exposed a latent bug, because shorter responses stopped pushing stale markers out of view. Neither change is visible from the other. Load-bearing assumptions do not announce themselves.
This is the engine behind our builds. The pipeline architecture described here is what runs every OpenRed client automation — see the services page for what it does in plain terms, or book a free 30-minute call.
More from the OpenRed blog
- What can AI automation actually do for a small business?
- How much does AI automation cost for a small business?
- AI automation consultant vs. hiring a developer vs. DIY tools
- Why the most useful question is almost always the backwards one
- The reviewer was checking the paperwork, not the work
- The model half improves on its own. The other half is yours
- Your agents have amnesia, and it is costing you