DEV Community

Harper Zhu
Harper Zhu

Posted on

Persist AI Agent State on Free Servers with JSON Checkpoints

I stop losing AI agent insights on free ephemeral servers by writing a JSON checkpoint after every meaningful step and loading that file before the next session does any real work. Token grants fund compute, but only an external persistence layer preserves the context the agent already paid to earn.

Disclosure: This article was prepared as part of MonkeyCode's product outreach.

Why Free Ephemeral Servers Wipe Agent Context

I watched an AI coding agent spend an hour diagnosing a failing test, then lose every insight when the sandbox expired. The agent started the next session by re-running the same commands and re-reading the same logs, so the second hour was a replay of the first. That pattern repeated every time the environment reset, and the wasted effort became a predictable tax on my productivity.

The free server option in MonkeyCode is a powerful way to experiment, but its ephemeral nature creates a hidden cost. Every new sandbox is a blank slate for the agent. Token grants solve the compute budget, not the context budget. A 10-million-token grant loses value when the agent must re-learn the same codebase on every restart.

I treat that mismatch as a design constraint, not something to fight:

  • The sandbox gives me a filesystem, a shell, and a token grant for one session
  • The grant is consumed by exploration: reading logs, forming hypotheses, ruling out dead ends
  • When the sandbox dies, those conclusions die with it unless I copy them out
  • The next grant then pays again for the same exploration

Compute and context are different budgets. I keep them on different layers so a reset only kills the machine, not the work.

Record Decisions in a JSON Checkpoint

A simple JSON file can turn a disposable server into a continuous work session, because the agent writes a checkpoint after each meaningful step. The next session loads that checkpoint before doing any real work, which preserves the hard-won context from previous attempts.

I keep the schema intentionally small so the agent stays selective:

  • steps: the actions or observations that actually changed my understanding
  • hypotheses: the current best explanation, not every discarded idea

Minimal Python checkpoint

The script below reads a memory file if one exists, simulates a short agent session, and saves the updated state. It is intentionally small so the mechanics are obvious. For the file format I follow the Python json module.

#!/usr/bin/env python3
"""demo_memory.py - simulate an AI agent that persists its memory across sessions."""
import json
import os

MEMORY_FILE = "demo_memory.json"

def load_memory():
    if os.path.exists(MEMORY_FILE):
        with open(MEMORY_FILE) as f:
            return json.load(f)
    return {"steps": [], "hypotheses": []}

def save_memory(memory):
    with open(MEMORY_FILE, "w") as f:
        json.dump(memory, f, indent=2)

def main():
    memory = load_memory()
    if memory["steps"]:
        print("Resuming from previous session:")
        for i, (step, hypothesis) in enumerate(zip(memory["steps"], memory["hypotheses"]), 1):
            print(f"  {i}. {step} -> {hypothesis}")
    else:
        print("No memory found. Starting fresh.")

    step = input("What did you just learn? ")
    if step.strip().lower() == "exit":
        return
    hypothesis = input("What is your current hypothesis? ")
    memory["steps"].append(step)
    memory["hypotheses"].append(hypothesis)
    save_memory(memory)
    print("Memory saved. Next session will resume here.")

if __name__ == "__main__":
    main()
Enter fullscreen mode Exit fullscreen mode

I verify the loop with two runs:

  1. The first run starts with empty memory, records a step and a hypothesis, and writes demo_memory.json.
  2. The second run loads that file, prints the previous context, then appends a new step.
  3. Killing the process—or the sandbox—does not erase the file if I have already copied it out.

That is the core of a persistence layer: the agent's working state survives the death of the sandbox. I refuse to persist raw command output or entire log files. Those bloat the JSON and recreate the original context-tax problem inside the memory file itself.

Store Memory Outside the Ephemeral Server

In a real deployment, the memory file must live outside the ephemeral server. I copy the file to a persistent location after each session and fetch it before the next one. A Git repository works well as a memory store. The agent can commit the memory file at the end of a session, and the next session can pull the latest version before starting. This adds a few seconds of overhead but saves many minutes of redundant exploration.

Git pull and push helpers

# save_memory.sh - push memory to a remote Git repo
#!/usr/bin/env bash
set -euo pipefail
git add memory.json
git commit -m "Update agent memory"
git push origin main
Enter fullscreen mode Exit fullscreen mode
# load_memory.sh - pull the latest memory before starting
#!/usr/bin/env bash
set -euo pipefail
git pull origin main
Enter fullscreen mode Exit fullscreen mode

The session wrapper I actually run looks like this:

  1. Run load_memory.sh so memory.json matches the remote tip
  2. Start the agent with load_memory() as its first call
  3. After each high-signal finding, append to steps and hypotheses, then call save_memory()
  4. On exit, run save_memory.sh so the next sandbox inherits the work

The same pattern works with object storage or a simple HTTP endpoint. The key insight is that the persistence layer is separate from the compute layer. The free server provides the compute, while an external store provides the memory. This separation is what makes ephemeral environments practical for long-running agent tasks. For the save path I follow the official git commit reference.

A quick comparison of stores that fit this pattern:

  • Git: conflicts are visible, history is cheap, and the setup is already familiar
  • Object storage: no merge step, which is better when only one session writes
  • HTTP endpoint: useful when I already have a small internal API, at the cost of extra moving parts

I pick Git when I want reviewable checkpoints and object storage when I want a single blob with no branch noise.

Know When This Pattern Helps—and When It Does Not

The limitations of this approach are worth naming. A JSON file grows quickly if the agent records too much, so the agent must be selective about what it persists. Conflicts can arise when two sessions write to the same file, though a Git-based store makes conflicts visible and resolvable. Some state, like loaded libraries or running processes, cannot be serialized into a file and must be rebuilt anyway. The persistence layer is a complement to, not a replacement for, a well-designed agent loop.

I skip the pattern in three cases:

  • Teams with strict data-residency requirements, because copying memory files to an external store may violate those rules
  • Teams that already run agents in a single long-lived environment, because the environment already provides continuity
  • Teams still evaluating different agents against a fixed benchmark, since a persistence layer adds complexity without improving the measurement

When I do use it, I add two guardrails: a maximum list length so old steps roll off, and a rule that the latest hypothesis overwrites the previous one instead of growing forever. Those two choices keep the file small enough to read at the start of every session.

Make the Next Free Session Continue the Last One

The ephemeral memory problem is real, and it is solvable with a few lines of code. A free server with a token grant is only useful if the agent can carry its work forward. By adding a small persistence layer, I turn a disposable sandbox into a productive workspace that learns across sessions.

If you are experimenting with MonkeyCode's free server, add a memory file to your next agent session and measure how much faster the second session completes. Do this in order:

  1. Copy the Python script into your repo and treat memory.json as part of the project, not as sandbox leftover.
  2. Wrap each session with the two Git helpers so you pull before work and push on exit.
  3. Run two sessions on the same failing test and compare how much of the first hour you do not have to repeat.
  4. Comment with your before-and-after times, or with the one field you wish the schema had, so the next write-up can tighten the pattern.

Start this week with one failing test. Ship the checkpoint. Then tell me whether the second session actually skipped the replay.

MonkeyCode provides free models that can run this workflow.

Disclosure: This article was prepared as part of MonkeyCode's product outreach.

Top comments (0)