OpenHands Remembers Its Sessions. Your Nightly Runs Still Wake Up Blank.
OpenHands Remembers Its Sessions. Your Nightly Runs Still Wake Up Blank. You run an OpenHands agent every night at 2 AM. It sweeps the repo, triages the open pull requests, and leaves a summary of what needs your eyes in the morning. The first week is great. By week three, the nightly runs start re-flagging PRs you already reviewed, re-discovering the same flaky test, and re-asking which services are safe to touch, even though the agent resolved all of that last month. So does OpenHands rememb
OpenHands Remembers Its Sessions. Your Nightly Runs Still Wake Up Blank.
You run an OpenHands agent every night at 2 AM. It sweeps the repo, triages the open pull requests, and leaves a summary of what needs your eyes in the morning. The first week is great. By week three, the nightly runs start re-flagging PRs you already reviewed, re-discovering the same flaky test, and re-asking which services are safe to touch, even though the agent resolved all of that last month.
So does OpenHands remember between sessions? The honest answer is: it remembers what it wrote down, where you told it to write it, on the machine you run it on. Everything else wakes up blank.
What actually persists in OpenHands
There are two separate memory stories in OpenHands, and they answer different questions.
Story one: the app's session data. In the standard OpenHands setup, session data lives in memory. If the service restarts, previous sessions become invalid, because a new secret is generated and the old session records can no longer be recovered. The UI usually offers to resume a session, but after a restart the resume often lands you in a fresh chat anyway. The documented fix is in config.toml: set file_store="local" with an absolute file_store_path, and pin a fixed jwt_secret so session identifiers stay valid across restarts. With that configuration, sessions persist on disk. Without it, a container restart, a redeploy, or a machine reboot wipes the session list clean.
Story two: the SDK's persistent memory. The newer OpenHands SDK has an opt-in persistent memory system built around two MEMORY.md files. Pass AgentContext(load_memory=True) and the conversation loads memory indexes from two tiers: a user tier at ~/.openhands/memory/ and a project tier at <workspace>/.openhands/memory/. At session start, the contents are injected into the system prompt as a <MEMORY_CONTEXT> block, and the system prompt instructs the agent to maintain those files as it works: record durable, broadly useful facts in MEMORY.md near the end of a task, merge duplicates, prune stale entries, keep the indexes concise, never record secrets.
That is genuinely useful for a developer who opens OpenHands on the same machine every day and wants the agent to pick up where it left off. But notice what it is not. It is not shared across machines. It is not visible to any other tool. And it only contains what the agent itself chose to write down.
The scheduled-run problem
Now picture the automation operator's setup: an OpenHands agent on a cron schedule, running repo maintenance every night, maybe on a fresh container each time. Each scheduled run is a brand-new session. The file_store trick helps the UI keep sessions across a restart, but it does not hand the new night's agent the decisions the last night's agent made. The SDK memory loads MEMORY.md from local disk, which works if the container persists and the paths are mounted, and fails silently if the scheduled job spins up a clean environment.
Even when everything is wired correctly, there is a deeper issue: the memory is whatever the agent happened to record. An agent under time pressure records less. An agent that misjudged what mattered records the wrong things. There is no durable record of the full conversation, only the summary the agent wrote of itself. And stale entries linger until the agent bothers to prune them, because nothing external is curating the memory.
This is the same pattern across almost every agent framework. The memory is an accessory of the tool, not a layer underneath the operation. It remembers sessions on one machine for one tool, in one format, until the container, the config, or the schedule changes.
What scheduled OpenHands runs actually need
A nightly repo agent needs three things that neither file_store sessions nor MEMORY.md provide on their own:
- Continuity across fresh environments. Scheduled jobs often run in clean containers. Memory that lives in
~/.openhands/memory/on a specific box is not continuity, it is a file on a box. The memory has to live where the schedule can reach it, every run, without mount tricks. - Full history, not just the agent's notes. When the morning summary says "flagged PR #412 again," you want to see the actual conversation where the agent decided it was fine last Tuesday, not the one-line entry the agent wrote about it. Summaries compress away the reasoning you need when you disagree with the decision.
- Memory that follows the operator, not the tool. The nightly OpenHands agent is one part of your stack. The same repo decisions matter to the Claude Code session where you actually write code, the n8n workflow that files the weekly report, and the ChatGPT thread where you plan the sprint. A memory file on the OpenHands box is invisible to all of them.
This is where a hosted memory layer changes the picture. OpenHands speaks MCP natively, including Streamable HTTP, so a memory service exposed over MCP connects directly: the agent gets recall and retain tools, and a small rule in its instructions makes memory a habit, recalling relevant decisions at the start of each run and retaining durable facts at the end. The memory lives in the cloud, not on the container, so a fresh 2 AM run on a fresh machine starts with everything the last run knew. Because the same account serves every connected tool, the repo context the nightly agent saved is right there when you open Claude Code in the morning or ask ChatGPT about the sprint.
The setup that stops the amnesia
If you run OpenHands on a schedule, the practical stack looks like this:
- Pin
file_store="local"with an absolutefile_store_pathand a fixedjwt_secretso the app keeps sessions across restarts. This is table stakes, not the solution. - Use the SDK persistent memory for the local development loop, where one developer and one machine make the two-tier
MEMORY.mddesign shine. - Put a hosted memory layer underneath the scheduled runs, connected over MCP, so every run recalls and retains against the same store, from any machine, in any tool.
The last piece is the one that turns a nightly agent from a forgetful contractor into institutional memory. Vilix AI is built for exactly this: cloud-hosted with zero infrastructure to manage, the same memory served to every connected tool over MCP, full conversation history stored instead of just distilled facts, a free plan that stays free, a 7-day Pro trial with no credit card, and your data exportable or deletable anytime.
OpenHands remembers its sessions when you wire it carefully. Your operations should remember everything, everywhere, without the wiring. Give your nightly runs one memory, and they stop waking up blank.