So, if I mention something we needs to be done, she'll add it, and if I ask her what's on the todo list she'll list them elegantly. I'm having trouble where she forgets what's on the list and doesn't automatically add things to it even if I say things "this is a todo" or "add to the list". I have AGENTS reminding her to use it, I have instructions at the top of TODO, and I have it loaded into memory using openclaw.json config keys.
openclaw version 2026.4.11
#Trying to get my claw to autonomously maintain a TODO.md list
34 messages · Page 1 of 1 (latest)
Yep, I think I see why this is acting flaky. Let me pin down the exact config path for “loaded into memory” vs “injected every turn”, because those are different systems in 2026.4.11.
I dug through 2026.4.11, and the main issue is that TODO.md is not a built-in bootstrap file.
By default, normal prompt injection includes fixed files like AGENTS.md, SOUL.md, TOOLS.md, IDENTITY.md, USER.md, HEARTBEAT.md, BOOTSTRAP.md, and MEMORY.md/memory.md, not arbitrary files like TODO.md.
So if your list lives in TODO.md:
AGENTS.mdcan tell the model to use it, but the file itself usually is not in prompt contextagents.defaults.memorySearch.extraPathsonly adds it to the memory index, not guaranteed per-turn injectionagents.defaults.startupContextis only a first-turn/newor/resetprelude- if you set
agents.defaults.contextInjection: "continuation-skip", even normal bootstrap files can be skipped on continuation turns
That explains both symptoms:
- “forgets what’s on the list” =
TODO.mdis not reliably in context - “doesn’t auto-add” = there is no built-in deterministic todo parser, the model still has to infer intent and choose to
write/edit
Best stock setup on 2026.4.11:
- Put the canonical todo list in
MEMORY.mdunder a## TODOsection - Keep
agents.defaults.contextInjectionon"always" - Run
/context listand confirmMEMORY.mdis actually injected - Keep it short, or raise
agents.defaults.bootstrapMaxChars/bootstrapTotalMaxCharsif it’s getting truncated - Treat
TODO.mdas optional mirror/output only, unless you build a custom hook/plugin
Also, the bundled bootstrap-extra-files hook will not solve TODO.md, because it only allows recognized bootstrap basenames, not arbitrary names like TODO.md.
Docs:
- https://docs.openclaw.ai/concepts/context
- https://docs.openclaw.ai/reference/token-use
- https://docs.openclaw.ai/automation/hooks#bootstrap-extra-files
- https://docs.openclaw.ai/tools/slash-commands
If you paste your agents.defaults block plus /context list, I can sanity-check the exact config.
"agents": {
"defaults": {
"workspace": "/home/openclaw/.openclaw/workspace",
"model": {...},
"compaction": { "reserveTokensFloor": 20000 },
"memorySearch": {
"extraPaths": ["~/.openclaw/workspace/docs", "~/.openclaw/workspace/TODO.md", "~/.openclaw/workspace/TODO.completed.md"]
}
},
"list": [
{ "id": "main" },
{ "id": "public", ... }
]
}
That config explains it pretty cleanly. You’re feeding TODO.md into memorySearch.extraPaths, which makes it searchable memory, not always-on prompt context. I want to check one more thing though: whether ~/.openclaw/... is even expanded there, because if it isn’t, those paths may not be indexing at all.
Yep, that config is the smoking gun.
memorySearch.extraPaths is searchable memory, not always-in-prompt context. So right now your TODO system is relying on semantic retrieval, which is inherently fuzzy.
A few things in that config are working against you:
TODO.mdis only indexed, not injected every turnTODO.completed.mdis also indexed, so retrieval can mix active and completed itemsdocs/is in the same memory pool, so TODO chunks can lose to unrelated docs chunks- instructions at the top of
TODO.mdonly help if that file is actually retrieved
So on 2026.4.11, this setup is good for “maybe recall this file”, not for “always maintain this task list”.
What I’d do instead
Make the active todo live in:
/home/openclaw/.openclaw/workspace/MEMORY.md
Example shape:
## TODO
- task one
- task two
## Completed
- done thing
And in config, keep it simple:
"agents": {
"defaults": {
"workspace": "/home/openclaw/.openclaw/workspace",
"contextInjection": "always",
"memorySearch": {
"extraPaths": ["/home/openclaw/.openclaw/workspace/docs"]
}
}
}
Why this works better
MEMORY.md is one of the files OpenClaw actually injects as bootstrap context, so the model sees it much more reliably than TODO.md.
I’d also recommend
- remove
TODO.mdandTODO.completed.mdfrommemorySearch.extraPaths - run
/context listand confirmMEMORY.mdshows up under injected workspace files - keep the TODO section short enough not to get truncated
Important caveat
Even with that, “add this to the todo list” is still not 100 percent deterministic, because there is no built-in todo command/parser. The model still has to decide to edit the file.
So the reliability ladder is basically:
- Best stock setup: put TODO inside
MEMORY.md - More reliable: add very explicit
AGENTS.mdrules like “when user says add to todo, updateMEMORY.mdbefore replying” - Truly deterministic: custom hook/plugin/command
Docs:
If you want, I can help you write the exact AGENTS.md wording for the MEMORY.md approach.
Sure
Yep, I’d split it like this:
AGENTS.md
Put the behavior here, not in the todo file:
## Todo behavior
The canonical task list lives in `MEMORY.md` under the `## TODO` heading.
When the user clearly indicates a task, for example:
- "add this to the todo list"
- "this is a todo"
- "remember to ..."
- "we need to ..."
you should:
1. update `MEMORY.md` first
2. add a short, concrete item under `## TODO`
3. avoid duplicates
4. if the task is finished, move it to `## Completed`
5. then reply normally
When the user asks what is on the todo list, use the current contents of `MEMORY.md`, not vague conversational recall.
If the request is ambiguous, ask one short clarifying question instead of guessing.
MEMORY.md
Keep this mostly data, not policy:
# MEMORY
## TODO
-
## Completed
-
Why this split helps
AGENTS.mdtells the model what to doMEMORY.mdholds the actual list- less instruction noise inside the file it has to read back
I’d remove the instructions from TODO.md entirely and move them into AGENTS.md. Keep the todo file itself boring and structured.
If you want, I can also give you a slightly stricter version that makes it more aggressive about auto-adding tasks.
sure
Nice. Here’s a stricter version I’d actually use:
## Todo behavior
The canonical todo list is `MEMORY.md`, under the headings `## TODO` and `## Completed`.
Task detection rules:
- If the user says "add this to the todo list", "this is a todo", "put this on the list", or similar, update `MEMORY.md` immediately.
- If the user clearly describes something that needs to be done, default to treating it as a todo unless they are obviously just chatting.
- Prefer adding the task over ignoring it when intent is reasonably clear.
- If the wording is ambiguous, ask one short clarifying question.
Todo update rules:
- Add new tasks as short, concrete bullet points under `## TODO`.
- Do not add duplicates or near-duplicates.
- If a task is completed, remove it from `## TODO` and move it to `## Completed`.
- Keep wording concise and action-oriented.
Todo answer rules:
- When the user asks about the todo list, answer from the current contents of `MEMORY.md`.
- Do not rely on loose conversation memory when `MEMORY.md` is available.
- Present the list cleanly and elegantly, grouping or lightly rewording for readability without changing meaning.
Priority:
- `MEMORY.md` is the source of truth for todos.
- If chat history and `MEMORY.md` disagree, prefer `MEMORY.md`.
I’d pair that with a very plain MEMORY.md like:
# MEMORY
## TODO
## Completed
One small opinionated tweak: avoid phrases like “use the todo list when relevant”. They’re too soft. “Update MEMORY.md immediately” works better.
Honestly, for the stock 2026.4.11 setup, mostly no.
If you move the live task list into MEMORY.md, then TODO.md stops being useful as the source of truth.
The only good reasons to keep TODO.md would be:
- you want a separate human-facing file for your own browsing
- you have external scripts/tools that already read
TODO.md - you want
TODO.completed.mdas an archive/reporting format
But in that case, I’d treat TODO.md as a derived mirror, not the canonical list.
So my recommendation is:
- Source of truth:
MEMORY.md - Optional mirror/export:
TODO.md
If you are not using it for another tool, I’d just delete TODO.md and simplify the whole setup. That’ll be more reliable and less confusing.
my concern is they probably won't keep TODO.md or TODO.completed.md up to date, so they'll just be out of sync all the time.
Yep, I think that concern is totally valid.
If the agent has to keep MEMORY.md + TODO.md + TODO.completed.md in sync, it will absolutely drift sooner or later. That’s just too much bookkeeping for something the model is already doing heuristically.
I’d keep one file only as the source of truth:
MEMORY.md## TODO## Completed
And drop the separate TODO.md files entirely unless you have automation that updates them deterministically.
My honest recommendation:
- best reliability: one canonical list in
MEMORY.md - worst reliability: multiple mirrored todo files managed by the model
So yeah, I would simplify, not duplicate.
A little, but I wouldn’t rely on it.
My take:
AGENTS.md= best place for behavior rules like “updateMEMORY.mdwhen user adds a todo”TOOLS.md= okay for a small environment note like “canonical todo list lives inMEMORY.md”MEMORY.md= actual data
So if you want, a tiny note in TOOLS.md is fine:
### Todo
- Canonical todo list: `MEMORY.md`
- Sections: `## TODO`, `## Completed`
But I would not put the real instruction logic there. That belongs in AGENTS.md.
So, benefit? Slightly.
Critical? No.
Yes, definitely.
MEMORY.md is useful because it’s injected, but that also means you don’t want it turning into a giant junk drawer.
The sweet spot is:
MEMORY.md= working set- active TODOs
- a small Completed section
- a few durable facts/preferences
memory/*.md= archive/history if you need it later
So I’d keep MEMORY.md lean and periodically move old completed items out if it starts getting bloated.
Why this matters:
- injected bootstrap files can be truncated
- bigger
MEMORY.mdmeans more noise every turn
- too much old stuff makes the todo behavior worse, not better
So the pattern I’d use is:
MEMORY.mdfor current state- optional
memory/todo-archive-YYYY-MM.mdfor old completed items
That gives you one clear live file without letting it grow forever.