Article

A PostgreSQL Work Ledger for Replaceable AI Agents

Long-running agents need durable work, leases, explicit state transitions, and independent verification. This article examines a PostgreSQL-centered Looper redesign, separates measured audit findings from work that remained unproven on August 15, 2026, and explains its adoption boundaries.

Share

Koharu's reading tip

Look past agent names and hierarchies and ask where unfinished work lives and who can resume it after failure. The key is whether PostgreSQL becomes the mandatory path for state transitions rather than merely a place to store records.

Koharu's reading tip

The hardest failure in a long-running AI-agent system is not necessarily a model making one bad attempt. It is an unfinished objective disappearing together with a session or process.

A Looper design record published on August 15, 2026 describes a shift away from organizing more named agents and toward keeping work in PostgreSQL for replaceable workers to claim. The audit findings are measured records, but the new design was still being built and had not yet been proven.

What changes when PostgreSQL moves to the center, and where does the database stop protecting the system? Following the path from durable work through concurrency, verification, and external side effects makes the adoption boundary much clearer.

Persist unfinished work instead of preserving an agent

In the Looper audit, at least eight of the sixteen loops that ran were observe-only, and only three changed anything outside the orchestrator. Sensors reported red on 43 of 45 nights, while the fleet produced zero verified autonomous red-to-green fixes. Detection existed, but it was not wired to a mechanism that carried work into the next action.

Thousands of run records are not enough if no durable record says that an objective remains open. A new worker otherwise has to rediscover the previous context before it can continue. The redesign therefore makes a campaign row, not a conversation or resident agent, the durable object at the center.

Data kept on a campaign row Why the next step needs it
Desired state and observation Reconstruct why the work was opened
Current state Separate execution, verification, and confirmation
Lease owner, expiry, and generation Recover work from a dead worker and reject stale results
Attempt count, next time, and failure reason Avoid repeating the same failed attempt forever
Acceptance criteria and evidence location Judge completion from results rather than self-report

A worker claims this row, makes one attempt in an isolated work environment, records the result, and exits. If the process dies, the system loses an attempt rather than the objective. That is the practical difference between restarting an agent and resuming work.

PostgreSQL row locks and leases protect different time spans

SELECT ... FOR UPDATE SKIP LOCKED can prevent multiple workers from claiming the same row at the same time. The PostgreSQL 18 SELECT documentation says that SKIP LOCKED gives an inconsistent view unsuitable for general-purpose queries, but it can avoid lock contention among multiple consumers of a queue-like table.

This is not a feature invented for AI agents. According to the PostgreSQL 9.5 release notes, version 9.5 was released on January 7, 2016 and introduced SKIP LOCKED. A modern agent architecture is using a mature job-queue primitive.

The row lock lasts only for the transaction, however. A worker should not hold that transaction open while an external task runs for minutes or hours. A short claim transaction instead records an owner, an expiry, and a monotonically increasing generation on the campaign row. The result handler accepts a completion only when its generation still matches the current row.

That lease and generation protocol is an application convention, not a complete PostgreSQL feature. A separate reaper must also reclaim expired work. If the reaper depends on the same dispatcher that can fail, the recovery path disappears with the component it is meant to recover from.

Bind state transitions and evidence in one transaction

A ledger still stores only self-report if a worker can jump directly from attempted to confirmed. States such as ready, leased, attempted, verified, and confirmed need distinct owners and explicit legal transitions.

PostgreSQL triggers execute in the same transaction as the statement that fired them, and both effects roll back when either one fails. Requiring every legal state change to insert an event in that transaction prevents a database state change from silently losing its audit record.

An external operation is different. Updating a Git reference, calling an API, or sending a message cannot join a PostgreSQL transaction. As the AWS guidance on the transactional outbox pattern explains, storing a state change and its pending event in one transaction reduces dual-write inconsistency, but consumers must still tolerate duplicate delivery through idempotency.

The practical sequence is to record intent before the external action, include an expected Git SHA or idempotency key, and read the target back before recording success. A database generation can reject a stale worker writing to the ledger; it cannot fence an external process that has already started.

Narrow the write API and separate verification from the worker

The redesign aims to keep general database credentials away from workers. A kernel would expose narrow stored functions instead, separating what a worker can technically do from what this particular work item authorizes now.

Adding SECURITY DEFINER is not enough. The PostgreSQL 18 CREATE FUNCTION documentation advises excluding untrusted schemas from search_path and revoking the default PUBLIC execute privilege before granting access only to selected roles. If stored functions are the only write path, their own privilege boundary must be tested first.

Completion also has to be separated from the worker. A verifier under a different role, and preferably a different model family, would inspect a clean checkout using a verification bundle created after the worker committed. The campaign would not become confirmed until the next independently scheduled observation was green, keeping a one-time test pass distinct from the environment actually returning to its desired state.

This verification path was also still a plan as of August 15, 2026. The historical evidence that an independent sensor ran for 45 consecutive nights and found real defects does not prove that the new campaign workflow can close the full repair-and-confirmation loop.

Treat LISTEN/NOTIFY as a doorbell, not the ledger

LISTEN/NOTIFY is an obvious candidate when workers should wake promptly after a state change. The official LISTEN specification says that registrations are cleared when a session ends and describes an initial setup race, recommending that an application commit LISTEN, inspect database state in a new transaction, and then depend on later notifications.

Notifications therefore cannot be the memory of the system. Tables remain the source of truth, a periodic reconciler recovers anything missed, and NOTIFY can reduce wake-up latency. The NOTIFY documentation similarly recommends placing larger information in a table and sending only the record key in the notification.

Dedicated durable-execution systems are another option. The Temporal documentation presents recovery after crashes, network failures, or infrastructure outages as a core feature, resuming workflows from their prior point. A system that already needs complex workflows, durable timers, and recovery across several services should compare that capability before rebuilding it on PostgreSQL.

Looper chose not to add another stateful system for nightly-scale external CLI work on one machine. That is a decision tied to its current failure model and operating scope, not a claim that PostgreSQL is always better than a workflow engine.

Prove stopping, rejection, and recovery with one campaign class

The redesign should be judged by failure paths that close work, not by component count or document volume. The Phase 1A plan in the source deliberately narrows the first cell to one campaign class, one execution seat, one watched target, one verification bundle, and one authority profile.

Its proposed drills are concrete: inject a fault and require intake to open a campaign without help; force the first attempt to fail and require the second to differ; kill a worker and watch the lease be reclaimed; reject a bad patch and accept a good one; and prevent and record a forbidden write. Only the next scheduled green observation confirms completion.

A further test proposes seven consecutive days with verified closures and no human action inside the perimeter. Zero interventions across zero eligible campaigns would be marked under-exercised rather than perfect, so the metric reflects completed work instead of mere inactivity.

None of these tests had run when the source was published. What is available for adoption today is not a proven finished architecture, but a precise experiment defining what evidence would justify the next step.

PostgreSQL becomes the system only when every path uses the ledger

The answer to the opening problem is not a longer conversation history. The unfinished objective, ownership, attempts, evidence, and next wake condition must be durable so another worker can continue after any one worker disappears.

PostgreSQL can sit at that center because row locks, transactions, roles, functions, and triggers can work in one place. It earns that role only when workers cannot bypass the ledger, verification outcomes drive state transitions, and external side effects have their own idempotency and fencing.

Making agents replaceable does not by itself create an autonomous system. The PostgreSQL-centered design becomes operationally meaningful only when work persists, failures trigger a different next attempt, and independent evidence closes the loop.

Source

Share

Related Articles

These articles share nearby categories or tags, so you can keep reading along the same thread.