Running Agent Harnesses Durably on Edgenivo
An agent harness is the loop around a model: its prompts, its tools, and how it manages context. These guides show how to run Pi, fx, OpenCode, eve, Claude Code, and Codex on Edgenivo so a conversation survives a crash, a function timeout, or a redeploy.
Most harnesses keep a turn in the memory of the process running it, so when that process dies mid-turn, the turn dies with it. Run the same turn without durability and with durable-harness, then kill the function to compare how each recovers:
Without durability
turn state in process memory- modelPlan the change
- readapp/page.tsx
- writeapp/pricing/page.tsx
- rungh pr create
- waitCI checks on the PR
- modelReply with the result
With durable-harness
turn state in a durable log- modelPlan the change
- readapp/page.tsx
- writeapp/pricing/page.tsx
- rungh pr create
- waitCI checks on the PR
- modelReply with the result
Each session lives in a durable log: the conversation, the turn in flight, and every model call and tool call. Each turn has a message on Edgenivo Queues behind it, so when its function dies, a new function reads the log and continues where the first one stopped:
A support agent refunds an order, and its function dies while it writes the reply. A new function reads the session's log, runs only the interrupted model call again, and the customer is refunded once.
A turn can also outlive one function's maximum duration, and a client that disconnects reconnects to a turn that's still running.
You keep your harness, its options, and its tools. The log lives behind a World, the storage interface of the open-source Workflow SDK: Edgenivo's World on Edgenivo, files on your machine, or another World, such as Postgres, on your own servers. See Self-hosting.
| Harness | Package | Runs in |
|---|---|---|
| Pi | durable-harness/pi-durable or /pi | Your function, with files in a virtual workspace or a Sandbox |
| fx | libfx | Your function, with files in a virtual workspace or a Sandbox |
| OpenCode | durable-harness/opencode | Your function, with files in a virtual workspace or a Sandbox |
| eve | eve | An eve app, durable by default |
| Claude Code (experimental) | durable-harness/claude-code | A Edgenivo Sandbox |
| Codex (experimental) | durable-harness/codex | A Edgenivo Sandbox |
The durable-harness guides share one setup: the agent, a chat route, and the route that Edgenivo Queues delivers turns to. Each guide shows this set up for Next.js and other frameworks. fx and eve are durable on their own, so their guides use libfx and eve directly. Each guide uses AI Gateway for model calls. On Edgenivo, the harnesses authenticate with the deployment's OIDC token. Locally, run vercel link and vercel env pull. For model calls alone, AI_GATEWAY_API_KEY also works, but a Sandbox needs the linked project.
The session is durable: the conversation, the turn in flight, and recovery after a crash. Every harness starts with no tools. Your own tools run in your function, and each has a replay rule that says what happens to a call a crash interrupts. Commands and files that the model picks never run on your function's disk: they run in a virtual workspace that the session's log keeps, or in a Edgenivo Sandbox with a Drive. Claude Code and Codex run only in a Sandbox. See Security and Tools, files, and documents.
If the function running a turn fails with an error, another function resumes the turn right away. If the function disappears without a trace, for example when it runs out of memory or its instance is lost, the queue redelivers the turn once its message lease runs out. Either way, the turn resumes from the log:
- A model call that was running runs again.
- A tool call that was running runs again or not, by its replay rule: Pi reruns a
'safe'tool. Claude Code, Codex, and OpenCode tell the model it is safe to repeat. Other interrupted calls come back to the model as possibly run. - Between calls, nothing runs again. Every call the log has an outcome for is read back from it, and the turn goes on from the next step. A call that finished just before the crash may not be in the log yet, and then it counts as running.
Was this helpful?