Durable execution on PostgreSQL

The runtime core is zero-dependency, so it ships SQLite reference savers only. For fleet-wide retention, implement the CheckpointSaver (and, for the EU AI Act audit log, AuditBackend) protocols against your own database. Install the deps:

pip install 'techrevati-runtime[postgres]'      # psycopg 3

This is a recipe, not a shipped module — you own the connection pool, schema migrations, and retention. The protocols are intentionally small so an adapter is a single file.

CheckpointSaver over psycopg

import json
from datetime import UTC, datetime
from uuid import uuid4

import psycopg
from techrevati.runtime import Checkpoint, CheckpointSaver  # Protocol


class PostgresSaver:  # satisfies CheckpointSaver structurally
    def __init__(self, conninfo: str) -> None:
        self._conn = psycopg.connect(conninfo, autocommit=True)
        self._conn.execute(
            "CREATE TABLE IF NOT EXISTS checkpoints ("
            " id TEXT PRIMARY KEY, thread_id TEXT NOT NULL, created_at TEXT NOT NULL,"
            " state_json JSONB NOT NULL, parent_id TEXT, metadata_json JSONB NOT NULL)"
        )
        self._conn.execute(
            "CREATE INDEX IF NOT EXISTS idx_ckpt_thread_created"
            " ON checkpoints (thread_id, created_at DESC)"
        )

    def put(self, thread_id, state, *, parent_id=None, metadata=None):
        cp = Checkpoint(
            id=uuid4().hex, thread_id=thread_id,
            created_at=datetime.now(UTC).isoformat(),
            state=dict(state), parent_id=parent_id, metadata=dict(metadata or {}),
        )
        self._conn.execute(
            "INSERT INTO checkpoints VALUES (%s,%s,%s,%s,%s,%s)",
            (cp.id, cp.thread_id, cp.created_at, json.dumps(cp.state),
             cp.parent_id, json.dumps(cp.metadata)),
        )
        return cp

    def get(self, thread_id, checkpoint_id=None):
        if checkpoint_id is None:
            row = self._conn.execute(
                "SELECT id,thread_id,created_at,state_json,parent_id,metadata_json"
                " FROM checkpoints WHERE thread_id=%s ORDER BY created_at DESC LIMIT 1",
                (thread_id,),
            ).fetchone()
        else:
            row = self._conn.execute(
                "SELECT id,thread_id,created_at,state_json,parent_id,metadata_json"
                " FROM checkpoints WHERE thread_id=%s AND id=%s",
                (thread_id, checkpoint_id),
            ).fetchone()
        return None if row is None else Checkpoint(
            id=row[0], thread_id=row[1], created_at=row[2],
            state=row[3], parent_id=row[4], metadata=row[5],
        )

    def list(self, thread_id, *, before=None, limit=10): ...   # keyset by (created_at, id)
    def delete(self, thread_id): ...

Wire it exactly like the SQLite saver: AgentSession(saver=PostgresSaver(...)) with a thread_id at session() time.

AuditBackend over psycopg (Article 12)

The EU AI Act AuditLogSink accepts any AuditBackend. A Postgres backend that gives the audit user append-only privileges (no UPDATE/DELETE grant) turns the hash chain's tamper-evidence into stronger tamper-resistance:

from techrevati.runtime.compliance import AuditLogSink, AuditRecord

class PostgresAuditBackend:  # satisfies AuditBackend structurally
    def append(self, record: AuditRecord) -> None: ...   # INSERT only
    def last(self): ...
    def records(self): ...
    def count(self): ...
    def purge_before(self, cutoff: str) -> int: ...

sink = AuditLogSink(PostgresAuditBackend(...), signing_key=hsm_key)

See Audit Log for the chain semantics and threat model.