The service contract
Download the OpenAPI 3.1 contract for routes, authentication, and response shapes. Some request bodies do not yet have a complete type definition. Remaining setup notes ship with the evaluation package. The schema is public. Request evaluation packages for a configured installation and integration help.
The default listener address is 127.0.0.1:8090, configured with platformd -listen. Packaged Compose uses TLS by default; retain and trust the deployment certificate through your operator's authenticated channel. Native TLS requires a certificate/key pair. Serving plain HTTP requires the explicit -allow-insecure-http flag. The HTTP examples below assume that opt-in on a dedicated local test deployment; use your operator's HTTPS endpoint for a TLS deployment.
The task, approval, entitlement, and receipt list routes return a page. For these routes, pass limit from 1 to 200 and continue with the previous page's cursor. Capabilities, catalog, and manager-card responses use their own documented array shapes and declare no pagination parameters.
Authenticate with an operator-issued token
Your deployment operator issues a bearer token. Send it in Authorization: Bearer ... or X-AAES-Token. Either header authenticates the caller. A deployment can instead use mutual TLS: the caller supplies a verified certificate whose subject identifies a registered actor. In that mode, AAES Govern refuses bearer tokens. The credential identifies the caller and its organization’s deployment account, or tenant.
GET /healthz, GET /readyz, and POST /approvals/{channel}/callback are unauthenticated in the contract: no daemon-issued bearer credential is used on them. The callback still authenticates the channel: Slack posts a form body verified by the X-Slack-Signature HMAC; Teams posts a Bot Framework activity whose bearer JWT is verified against the Bot Connector's OpenID metadata with the bot's app ID as required audience.
| Variable | Purpose |
|---|---|
AAES_ENDPOINT | The daemon base URL, configured with platformd -listen. Default: http://127.0.0.1:8090. |
AAES_TOKEN | The operator-issued bearer token. Send it in Authorization: Bearer ... or X-AAES-Token. |
ActionRequest and BrokeredRequest require tenant_id and actor_id. Those fields are claims that must match the token, not a tenant picker. The SDKs fill them. A refusal is JSON with a reason, and a remedy when the daemon can name the smallest satisfying change.
First request to a configured deployment
Ask your operator for a running daemon URL and an operator-issued bearer token for a registered caller. Request an evaluation if you need the binaries, SDKs, or setup notes.
1. Set the connection
Use your operator's URL. The HTTP address below is for a daemon running on your own machine with -allow-insecure-http explicitly enabled. For packaged TLS, use the HTTPS endpoint and configure certificate trust; for example, curl accepts the retained certificate with --cacert /path/to/tls.crt. Supply the token through your environment. Do not put it in source code.
export AAES_ENDPOINT="http://127.0.0.1:8090"
: "${AAES_TOKEN:?Set AAES_TOKEN to the token from your deployment operator}"2. Read the capabilities you may use
curl --fail-with-body -sS "$AAES_ENDPOINT/v1/capabilities" \
-H "Authorization: Bearer $AAES_TOKEN"This read lists the caller's permitted capabilities. An empty list means none were returned for this caller.
{
"tenant_id": "your-tenant",
"actor_id": "your-agent",
"capabilities": []
}The identifiers above are illustrative. To discover capabilities you may request access to, call GET /v1/catalogue.
3. Handle errors before proceeding
Read the refusal reason before resubmitting. Preserve the effect key when following a documented retry procedure; changing it can create a duplicate effect.
| Response or failure | Meaning | Next action |
|---|---|---|
| Authentication or access refusal | The caller lacks valid authentication or permission. | Ask your operator to check the token and caller permissions. |
| Daemon-originated 503 | A required step could not complete safely. On a brokered path, an external effect may already have happened when its outcome could not be recorded. | Read the reason and reconcile the original intent and provider outcome. Repeat only as documented, preserving the request and effect key. |
| 403 after sealing | The decision-shaped response includes a sealed receipt showing how far processing progressed. | Inspect the receipt and refusal reason before deciding what to do next. |
| Federated-route 503 | Mint or marker failure can follow a sealed decision. No grant material was released and the live-grant slot is held. | A retry with the same effect-key step is permitted. |
| Timeout, connection reset, intermediary error, or missing response | The outcome is unknown. | Reconcile first. A missing receipt does not prove nothing was committed. |
| 409 conflict | A duplicate-effect reason identifies an existing recorded claim, not downstream success. Other state conflicts also use 409. | Read the reason and inspect the original decision. Do not create a new effect key to bypass the conflict. |
To reconcile, query GET /v1/receipts?task_id=… and match the published intent, effect, and effect-id fields. The projection omits caller correlation identifiers. If you cannot identify the decision, give your operator the task ID, effect-key step, and correlation identifiers so they can inspect the journal.
Complete a deferred decision
A 202 response means the decision is deferred: it has not authorized execution yet. Keep the original request body, task, and effect key. After the required condition changes, use the matching resume route:
POST /v1/action/resumerechecks an action decision.POST /v1/brokered/resumerechecks a brokered action and executes only if it is allowed.
Revalidation can defer again. A 404 means no matching standing deferral exists.
The SDK resume/Resume method uses the action-decision route only. For brokered resume, use resumeBrokered/resume_brokered/ResumeBrokered (available from SDK 0.1.0), or call the HTTP route directly.
Next: request an action decision
Your operator must first register the capability and caller permissions, configure the policy and task budget, and provide a valid task ID. Use a new effect key for each new action and preserve it when following the documented retry procedure. Actions classified as irreversible require approval by an authorized person.
POST /v1/action records a decision and, when allowed, mints a grant; it does not execute the downstream action. POST /v1/brokered decides and executes through a configured connector. POST /v1/observe reports an effect. Use the OpenAPI contract and SDK examples for the request types in your evaluation release.
Quickstart: one governed test action
Ask your operator to register a synthetic, non-chargeable read capability, configure its connector and permissions, and supply a task ID. Set AAES_TEST_CAPABILITY and AAES_TEST_TASK_ID to those values, install the Python SDK, and keep the connection settings above. This example executes only the registered test read through AAES Govern's connector.
import os
from aaes import AaesError, Client
client = Client.from_env()
task_id = os.environ["AAES_TEST_TASK_ID"]
request = dict(
capability=os.environ["AAES_TEST_CAPABILITY"],
action="read",
task_id=task_id,
effect_key_step="governed-read-demo-01",
)
try:
method = client.resume_brokered if os.environ.get("AAES_RESUME") == "1" else client.brokered
result = method(**request)
decision = result.decision
if decision.deferred:
raise SystemExit("Deferred: ask the operator to resolve the required condition, "
"then set AAES_RESUME=1 and rerun this identical request.")
if not decision.ok:
raise SystemExit(str(decision.refusal or decision.reason))
print("Authorized intent:", decision.intent_id)
print("Provider outcome:", result.outcome)
print("Recorded evidence:", client.list_receipts(task_id=task_id))
except AaesError as error:
raise SystemExit(str(error))Use this effect key for this one test action only. Keep it when resuming or following the documented retry procedure; use a new key for a new action. A timeout or connection error does not establish the provider outcome, so reconcile before retrying. Then ask your operator for the export, obtain its signing public key through a separately trusted channel, and check it offline:
aaesverify --export <export.jsonl> --pubkey <trusted-key.pub>An export check establishes integrity within that trust configuration. It does not establish complete capture or downstream success.
Route inventory
The integration-operations routes are mounted only when the deployment configures an integration-operations document. They are absent otherwise and are not agent SDK methods.
These routes belong to the daemon contract. Bearer or X-AAES-Token is required except where the table says otherwise. Download the OpenAPI 3.1 contract for payloads, parameters, and response schemas.
| Family | Method | Route | Purpose |
|---|---|---|---|
| Decision | POST | /v1/action | Record a decision and, when allowed, mint a grant. Does not execute the downstream action. |
| Decision | POST | /v1/brokered | Decide and execute through AAES Govern's connector. |
| Decision | POST | /v1/action/resume | Revalidate a deferred action decision using the unchanged body and effect key. Does not execute the downstream action. |
| Decision | POST | /v1/brokered/resume | Revalidate and, if allowed, execute a deferred brokered action using the unchanged body and effect key. |
| Decision | POST | /v1/federate | Federation interface; unavailable in the supplied distribution. Calls return 403 ("no federated backend") before the decision runs until an operator wires a minting backend. |
| Decision | POST | /v1/observe | Report an effect authorized under pass_through custody. |
| Grants | POST | /v1/grants/present | Bind a stored grant to the authenticated caller. |
| Grants | POST | /v1/grants/receipt | Journal the observed effect of a presented grant. |
| Discovery | GET | /v1/capabilities | Read the capabilities this caller may use. |
| Discovery | GET | /v1/catalogue | Read capabilities this caller can request access to. |
| Access | POST | /v1/access-requests | Request access. |
| Access | GET | /v1/access-requests/{id} | Read an access request. |
| Access | POST | /v1/access-requests/{id}/revoke | Revoke an access request. |
| Access | GET | /v1/manager-cards | Read manager cards. |
| Access | POST | /v1/manager-cards/decide | Submit a manager-card decision. |
| Access | GET | /v1/approvals | Read approvals. |
| Access | GET | /v1/approvals/{id} | Read an approval. |
| Access | GET | /v1/entitlements | Read entitlements. |
| Access | POST | /approvals/{channel}/callback | Receive an approval-channel callback. No daemon-issued bearer credential; the channel's own proof is required: Slack's HMAC signature or the Teams Bot Connector JWT with audience validation. |
| Task | GET | /v1/task | Read tasks. |
| Task | GET | /v1/task/{id} | Read a task. |
| Task | GET | /v1/task/{id}/execution-constraints | Read the immutable root execution profile and visible admissions. Operators and task sponsors receive the full ledger; other task readers receive scoped reservation identities. |
| Task | POST | /v1/task/{id}/execution-constraints | The registered human sponsor installs the immutable execution plan on an unused draft root. This is not an agent SDK mutation. |
| Evidence | GET | /v1/receipts | Read receipts. |
| Evidence | GET | /v1/receipts/{id} | Read a receipt. |
| Integration operations | GET | /v1/integration-ops/surfaces | Registered human only. List configured surface IDs without contacting adapters or exposing credential references; listing does not prove connectivity. |
| Integration operations | POST | /v1/integration-ops/connection-check | Registered human operator only. Read the configured adapter's answer for a surface and credential reference; this is not live vendor verification. |
| Integration operations | POST | /v1/integration-ops/rotate | Human administrator only. Move the surface to a new credential reference and retire the old reference. |
| Integration operations | POST | /v1/integration-ops/revoke | Human administrator only. Withdraw a configured surface so new operations on it are refused; the receipt does not prove live vendor revocation. |
| Health | GET | /healthz | Check health. Unauthenticated. |
| Health | GET | /readyz | Check readiness. Unauthenticated. |
Federation: decide here, execute at the application
Federation interface; unavailable in the supplied distribution. The route and SDK method exist, but no federated minting backend is wired in this distribution: calls return 403 ("no federated backend") before the decision runs. Successful issuance requires a separately integrated and validated backend; the contract's documented 200 response describes that conditional behavior.
Where a backend is wired, POST /v1/federate runs the full decision and returns a short-lived federated grant. The agent then calls the application directly with that grant. The downstream request and response payloads travel directly between the workload and the application rather than through AAES Govern; Govern still processes authorization metadata and may return sensitive credential material or issuance instructions.
/v1/actionrecords a decision and, when allowed, mints a grant./v1/brokereddecides and executes through AAES Govern's connector./v1/federatedecides and mints a federated grant for the agent's application call, when a minting backend is wired; refused with 403 in the supplied distribution./v1/observereports an effect for an existing intent authorized underpass_throughcustody; it is not a general-purpose endpoint for arbitrary external events./v1/grants/presentbinds a stored grant./v1/grants/receiptjournals the observed effect.
The operator console
The operator console is served by the AAES Govern process on a separate listener. It is not in the daemon OpenAPI contract, even where names look similar.
Console routes include /api/approvals, /api/spend, /api/records, /api/theme, and /api/settings/appearance, along with the console's agents, capabilities, policies, integrations, and deployment routes.
Other shapes of the same surface
SDKs
Use Go, Python, or TypeScript clients for the daemon. Receipt verification belongs to the offline CLI.
MCP
Expose the daemon through an MCP facade. Policy, capability registrations, and application credentials remain in the daemon.
For offline evidence verification, see the CLI guide. Return to the developer overview for the full integration surface.