Observed since 20 Oct, 21:18 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Official Python SDK for AGaaS — the Autonomous Governance Gateway. Ask before you act.
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.
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)
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.
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 |
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.
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.
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.
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
doctorThe 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.
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:
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:
govern_driven compares 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 with
measure_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.)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.
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
| 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.
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.
MIT
pypistats · 54 observations shown. Missing days are unknown. Source category: overall: without mirrors.
| Date / source period | Value | Observed at |
|---|---|---|
| 2026-10-15 – 2026-10-15 | 1 | 2026-10-20T21:57:12.5218116Z |
| 2026-10-13 – 2026-10-13 | 1 | 2026-10-20T21:57:12.5218116Z |
| 2026-10-12 – 2026-10-12 | 2 | 2026-10-20T21:57:12.5218116Z |
| 2026-10-11 – 2026-10-11 | 1 | 2026-10-20T21:57:12.5218116Z |
| 2026-10-10 – 2026-10-10 | 1 | 2026-10-20T21:57:12.5218116Z |
| 2026-10-09 – 2026-10-09 | 1 | 2026-10-20T21:57:12.5218116Z |
| 2026-10-07 – 2026-10-07 | 11 | 2026-10-20T21:57:12.5218116Z |
| 2026-10-06 – 2026-10-06 | 1 | 2026-10-20T21:57:12.5218116Z |
| 2026-10-04 – 2026-10-04 | 1 | 2026-10-20T21:57:12.5218116Z |
| 2026-10-03 – 2026-10-03 | 1 | 2026-10-20T21:57:12.5218116Z |
| 2026-10-02 – 2026-10-02 | 3 | 2026-10-20T21:57:12.5218116Z |
| 2026-10-01 – 2026-10-01 | 1 | 2026-10-20T21:57:12.5218116Z |
| 2026-09-30 – 2026-09-30 | 1 | 2026-10-20T21:57:12.5218116Z |
| 2026-09-28 – 2026-09-28 | 2 | 2026-10-20T21:57:12.5218116Z |
| 2026-09-27 – 2026-09-27 | 1 | 2026-10-20T21:57:12.5218116Z |
| 2026-09-26 – 2026-09-26 | 1 | 2026-10-20T21:57:12.5218116Z |
| 2026-09-23 – 2026-09-23 | 2 | 2026-10-20T21:57:12.5218116Z |
| 2026-09-22 – 2026-09-22 | 5 | 2026-10-20T21:57:12.5218116Z |
| 2026-09-21 – 2026-09-21 | 1 | 2026-10-20T21:57:12.5218116Z |
| 2026-09-20 – 2026-09-20 | 8 | 2026-10-20T21:57:12.5218116Z |
| 2026-09-18 – 2026-09-18 | 2 | 2026-10-20T21:57:12.5218116Z |
| 2026-09-16 – 2026-09-16 | 9 | 2026-10-20T21:57:12.5218116Z |
| 2026-09-15 – 2026-09-15 | 2 | 2026-10-20T21:57:12.5218116Z |
| 2026-09-14 – 2026-09-14 | 10 | 2026-10-20T21:57:12.5218116Z |
| 2026-09-13 – 2026-09-13 | 9 | 2026-10-20T21:57:12.5218116Z |
| 2026-09-12 – 2026-09-12 | 1 | 2026-10-20T21:57:12.5218116Z |
| 2026-09-10 – 2026-09-10 | 1 | 2026-10-20T21:57:12.5218116Z |
| 2026-09-07 – 2026-09-07 | 5 | 2026-10-20T21:57:12.5218116Z |
| 2026-09-04 – 2026-09-04 | 2 | 2026-10-20T21:57:12.5218116Z |
| 2026-09-01 – 2026-09-01 | 1 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-31 – 2026-08-31 | 2 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-28 – 2026-08-28 | 10 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-27 – 2026-08-27 | 9 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-24 – 2026-08-24 | 6 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-23 – 2026-08-23 | 3 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-22 – 2026-08-22 | 4 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-20 – 2026-08-20 | 1 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-18 – 2026-08-18 | 4 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-17 – 2026-08-17 | 10 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-14 – 2026-08-14 | 6 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-13 – 2026-08-13 | 7 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-11 – 2026-08-11 | 21 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-09 – 2026-08-09 | 6 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-08 – 2026-08-08 | 5 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-07 – 2026-08-07 | 4 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-06 – 2026-08-06 | 102 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-05 – 2026-08-05 | 4 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-04 – 2026-08-04 | 6 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-03 – 2026-08-03 | 15 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-02 – 2026-08-02 | 6 | 2026-10-20T21:57:12.5218116Z |
| 2026-08-01 – 2026-08-01 | 12 | 2026-10-20T21:57:12.5218116Z |
| 2026-07-31 – 2026-07-31 | 92 | 2026-10-20T21:57:12.5218116Z |
| 2026-07-29 – 2026-07-29 | 34 | 2026-10-20T21:57:12.5218116Z |
| 2026-07-28 – 2026-07-28 | 175 | 2026-10-20T21:57:12.5218116Z |
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.1.3 | 6 Aug 2026 | 4 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 21:18 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:251a5d4c07626992f4621edcaea4b877ceab0801a44ef413dc5412b0a5a52a75