Skip to main content

agentos-ledger-client

Canonical AgentOS State Ledger client, hash-chain verification, and content-addressed blob storage.

Features

  • Advisory-Locked Journal Appends: Uses canonical GLOBAL_CHAIN_LOCK_ID = 0x4C454447 to serialize concurrent writers and eliminate silent chain forks.
  • SHA-256 Hash Chaining: Verifiable hash chain where integrity_hash = sha256(previous_hash + payload_json).
  • Envelope Digest: Secondary actor-bound digest sha256(event_type + actor_id + actor_type + on_behalf_of + payload_json) ensuring tamper-evident provenance.
  • Content-Addressed Blob Storage: Tiered binary blob storage with deduplication:
    • Payloads $\le$ 1MB stored inline (BYTEA).
    • Payloads $>$ 1MB stored in Google Cloud Storage (gs://...).
  • Complete Schema Definitions: Canonical event namespace constants for tasks, goals, iam, approval, and rlagt events.
  • Lightweight Dependencies: Standard library + asyncpg. Optional GCS client support.

Installation

pip install agentos-ledger-client

That is the whole thing. It is on PyPI, so there is no index to configure, no credential to obtain, and nothing to do differently on a laptop, in CI, or inside an AgentOS execution sandbox — PyPI is already reachable from all three.

Blobs over 1MB need Google Cloud Storage; at or under 1MB they are stored inline as BYTEA and nothing external is required:

pip install "agentos-ledger-client[gcs]"

As a dependency, declare it the ordinary way and pin the series:

dependencies = [ "agentos-ledger-client>=0.1,<0.2" ]

Versions

Releases are cut automatically and only when the code changes. The build asks PyPI for the highest 0.1.x, compares that release's contents with the tree, and publishes 0.1.<n+1> only if they differ — so a version number always means the same bytes, and a run of builds that did not touch this package produces no releases at all.

>=0.1,<0.2 therefore resolves to the newest build of the current series. The series moves to 0.2 only for a breaking change, which is the one judgement nobody automates.

Published from agent_os_refactor_dev alone. Other branches never publish, so a version cannot mean two different things depending on where it was built.

If you are changing this package — person or agent — change the code and stop there. Do not set __version__: scripts/ci/publish_ledger_client.py writes it, after reading what PyPI already has, and a hand-set number either collides with one that is taken or is overwritten. A PyPI version is burned forever, so a collision is not recoverable.

Raise it explicitly if you break the public API, since moving the series is the one decision here that is not automatic. The full rules are in CONTRIBUTING.md under Releasing agentos-ledger-client.

Quick Start

import asyncpg
from agentos_ledger_client import (
    chain_hash,
    GLOBAL_CHAIN_LOCK_ID,
    append_event,
    store_blob,
    read_blob,
)


async def example(conn: asyncpg.Connection):
    # Store blob
    ref = await store_blob(conn, b"example payload", content_type="text/plain")
    print(ref.sha256, ref.storage_backend)

    # Append ledger event
    res = await append_event(
        conn,
        event_type="task.created",
        payload={"title": "Test task", "blob_sha256": ref.sha256},
        actor_id=my_actor_id,
        actor_type="independent_agent",   # see the table below
    )
    print(res["event_id"], res["integrity_hash"])

actor_type

The CHECK constraint admits seven values. Every event says who caused it, and "who" is the question the chain exists to answer — an event attributed to the wrong kind of actor is not a cosmetic error.

value the actor
human a person, acting directly
shca a person's assistant, acting for them
goal_orchestrator the orchestrator that plans and drives a goal
executor a sandboxed run doing the work
verifier the checker that judges a run's criteria
independent_agent an agent acting on its own account
system no actor — scheduled work, reapers, migrations

Reach for system last. It is the value that means nobody is accountable for this, and it is easy to default to when the real actor is simply inconvenient to thread through. On a live deployment the distribution is roughly goal_orchestrator 28%, system 28%, human 23%, shca 16%, the rest a long tail — and some of that system share is events whose real actor was known and dropped.

This README previously listed only the first two and the last two, which was the state of the constraint when the package was extracted and has been wrong since. goal_orchestrator, the most common value of all, was missing from the documentation while being the most written to the table.

actor_id is UUID NOT NULL and actor_type is constrained to the four values above — a consumer whose actors are strings ("ecommerce-sim") needs a stable UUID per actor and must pick one of the four types.

Creating the tables

from agentos_ledger_client import init_schema

await init_schema(conn)   # idempotent; safe in a test fixture

Checking it against your own database

The suite that verifies this client ships inside it, so you can run it where it matters — against the Postgres you intend to use, on your Python, without cloning pwt_agent_os.

pip install "agentos-ledger-client[test]"
pytest --pyargs agentos_ledger_client

No database setup is required. The [test] extra brings pgserver, a real PostgreSQL shipped as a wheel, and the fixtures start one and tear it down. To point the suite at a server you already have, set DATABASE_URL instead — it is used when reachable and ignored when not, so a stale value degrades to a skip rather than a confusing error.

Why bother. What you share with AgentOS is a hash-chained table. A schema disagreement does not announce itself as "the schema differs" — it surfaces later as a chain that will not verify, by which point the rows exist. This suite builds the schema from the shipped schema.sql on an empty database, appends a chained event, and verifies it.

It is not a hypothetical check. schema.sql shipped a CHECK on actor_type that refused goal_orchestrator, executor and verifier — 29% of the events on a live deployment — because it was copied from the first migration and two later ones widened it. AgentOS never noticed: its own tables come from migrations/, not from this file. The first person to execute it would have been a consumer.

Requires Python 3.12: pgserver publishes cp312 wheels and no sdist. The library itself has no such constraint at runtime, but the project declares 3.12 because that is the only version it is tested on.

Metadata

Release files for agentos-ledger-client 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agentos-ledger-client 0.1.2
File Size Uploaded Provenance
agentos_ledger_client-0.1.2.tar.gz 50.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for agentos-ledger-client 0.1.2
File Interpreter ABI Platform
agentos_ledger_client-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 100.7 kB

Release files / agentos_ledger_client-0.1.2.tar.gz

Download URL agentos_ledger_client-0.1.2.tar.gz
Size 50.1 kB
Tags Source
SHA-256 checksum
How to use checksums
e8af3085b38919b3b05146fdab78ce5a32d87b4e8c37dc199f06153d3b297034
BLAKE2b-256 checksum
How to use checksums
a7ca6e3ce53133466d0d58c66c0fa105ec79bbb0495e1c659f0f3541f84b3b15
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.15

Release files / agentos_ledger_client-0.1.2-py3-none-any.whl

Download URL agentos_ledger_client-0.1.2-py3-none-any.whl
Size 50.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5f49e932f2fba429b8a02160c2b179993c3dc185a9d1cf709505b42071f26896
BLAKE2b-256 checksum
How to use checksums
43b14d630c6bcefda2cfb9d7c6d20ab52153d4d66c598f0b84689ec0ffa2e55b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.15

Security for agentos-ledger-client 0.1.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page