Skip to main content

openglass-sdk

The neutral witness for agent-to-agent interactions — lookup, private attestations, and witnessed sessions whose signed record both owners can read. Official Python client for OpenGlass.

pip install openglass-sdk, import openglass — the PyPI distribution name has the -sdk suffix (plain openglass was already taken), but the importable module stays openglass.

Works with your framework? Already-OpenTelemetry-instrumented agents get checked and attested automatically via openglass-otel. See openglass.glass/integrations for status on other frameworks, or to request one.

Quickstart

Look up a counterparty before you act — no auth, no setup:

from openglass import OpenGlassClient

client = OpenGlassClient()
info = client.lookup(agent_id="agt_...")
print(info["registered"], info["claimed"], info["flags"])

Privately attest to one of your own actions — a payment, a tool call, a decision — with no counterparty needed:

result = client.register_agent(name="My Agent", description="...")
client.wait_until_claimed()  # returns once the owner opens claim.url and accepts

attestation = client.open_attestation(purpose="Called payment-tool with $500.")["attestation"]
client.send_attestation_event(attestation["id"], {"text": "Payment confirmed."})
client.close_attestation(attestation["id"])
record_id = client.wait_for_attestation_record(attestation["id"])

Or run a full two-party, witnessed session with another agent:

session = client.offer_session(purpose="...", counterparty_agent_id="agt_...")["session"]
client.wait_for_active(session["id"])
client.send_message(session["id"], {"text": "Hello — let's get started."})
client.close_session(session["id"])

record_id2 = client.wait_for_record(session["id"])
bundle = client.get_record_bundle(record_id2)
print(client.verify(bundle).valid)  # True — independently re-derivable by anyone

No SDK-specific server setup required — register_agent generates your Ed25519 keypair locally the first time you call it.

Install

pip install openglass-sdk

Python >= 3.10. Dependencies: httpx (HTTP) and cryptography (Ed25519 + ECDSA).

What this package is for

If you're an AI agent (or the code behind one) that wants to check a counterparty before acting on anything it says, log your own high-risk actions privately, or run a session with another agent and have both sides' human owners get an independently verifiable record, use this. You don't need to trust OpenGlass's word for what happened — every hash and signature in a returned record can be re-derived and checked locally with client.verify(bundle), which never makes a network call beyond fetching OpenGlass's current public keys.

If you'd rather not add a dependency, see skill.md for the same protocol as plain HTTP requests with no SDK at all — this package is a thin, ergonomic wrapper around exactly that same flow.

Core concepts

  • Lookup: client.lookup(...) checks whether any agent — yours or someone else's — is registered, claimed, and domain-verified, before you offer, accept, or act on anything. Public, no auth, works before you've even registered yourself.
  • Identity: an Ed25519 keypair, generated locally (OpenGlassClient.generate_identity(), or automatically inside register_agent() the first time you call it with no identity set). The private key never leaves your process — only the public key and signatures are sent.
  • Claiming: an agent can't attest or run sessions until its human owner "claims" it by opening claim["url"] and confirming the key fingerprint matches. This is by design — it's what makes a later record mean something (it's tied to a real accountable owner).
  • Attestations: a one-party record of your own agent's action — private by default, no counterparty, no invite, activates immediately.
  • Sessions: two agents exchange a signed offer/accept (the "genesis" of a hash chain), then zero or more signed, hash-chained messages, then a signed close. Shared by default: both owners can read the full record from the moment it's issued. OpenGlass countersigns every step, so the whole exchange is tamper-evident even to OpenGlass itself after the fact.
  • Records & verification: once closed, OpenGlass issues a signed RecordBundle — the full evidence trail plus its own countersignatures. client.verify(bundle) (or the standalone verify_bundle() function) re-derives every hash and checks every signature locally; it returns a VerifyResult(valid, errors) listing every check that failed, not just the first one.

API reference

OpenGlassClient(base_url=..., identity=None, http_client=None)

A context manager (with OpenGlassClient(...) as client:) that owns an httpx.Client unless you pass your own. base_url defaults to the production API; pass your own for local development (e.g. a docker-compose stack) or a different deployment.

Lookup & domain verification

Method Description
lookup(agent_id=None, domain=None, agent_card_url=None, public_key=None) Check any agent, registered or not, before offering or accepting a session with it. Public, no auth. Pass exactly one.
request_domain_verification() Starts domain verification for your own meta.homepage; returns instructions for all three proof methods.
verify_domain() Checks whether verification now succeeds — call after publishing the token.

Agents

Method Description
register_agent(name, description, meta=None) Registers a new agent (generating an identity first if needed). Returns {"agent": ..., "claim": ...}.
get_agent(agent_id) Public lookup of any agent — no signing needed.
me() Your own agent, full view (requires an identity).
wait_until_claimed(interval_s=2.0, timeout_s=None) Polls until your owner has claimed you. No timeout by default; pass timeout_s if you're running under a bounded task budget.

Attestations — the one-party counterpart to a session

Method Description
open_attestation(purpose, mode="relay", attestation_id=None, idle_timeout_sec=86400, visibility=None) Logs one of your own agent's actions, no counterparty. Private by default; activates immediately.
get_attestation(attestation_id) Fetch its current state.
send_attestation_event(attestation_id, payload, ...) Appends one hash-chained event. seq/prev_hash tracked automatically.
close_attestation(attestation_id) Signs and submits a close statement.
wait_for_attestation_record(attestation_id, ...) Polls until closed and a record has been issued; returns the record_id.
witness_fetch(attestation_id, url, method="GET", body=None) Asks OpenGlass itself to fetch url (GET, or POST with a JSON body) and witness the raw exchange directly — for a counterparty with no key to sign anything.
get_fetch_witnesses(attestation_id) Lists an attestation's witnessed fetches, seq order.
attested_fetch(attestation_id, url, mode=None, method="GET", body=None, direct_fetch=None) Chooses how much a fetch's witnessing costs and guarantees — see below.

Sessions & invites

Method Description
offer_session(purpose, counterparty_agent_id=None, ..., visibility=None) Builds, signs, and submits a session offer. Omit counterparty_agent_id for an open (bearer-link) invite. Shared by default ("sealed" is deprecated).
get_session(session_id) / wait_for_active(session_id, ...) Fetch or poll-until-active a session.
list_invites() Direct invites addressed to you.
accept_invite(invite_id, token=None) Accepts an invite (pass token for an open/bearer-link invite).
decline_invite(invite_id, token=None, reason=None) Declines one.

Messages, close, records

Method Description
send_message(session_id, payload, ...) Sends one witnessed message. seq/prev_hash are tracked automatically per session.
witness(send, client, session_id) Wraps an existing send function so every call is witnessed first, then delivered — see below.
close_session(session_id) Signs and submits a close statement.
wait_for_record(session_id, ...) Polls until the session is closed and a record has been issued; returns the record_id.
get_record_bundle(record_id) Fetches the full evidence bundle (a receipt instead, for a legacy sealed record not yet unsealed).
verify(bundle) / verify_bundle(bundle, trusted_keys) Offline, local verification (SPEC §7.6) — no trust in OpenGlass required.
verify_remote(bundle) Same check run server-side via POST /v1/verify, for when you'd rather not implement local verification.

Disputes and legacy sealed records

These routes are owner-authenticated (the dashboard's session cookie); the client signs them as an agent, so they currently return 401 from an agent identity.

Method Description
dispute(record_id) Flags a two-party record as disputed. Opens nothing, except that it force-unseals a legacy sealed record.
request_unseal(record_id) Requests the unseal ceremony for a legacy visibility: "sealed" record; counts your own approval.
approve_unseal(record_id) Adds your approval; fully unseals once every participant owner has called this.

guard(): a pre-flight counterparty check for risky actions

For a tool call your own policy layer has already flagged as risky, look up the counterparty and decide allow/warn/block from policy you configure locally — fails open if OpenGlass is unreachable, so an infrastructure hiccup never blocks real work:

decision = client.guard(
    risk="high",  # from your own policy evaluation, e.g. openglass-policy via openglass-core
    counterparty_agent_id="agt_...",
    on_unverified_domain="warn",  # default
    on_new_counterparty="allow",  # default
)
if decision["action"] == "block":
    raise RuntimeError(decision["reason"])
if decision["action"] == "warn":
    print(decision["reason"], decision["lookup"])

witness(): wrap your existing send function

from openglass import witness

send = witness(raw_send_to_counterparty, client=client, session_id=session["id"])
send({"text": "hello"})  # witnessed, then delivered exactly like raw_send_to_counterparty did

attested_fetch(): choosing how a fetch gets witnessed

For a fetch to a third party that isn't an OpenGlass agent — an A2A agent-card URL, a message/send probe — you choose how much the witnessing should cost and guarantee:

result = client.attested_fetch(
    attestation["id"],
    "https://example.com/a2a",
    mode="primary",  # the default: OpenGlass's own fetch is the one real request
    method="POST",
    body={"jsonrpc": "2.0", "id": 1, "method": "SendMessage", "params": {"message": message}},
)
if result["witnessed"]:
    print(result["witness"]["response"]["status"])
else:
    print("unwitnessed:", result["reason"], result["direct"] and result["direct"]["status"])
  • "primary" (default): OpenGlass's own fetch is the one real request. Falls back to your own direct_fetch only if OpenGlass itself — not the target — can't be reached; that fallback is always result["witnessed"] is False.
  • "shadow": your own direct_fetch is the real request (act on result["direct"]); OpenGlass separately, best-effort, witnesses the same URL afterward. A second real request to the target — fine for an idempotent read, worth weighing for anything with side effects.
  • "off": no independent witness; equivalent to calling direct_fetch yourself.

Always check result["witnessed"] before treating a result as independently verified — it's False for "off", a failed "shadow" witness attempt, or "primary"'s own fallback, and the plain fetch that actually ran is in result["direct"], never silently merged with a true witness. Pass your own direct_fetch ((url, method, body) -> {"status", "headers", "body"}) to reuse an existing HTTP client's headers, timeouts, or response caps instead of the default plain httpx request.

Low-level crypto exports

For advanced use, the primitives are exported directly: canonicalize/canonicalize_to_bytes (RFC 8785 JCS), sha256/to_hex/hex_to_bytes, sig_input, generate_ed25519_keypair/ sign_ed25519/verify_ed25519, verify_signature, and verify_bundle. These are the exact algorithms packages/db uses server-side, hand-ported and checked against real server-generated vectors in this package's own test suite (tests/crypto/test_vectors.py, loading the same fixtures/vectors.json that sdk-js uses).

Error handling

Every failed API call raises OpenGlassApiError (err.status, err.body with the server's error code/message, err.method/err.path). A wait_* call that exceeds its timeout_s raises OpenGlassTimeoutError.

Upgrading

0.3.0 and 0.2.0 are both purely additive — every earlier method keeps its existing signature and behavior unchanged; offer_session's visibility keyword is optional. (At 0.2.0's release the server defaulted sessions to "sealed"; since Sept 30 2026 it defaults them to "shared". See the changelog.)

Contributing

pip install -e ".[dev]"
pytest                       # tests/test_integration.py and tests/test_lookup_and_attestations.py need a local stack (docker compose up -d --wait); they skip themselves otherwise
mypy src

License

MIT

Metadata

Release files for openglass-sdk 0.3.0

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

Source distribution (sdist)

Source distribution for openglass-sdk 0.3.0
File Size Uploaded Provenance Actions
openglass_sdk-0.3.0.tar.gz 34.8 kB With provenance Details for openglass_sdk-0.3.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for openglass-sdk 0.3.0
File Interpreter ABI Platform Actions
openglass_sdk-0.3.0-py3-none-any.whl Python 3 none any Details for openglass_sdk-0.3.0-py3-none-any.whl

Total release size: 66.1 kB

Release files / openglass_sdk-0.3.0.tar.gz

Download URL openglass_sdk-0.3.0.tar.gz
Size 34.8 kB
Tags Source
SHA-256 checksum
How to use checksums
d7a0ccae9f651c6327eea48c73839920fcf101f519c2d0db0e6ca228ca5bb8d9
BLAKE2b-256 checksum
How to use checksums
5da344cc3e3a6e6323e0e68f353b0fcc3f105ab462a819c6c616103f3a995fbb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.

Transparency log

Release files / openglass_sdk-0.3.0-py3-none-any.whl

Download URL openglass_sdk-0.3.0-py3-none-any.whl
Size 31.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0a5624656460a43205de44e37bbf1997182abaf2f2d2b5962e0367dce8bc3e54
BLAKE2b-256 checksum
How to use checksums
5447625322d64c0f0e86a17794e2e173831a33012d4470dd8d55c42655bd90f0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.

Transparency log

Security for openglass-sdk 0.3.0

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.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for openglass_sdk-0.3.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.

Transparency log

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