agaas-sdk
Official Python SDK for AGaaS — the Autonomous Governance Gateway.
AGaaS answers one question about an autonomous action: should it proceed? The engines behind that answer are allowed to refuse, and this SDK is built so a refusal is impossible to mistake for approval.
pip install agaas-sdk # no dependencies
from agaas_sdk import AgaasClient
with AgaasClient(api_key="agaas_live_…") as agaas:
resp = agaas.caf_gate("acme", "checkout-agent", state, action)
if resp:
do_it() # allow
else:
hold(resp.verdict.reasons) # abstain — every cause, not just the first
One call; your manifest decides. Which judges run is declared in your
manifest — not in this code and not on your API key — so the key needs only
caf:gate. Every decision lands in a tamper-evident chain (resp.audit_seq
locates it), and an abstain is returned, not raised: it is a verdict you must
act on, and the reasons say why.
The ten measurement engines are also callable directly, for calibration and analysis — see Direct engine calls. The four judges are not: they are reachable only through the gate.
Getting started from zero
The snippet above assumes you already hold a key. If you don't:
1. Create an account at https://agaas.phy357ai.com and add credits. Calls are metered — including calls that get refused, which is the main reason to care about the pre-flight section below.
2. Turn on the engines you intend to use, in the dashboard under
Settings → Engines. This is per ACCOUNT, not per key. An engine that is off
is refused with 403 engine_not_enabled wherever it could be reached.
3. Create the key under API Keys. It asks for a name and nothing else — the key inherits the operations enabled in Settings → Scopes, and follows them if you change your mind later. The secret is shown once.
4. Call something.
export AGAAS_API_KEY="agaas_live_…"
from agaas_sdk import AgaasClient
with AgaasClient() as agaas:
print(agaas.limits()) # what this deployment will accept
v = agaas.measure_transport(reference=yesterday, candidate=today)
print(v.wasserstein)
Which door each engine is behind
Two kinds of engine, reached two different ways. This is the thing to get right before writing any code:
| engines | how you call it | governed by | |
|---|---|---|---|
| Judges | CPE, Concord, Arrow, Covenant | caf_gate() only |
your manifest and Settings → Engines |
| Measures | the other ten | directly | Settings → Engines |
A judge produces a verdict, so the path it is reached by is the product: your manifest names which judges run, and the answer is hash-chained and replayable. Calling one directly would return the same number with no manifest and no chain, so it is refused:
agaas.govern_risk(...) # 403 direct_engine_call — submit it to caf_gate()
A measure returns a number with no verdict and no abstain, and a manifest has no syntax to declare one — so the account switch is its whole security axis.
| method | kind |
|---|---|
govern_risk · govern_coherence · govern_driven · measure_guarantee |
judge — via caf_gate() |
govern_coherence_relative · certify_reach · measure_signature · measure_spectrum · measure_coordination · measure_transport · measure_topology · measure_topology_drift · measure_entropy_production · measure_consensus |
measure — direct |
Note measure_guarantee (Covenant) is a judge despite the measure:
prefix — it is judged, not measured. Grouping by prefix is the one mistake this
table exists to prevent.
Which engine answers which question
No type can encode this, so it is the part worth reading rather than autocompleting:
| you want to know | call |
|---|---|
| is this action's near-term risk acceptable? | govern_risk |
| is my agent swarm still aligned? | govern_coherence |
| …and is this unusual for us specifically? | govern_coherence_relative |
| is something really driving this, or is it noise? | govern_driven |
| can I prove the system never reaches an unsafe state? | certify_reach |
| are these actors coordinating, above chance? | measure_coordination |
| how far has this distribution moved? | measure_transport |
| do my prediction intervals still hold? | measure_guarantee |
Direct engine calls
The ten measurement engines can be called on their own — the right tool for calibration, analysis, or when you deliberately want one number rather than a governed verdict. They need no scope on the key; what they need is to be enabled for the account in Settings → Engines.
v = agaas.measure_transport(reference=last_week, candidate=today)
The four judges are not available this way. govern_risk,
govern_coherence, govern_driven and measure_guarantee answer
403 direct_engine_call — submit the decision to caf_gate() and let your
manifest declare which of them run.
What makes this different from a generated client
An AGaaS engine can decline to answer. Most SDKs have nowhere to put that, so it arrives as an error to swallow or a zero to misread. Three rules follow.
A refusal never looks like a number. sigma_above_null and divergence
are unions on the wire — a float, or {"abstain": "reason"}. A binding typed
as float works in testing and breaks in production the first time an engine
declines. Here they are MetricValue, which is falsy when withheld and raises
on arithmetic rather than reading as 0.0.
if result.divergence.available:
use(float(result.divergence))
else:
log(result.divergence.reason)
An abstain is never retried. A 422 is a verdict on your input, so the
same payload abstains forever. Retrying bills you again to be refused again.
The SDK retries 429, engine_at_capacity, infrastructure 503s and pre-response
transport failures — nothing else.
Your key never touches a plaintext connection. A non-loopback http://
base URL raises at construction, before any I/O. http://127.0.0.1 stays
allowed, because that traffic never reaches a wire.
The 422 trap
AGaaS returns two error formats that share status codes:
| body | means | |
|---|---|---|
422 + {"error": …} |
JSON envelope | the engine abstained — valid input, refused answer |
422 + plain text |
bare string | your payload is malformed — a field has the wrong type |
The second comes from the web framework before AGaaS code runs, so no envelope
exists. Discriminating on status alone reports a client bug as a server verdict.
This SDK discriminates on body shape (not Content-Type, which a proxy may
rewrite) and raises AbstainedError vs BadRequestError accordingly.
Don't wait to be refused
Over-cap requests abstain. That costs no credits — an abstain returns before the audit commit, and the usage event rides that commit — but it still costs a round trip, a rate-limit token, and the time of whatever was waiting on the verdict. Pre-flight validation is on by default and catches them locally, using the server's own vocabulary:
agaas.govern_coherence({"solo": [1.0, 2.0]})
# LimitViolation: coherence: too_few_agents — got 1, graph connectivity needs >= 3
Nothing was sent. Offline, and free:
agaas-calibrate check coherence payload.json
agaas-calibrate limits --offline
Is my setup right? — doctor
The first-run failures look alike from the outside and have completely different fixes: a dead key (401), an engine switched off (403), a judge you tried to call directly (403, different reason), and an empty balance (402). Finding them one at a time through failed calls is a poor introduction to a governance API.
agaas-calibrate doctor
server https://agaas.phy357ai.com
reach ok
key valid
caps 12 engines, live from server
engines
[ok] measure:transport
[gate] govern:risk judge — call it through caf_gate()
[off] measure:spectrum off for this account (AGaaS Settings → Engines)
summary 1 callable, 4 via the gate, 9 off
It costs no credits, and that is checkable rather than a promise. The guard decides before the rate limit and long before the handler, so a refused probe consumes nothing; a permitted one passes the guard and the deliberately unparseable probe body is rejected by the JSON extractor — no handler runs, no audit is committed, and the usage event rides that same commit.
None of [gate], [off] or [absent] is an error: a judge being gate-only is
the design, and an engine switched off is a deliberate choice. For CI, name what
you actually need:
agaas-calibrate doctor --require measure_transport,measure_spectrum
That fails the build before your workload meets its first 403 in production.
Server compatibility. Older deployments refuse
GET /v1/limits. When a server does,limits()falls back to an embedded snapshot and sets.stale = True— an SDK cannot assume the deployment it is pointed at has been upgraded. Check that flag before treating a cap as authoritative.
Calibration
Several engines are relative: they answer "is this unusual for you", which is unanswerable until they know what usual looks like. The full guide — which engine needs what, and the mistakes that silently disable a gate — is in CALIBRATION.md. In short, skipping calibration gives you one of two quiet failures:
- a gate that abstains forever (never enough history), or
- a gate that never fires — a baseline so wide nothing is anomalous.
The second is the dangerous one. A governance gate that approves everything is indistinguishable from a working one until the day it was meant to stop something.
agaas-calibrate run history.json -o baselines.json # offline, free
agaas-calibrate verify baselines.json # one real call per engine
from agaas_sdk import calibrate_coherence
cal = calibrate_coherence(past_coherence_values)
if not cal.ready:
print(cal.missing) # "22 more observations (have 8, want >= 30)"
Everything is computed from data you supply. There is no synthetic default
and no "typical" baseline, because one copied from someone else's traffic
produces confident verdicts about a distribution that was never observed. Where
history is insufficient, calibration refuses and says what is missing — the
same stance the engines take. run exits non-zero if anything is blocked, so
CI can gate on it.
Two failures it catches that are otherwise silent:
- Constant history. Zero variance means the z-score divides by zero and nothing can ever be anomalous.
- Arrow's null band on the wrong scale.
govern_drivencompares the engine's entropy-production rate of your live series against a null band, so the band must be entropy-production rates too — build it withmeasure_null_scores, which measures each equilibrium window through the engine. A locally-invented statistic miscalibrates the gate. (Arrow is also the one calibrator that sends data to the service — see CALIBRATION.md.)
Design
Hexagonal, with three ports (Transport, Clock, CredentialStore) as
structural Protocols. Supply your own by shape — no subclassing.
client = AgaasClient(key, transport=MyRecordingTransport(), clock=FakeClock())
The whole test suite runs with no network and no wall-clock time.
Zero required dependencies. The default transport is urllib. This package
carries a credential, and every transitive dependency is code that could read
it. pip install agaas-sdk[httpx] adds pooling and HTTP/2;
agaas-sdk[async] adds AsyncAgaasClient.
Request construction lives in one module shared by both clients, and the calibration CLI ships inside the SDK rather than beside it. Splitting them puts the same credential handling in two codebases, where a fix applied to one can silently miss the other.
Coverage
All 14 engines: govern_risk · govern_coherence ·
govern_coherence_relative · govern_driven · certify_reach ·
measure_signature · measure_spectrum · measure_coordination ·
measure_transport · measure_topology · measure_topology_drift ·
measure_entropy_production · measure_guarantee · measure_consensus
Errors
| exception | status | retried |
|---|---|---|
AbstainedError |
422 + envelope | never — same input abstains forever |
BadRequestError |
400 / 415 / 422 plain | never — the bug is local |
AuthenticationError |
401 | no |
PermissionError_ |
403 | no |
PaymentRequiredError |
402 | no — carries topup_url |
PayloadTooLargeError |
413 | no |
RateLimitError |
429 | yes, honouring Retry-After |
CapacityError |
503 engine_at_capacity |
yes — clears in ~1 s |
ServiceUnavailableError |
503 infra | yes, backing off hard |
ServerError |
500 | no — deterministic engines fail identically |
TransportError |
no response | yes |
Backoff jitter is derived by hashing (key, attempt): reproducible for one
client, decorrelated across clients, so a fleet does not retry in lockstep
after a shared outage.
Support and security
Questions, bugs: scitechfamily357@gmail.com (agaas-sdk in the subject).
Security issues: report them privately to the same address — see SECURITY.md. This package handles API credentials, so a public report exposes every installed copy before a fixed version can ship, and a released version on an index can never be overwritten, only superseded.
Never include a real API key in a report. If one leaked, rotate it in the dashboard first — that is faster and more certain than any fix.
License
MIT
Metadata
Release files for agaas-sdk 0.1.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| agaas_sdk-0.1.3.tar.gz | 78.1 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| agaas_sdk-0.1.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 146.0 kB
Release files / agaas_sdk-0.1.3.tar.gz
| Download URL | agaas_sdk-0.1.3.tar.gz |
|---|---|
| Size | 78.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9949f339c05ac3d21640d7b8d2f2669c5536abcc9cc65895021cea104d8efd86
|
|
BLAKE2b-256 checksum How to use checksums |
08c13311b8de0ae017367c5b2d084e2839a1d9c89b066c120c4517f829f945a9
|
| 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 Aug 6, 2026.
Transparency logRelease files / agaas_sdk-0.1.3-py3-none-any.whl
| Download URL | agaas_sdk-0.1.3-py3-none-any.whl |
|---|---|
| Size | 68.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6a7623c1b28ce367d55b143fb6469e25c3cccece9bc727d6239e72c4d6168ad7
|
|
BLAKE2b-256 checksum How to use checksums |
9dc8def49d5cfda163dee6089439f3bd6350e509d877f775a9125c037e8b3541
|
| 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 Aug 6, 2026.
Transparency logSecurity for agaas-sdk 0.1.3
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
All 2 files in this release have been uploaded with provenance metadata.
Attestation for agaas_sdk-0.1.3.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 Aug 6, 2026.
Transparency logA 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.