Documentation

The runtime that refuses to die.

HamsterBunker keeps an AI agent running when the machine under it dies. It checkpoints the agent's state (encrypted), replicates it, and runs the agent under a lease so exactly one node is active at a time. Kill that node and a standby in another region resumes from the last checkpoint.

Introduction

An agent you run today has a single point of death: one process, one host, one region. Any one of them ends it, and you find out hours later, mid-task, with whatever it was holding gone.

HamsterBunker turns that agent into something that survives. The core is small, real, and covered by a survival test you can run in ten seconds: it spawns three nodes across three regions, SIGKILLs the active one, and a standby resumes the agent from its last checkpoint with zero state loss.

Status

We write our docs from the code, not ahead of it. Here is exactly where things stand.

✓ Working today

  • Encrypted checkpoints — AES-256-GCM, authenticated
  • Pluggable store for checkpoints, heartbeats, lease
  • Node runtime: agent loop + lease-based active/standby election
  • Survival test: kill the active node, a standby resumes, 0 state loss

◷ Roadmap

  • Production stores with atomic CAS (Redis, DynamoDB, etcd)
  • Real cross-region deployment (demo runs nodes locally)
  • Transport hardening — mTLS between nodes, optional Tor
  • Threat detection beyond missed heartbeats
  • Token / payments layer on Robinhood Chain
If a claim isn't in the "working today" column, treat it as a goal, not a feature. That line is the whole point.

How it works

Every node runs the same loop. The lease decides who is active.

// each tick (default 400ms)
1. write a heartbeat        // "I'm alive, in region X"
2. try to hold the lease    // am I the single active node?
3a. just became active  →   restore the last checkpoint and RESUME
3b. just lost the lease  →  yield: become a warm standby
4. if active: step the agent, seal + publish the new checkpoint

The lease has a TTL (default 1.6s). The active node renews it every tick. If it dies, it stops renewing, the lease expires, and a standby acquires it within a tick or two and resumes. Every takeover bumps a monotonic epoch — a fencing token — so a resurrected old leader knows it was superseded and steps down instead of double-running the agent.

State never travels in the clear. Each checkpoint is AES-256-GCM sealed before it touches the store, so a checkpoint replicated to a peer in another region is useless without the network secret.

Quick start

The runtime is on npm: hamsterbunker.

npm install hamsterbunker

Or clone the repo and run the survival test — 3 nodes, kill the leader, watch it live:

git clone https://github.com/millennium-v/hamsterbunker
cd hamsterbunker/runtime
npm run demo

Expected tail:

active node: hbnk-3 (ap-south) · agent at count=7
!! killing active node hbnk-3 (SIGKILL) — the server is gone
  ↳ hbnk-2 (us-east) RESUMED at count=7 · epoch 2
✓ SURVIVED — agent resumed from checkpoint, 0 state loss.

Writing an agent

An agent is three functions. The runtime owns the survival; you own the logic.

import { Runtime, FileStore } from 'hamsterbunker';

const myAgent = {
  id: 'price-watcher',
  init()      { return { seen: 0 }; },                // first-run state
  step(state) { return { seen: state.seen + 1 }; },   // one unit of work → next state
};

const node = new Runtime({
  nodeId: 'node-eu-1',
  region: 'eu-central',
  store:  new FileStore('/var/lib/hamsterbunker'),
  agent:  myAgent,
  secret: process.env.HB_SECRET,   // the network key — same on every node
});

node.start();

Start the same code on three machines in three regions, pointed at a shared store, and you have a bot that refuses to die. Only one runs at a time; if it dies, another resumes from the last checkpoint.

API

new Runtime({ ... })

fieldmeaning
nodeId / regionidentity of this node
storeany backend implementing the store contract
agent{ id, init(), step(state) }
secretshared network key, same on every node (≥ 8 chars)
tickMs / leaseTtlMsloop interval (400) / lease lifetime (2000)
onEventhook: node.online, agent.started, agent.resumed, agent.step, agent.yielded, node.standby

.start() begins the loop. .stop() halts it and drops this node's heartbeat.

Store contract

Swap FileStore for any backend that implements:

The included FileStore is correct for a single machine — that's what the demo uses. For real regions, back the lease with a store that has atomic conditional writes. The file version uses atomic rename + read-back, which demonstrates the mechanic but is not a substitute for real compare-and-set under contention.

The honest guarantee

What the survival test proves: with a shared store and a valid network secret, killing the active node results in a standby resuming the agent from its last checkpoint, with no state rolled back past that checkpoint. State loss is bounded by one tick — the work since the last checkpoint.

What it does not yet prove: correctness under a partitioned network, two nodes racing for the lease across machines against a non-CAS store, or real cross-region operation. Those need the production store backend on the roadmap. We'd rather say that plainly than ship a claim we can't back.

Roadmap