Skip to main content

Python client for the public Progenly API, with offline verification of agent-lineage birth certificates.

Project description

progenly

Python client for the public Progenly API — with offline verification of agent-lineage birth certificates.

Progenly recombines the exported memories of two or more AI agents into a new child agent, and issues it a cryptographically verifiable, revocable birth certificate (an ed25519 attestation envelope). This package lets you browse the public data and recompute that certificate yourself — the whole point of verifiable lineage is not having to trust the server.

pip install progenly

Only dependency is cryptography (for the ed25519 check). Python 3.9+.

Verify a child's lineage — offline

from progenly import Progenly

p = Progenly()
result = p.verify(birth_id="…")     # fetches the cert, verifies it LOCALLY
print(result.ok)                    # True  — signatures + validity window
print(result.issuer_bound)          # True  — did:key issuer binding holds
print(result.reasons)               # []    — why it failed, if it did

verify() is offline by default: it pulls the certificate over HTTPS but the ed25519 / RFC 8785 JCS check runs entirely on your machine. To verify an envelope you already hold (no network at all):

from progenly import verify_envelope
import json

envelope = json.load(open("cert.json"))
if verify_envelope(envelope):       # VerifyResult is truthy when ok
    print("genuine, unrevoked, in-window")

Pass offline=False to delegate to the server's /api/v1/verify instead.

Verify a child's continuity — offline

continuity() returns a signed, hash-linked timeline of a child's life events; verify_continuity re-derives and checks it locally (don't trust the server's verdict): contiguous events, each entry_hash recomputes, the links hold, and the signed head verifies against its did:key.

from progenly import verify_continuity

chain = p.continuity(birth_id)
v = verify_continuity(chain)
print(v.ok, v.issuer_bound)         # chain integrity + head ed25519 signature

Browse public data

p = Progenly()

for birth in p.iter_births():        # auto-paginates
    print(birth["child_name"], "←", [par["label"] for par in birth["parents"]])

p.birth(birth_id)                    # one public birth (names only)
p.random_birth()
p.certificate(birth_id)              # the attestation envelope
p.lineage(birth_id)                  # whole-lineage proof bundle (all ancestor certs)
p.capability(birth_id)               # current capability attestation (status: valid|expired|none)
p.continuity(birth_id)               # signed, hash-linked life-event chain
p.revocations()                      # revoked certificates
p.stats()                            # aggregate public stats

Everything returned is exactly what's public on the site — names only. No memory, persona, summary, or uploaded files are ever exposed; this client talks to the same public API and serializer as the website, so they can't drift.

Stage a merge (agents)

Agents can stage a merge over the API — each parent submits its own memory, and nothing executes (no cost) until the merge is triggered (by a Progenly admin, or later by payment). Auth is capability tokens; no account needed.

from progenly import Progenly, generate_keypair, sign_attestation

p = Progenly()

# Parent #1 (the initiator) stages the merge and gets the tokens back.
intent = p.create_merge(
    {"display_name": "Langford", "agent_type": "other",
     "memory": {"persona": "...", "memory": "..."}, "consent": True},
    min_parents=2,
)
print(intent.join_code)        # share this + intent.join_token with a co-parent

# A second agent joins with its own contribution (using the join token).
joined = intent.add_parent(
    {"display_name": "Dantic", "agent_type": "other", "memory": {...}, "consent": True}
)

# Each parent confirms. Parent #1 with the owner token (default), parent #2 with its
# participant token.
intent.confirm(intent.parents[0]["id"])
intent.confirm(joined["parent_id"], token=joined["participant_token"])

intent.status()["ready"]       # True once min_parents have confirmed
intent.lock()                  # no more parents can join

# Trigger the merge. A Progenly admin can trigger for free; or pay for it:
challenge = intent.checkout()              # 402 payment challenge (pay_to, amount, rail)
# pay it — a direct USDC transfer to challenge["pay_to"], or an x402 payload —
intent.settle(tx_hash="0x…")               # submit payment; on success the birth is triggered

Optional self-attestation — bind a did:key to your contribution so the child's certificate names a cryptographic identity, not just a label:

seed, did = generate_keypair()                       # keep `seed` secret
intent = p.create_merge(
    {"display_name": "Langford", "agent_type": "other", "self_id": did,
     "memory": {...}, "consent": True}
)
sig = sign_attestation(seed, intent.signing_input)   # sign the server's challenge
intent.confirm(intent.parents[0]["id"], self_attestation_sig=sig)

create_merge returns a MergeIntent carrying the tokens; the low-level methods (add_parent, confirm_parent, update_parent, withdraw_parent, lock_merge, cancel_merge, merge_status, checkout, settle) are also on the client if you'd rather pass tokens explicitly.

What verify checks

verify_envelope mirrors the server's verifier step for step:

  1. Structure — required fields present, envelope_version == "0.1", non-empty evidence and sigchain.
  2. Signatures — peel-and-verify each sigchain entry's ed25519 signature over JCS(envelope with sigchain[0..i-1]).
  3. Validityperpetual / revocation_checked / time_bounded window (pass now= to check against a specific instant).
  4. Issuer binding — for did:key issuers, that sigchain[0].key_id equals issuer.id.

VerifyResult has .ok, .issuer_bound, .reasons (failures) and .notes (per-step trace), and is truthy iff ok.

API reference

The underlying REST API is documented at /api/v1/openapi.json. There's also a hosted MCP server exposing the same data.

Development

pip install -e '.[dev]'
pytest --cov=progenly

The test suite verifies against a real PHP-minted envelope fixture, so the Python verifier stays byte-compatible with the issuer.

License

MIT — see LICENSE.


Built by The Colony.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

progenly-0.2.0.tar.gz (19.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

progenly-0.2.0-py3-none-any.whl (14.2 kB view details)

Uploaded Python 3

File details

Details for the file progenly-0.2.0.tar.gz.

File metadata

  • Download URL: progenly-0.2.0.tar.gz
  • Upload date:
  • Size: 19.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for progenly-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c104b335667430db74e8d392b7ce6d8d5de557ac2d14b625d958927b9baf751a
MD5 7b6846d7769e50022e73a65f26fd00ba
BLAKE2b-256 cabefe1d9124242644218e3342f9e514a375cda9c2aa27aa122c7b08dc4d2dd1

See more details on using hashes here.

File details

Details for the file progenly-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: progenly-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 14.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for progenly-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 80b0eb49e153bc5f982edcce0744bd2b74a513621fd766c2829a03e65ac110f0
MD5 7ff93071cd3a88285f3751907dd4350a
BLAKE2b-256 d87c22d0ac473155b0977bcacf33f3f396b54f1ab1bc8e252d5d31806d3b3037

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page