Skip to main content

Protocol Reference

This page defines the HTTP endpoint and schema reference for ANIP 0.24. It is the implementation-facing reference — use it alongside the concept pages (Capabilities, Delegation, Failures, Trust) which explain the why.

Endpoints​

An ANIP HTTP service exposes these standard endpoints:

EndpointMethodAuthSection
/.well-known/anipGETNoneDiscovery
/.well-known/jwks.jsonGETNoneJWKS
/anip/manifestGETNoneManifest
/anip/tokensPOSTBearerToken Issuance
/anip/permissionsPOSTBearerPermission Discovery
/anip/invoke/{capability}POSTBearerInvocation
/anip/approval_grantsPOSTBearerApproval Grants
/anip/auditPOSTBearerAudit
/anip/checkpointsGETNoneCheckpoints
/anip/checkpoints/{id}GETNoneCheckpoint Detail

/anip/approval_grants is required when the service can emit approval_required. Services that never emit approval-required continuations do not need to advertise it.

Some runtimes and profiles may also advertise optional endpoints such as handshake, capability graph, or test endpoints. A service must only advertise endpoints it actually implements. For non-HTTP transports, see Transports.


Discovery​

GET /.well-known/anip

No authentication required. This is the entry point for any agent discovering the service.

Response​

{
"anip_discovery": {
"version": "0.24.4",
"service_id": "travel-service",
"endpoints": {
"manifest": "/anip/manifest",
"tokens": "/anip/tokens",
"permissions": "/anip/permissions",
"invoke": "/anip/invoke/{capability}",
"approval_grants": "/anip/approval_grants",
"audit": "/anip/audit",
"checkpoints": "/anip/checkpoints"
},
"capabilities": {
"search_flights": {
"description": "Search available flights",
"side_effect": { "type": "read" },
"minimum_scope": ["travel.search"],
"financial": false
},
"book_flight": {
"description": "Book a flight reservation",
"side_effect": { "type": "irreversible" },
"minimum_scope": ["travel.book"],
"financial": true
}
},
"trust": {
"level": "signed",
"anchoring": { "cadence": "hourly" }
},
"metadata_disclosure": {
"caller_class": "all",
"failure_detail": "full"
}
}
}

Fields​

FieldTypeRequiredDescription
versionstringYesProtocol version (e.g., "0.24.4")
service_idstringYesUnique service identifier
endpointsobjectYesMap of operation names to URL paths
capabilitiesobjectYesLightweight capability summaries (name → metadata)
trustobjectYesTrust posture: level (declarative, signed, anchored) and optional anchoring cadence
metadata_disclosureobjectNoControls what metadata is disclosed to different caller classes

Each capability summary in discovery includes description, side_effect.type, minimum_scope[], and financial (boolean). The full declarations are in the manifest.


JWKS​

GET /.well-known/jwks.json

No authentication required. Returns the service's public signing keys in standard JWKS format.

Response​

{
"keys": [
{
"kty": "EC",
"crv": "P-256",
"x": "base64url-x-coordinate...",
"y": "base64url-y-coordinate...",
"kid": "primary-signing-key",
"use": "sig",
"alg": "ES256"
}
]
}

Used to verify: manifest signatures (X-ANIP-Signature header), delegation token JWTs, and checkpoint signatures.


Manifest​

GET /anip/manifest

No authentication required. Returns the full capability declarations with a cryptographic signature.

Response headers​

X-ANIP-Signature: eyJhbGciOiJFZERTQSJ9...

Response body​

{
"manifest_metadata": {
"version": "0.24.4",
"sha256": "a1b2c3d4...",
"issued_at": "2026-03-28T10:00:00Z",
"expires_at": "2026-03-29T10:00:00Z"
},
"service_identity": {
"id": "travel-service",
"jwks_uri": "/.well-known/jwks.json",
"issuer_mode": "self"
},
"trust": {
"level": "signed",
"anchoring": { "cadence": "hourly" }
},
"capabilities": {
"search_flights": {
"description": "Search available flights between airports",
"contract_version": "1.0",
"inputs": [
{
"name": "origin",
"type": "airport_code",
"required": true,
"description": "Departure airport (IATA code)"
},
{
"name": "destination",
"type": "airport_code",
"required": true,
"description": "Arrival airport (IATA code)"
},
{
"name": "date",
"type": "date",
"required": false,
"description": "Travel date (ISO 8601)"
}
],
"output": {
"type": "flight_list",
"fields": ["flight_number", "origin", "destination", "price"]
},
"side_effect": {
"type": "read"
},
"minimum_scope": ["travel.search"],
"cost": { "certainty": "fixed" },
"response_modes": ["unary"],
"observability": {
"logged": true,
"retention": "90d"
}
},
"book_flight": {
"description": "Book a flight reservation",
"contract_version": "1.0",
"inputs": [
{ "name": "flight_number", "type": "string", "required": true },
{ "name": "passengers", "type": "integer", "required": true, "default": 1 }
],
"output": {
"type": "booking_confirmation",
"fields": ["booking_id", "status", "total_cost"]
},
"side_effect": {
"type": "irreversible"
},
"minimum_scope": ["travel.book"],
"cost": {
"certainty": "estimated",
"financial": {
"currency": "USD",
"range_min": 200,
"range_max": 800,
"typical": 420
}
},
"requires": [
{ "capability": "search_flights", "reason": "must verify flight exists" }
],
"response_modes": ["unary"],
"observability": {
"logged": true,
"retention": "365d",
"fields_logged": ["flight_number", "passengers"]
}
}
}
}

Capability declaration fields​

FieldTypeRequiredDescription
descriptionstringYesHuman-readable description
contract_versionstringYesSemantic version of this capability's contract
inputsarrayYesInput parameter declarations (see below)
outputobjectYesOutput shape: type and fields[]
side_effectobjectYesSide-effect declaration (see below)
minimum_scopestring[]YesRequired scope strings for delegation
costobjectNoCost declaration (see below)
requiresarrayNoPrerequisite capabilities
kindstringNoatomic or composed. Default: atomic.
compositionobjectRequired when kind is composedDeclarative v0.23 internal step graph.
business_effectsobjectNoDeclared business outputs and explicit non-outputs.
requires_bindingarrayNoExecution-time binding requirements.
control_requirementsarrayNoToken-evaluable preconditions surfaced in permissions.
response_modesstring[]No["unary"], ["streaming"], or ["unary", "streaming"]. Default: ["unary"]
observabilityobjectNoLogging and retention posture
refresh_viastring[]NoAdvisory: capabilities to re-invoke when a stale or missing artifact causes a failure. Every name must exist in the same manifest.
verify_viastring[]NoAdvisory: capabilities to invoke to verify side effects after executing this capability. Every name must exist in the same manifest.
cross_serviceobjectNoAdvisory cross-service handoff hints. See Cross-service handoff hints (v0.19).

Input field​

FieldTypeRequiredDescription
namestringYesParameter name
typestringYesSemantic type hint (e.g., "string", "airport_code", "integer")
requiredbooleanNoDefault: true
defaultanyNoDefault value if not provided
descriptionstringNoHuman-readable description
semantic_typestringNov0.24 typed hint for planner/runtime behavior, such as entity_reference, scope, time_window, or domain-specific semantic names.
entity_referencebooleanNoWhether the input names a concrete entity that may need resolution.
allowed_valuesarrayNoClosed set of allowed values. Required when resolution.mode is closed_values.
catalog_refstringNoIdentifier for a backend or app catalog used to resolve values. This is a catalog identity, not an inline value list.
input_meaningsobjectNoOptional consumer-facing explanation of how to interpret the input.
resolutionobjectNov0.24 input-resolution policy. See below.

Input resolution (v0.24)​

The resolution block tells runtimes and consuming agents how an input should be supplied or resolved. It prevents fragile behavior such as treating every capitalized word as a valid entity or requiring every possible customer/account/project name to be hardcoded in the contract.

{
"name": "account_ref",
"type": "string",
"required": true,
"semantic_type": "entity_reference",
"entity_reference": true,
"catalog_ref": "gtm.account_catalog",
"resolution": {
"mode": "backend_resolved",
"resolver_ref": "gtm.account_catalog",
"on_missing": "clarify",
"on_ambiguous": "clarify",
"on_unresolved": "deny"
}
}
FieldTypeRequiredDescription
modestringYesResolution mode. See values below.
resolver_refstringNoResolver or catalog identifier used by the service/app to resolve the value.
on_missingstringNoBehavior when caller omits the value. See behavior values below.
on_ambiguousstringNoBehavior when multiple candidate values match.
on_unresolvedstringNoBehavior when no candidate value can be resolved.

Resolution modes:

ModeMeaning
closed_valuesValue must be one of allowed_values.
backend_resolvedService resolves a concrete reference through a backend resolver/catalog.
actor_policyService derives the value from actor/session/tenant policy.
actor_policy_or_explicitService may derive the value from actor policy, but caller may provide an explicit value when allowed.
app_selectedConsuming app may select the value within declared bounds.
explicit_onlyCaller must provide the value directly; runtime should not infer it.
clarifyRuntime/app should ask for clarification when the value is missing or ambiguous.

Resolution behavior values for on_missing, on_ambiguous, and on_unresolved:

ValueMeaning
clarifyAsk the caller/user for the missing or ambiguous value.
use_defaultUse the input's declared default.
use_actor_scopeDerive from actor/session/tenant scope.
app_select_or_clarifyConsuming app may select within bounds, otherwise clarify.
denyDeny the request.
deny_or_clarifyDeny when unsafe; clarify when recoverable.
omitOmit the value when optional and safe.

Cross-field validation:

  • closed_values requires allowed_values.
  • use_default requires default.
  • catalog_ref and resolver_ref are identifiers; they must not embed secret material.
  • Runtime implementations should honor resolution before falling back to legacy heuristics.

Side-effect types​

ValueMeaning
readNo state change. Safe to call speculatively.
writeReversible state change.
transactionalState change with a rollback window. Has optional rollback_window (duration) and compensation (capability name).
irreversiblePermanent state change. Cannot be undone.

Cost declaration​

FieldTypeDescription
certaintystring"fixed", "estimated", or "dynamic"
financialobjectOptional: currency, range_min, range_max, typical
computeobjectOptional: expected_duration, resource hints
determined_bystringOptional: what determines the cost (e.g., "passenger_count")

Cross-service hints (v0.19)​

The cross_service object contains four optional arrays, each of type ServiceCapabilityRef[]:

ArrayDescription
handoff_toCapabilities on other services this capability naturally leads into
refresh_viaCapabilities on other services that refresh a stale artifact
verify_viaCapabilities on other services that verify side effects
followup_viaCapabilities on other services useful after this one completes

ServiceCapabilityRef (v0.19)​

FieldTypeRequiredDescription
servicestringYesThe service identifier of the target service
capabilitystringYesThe capability name on that service

Composition (v0.23)​

When kind is composed, the capability must declare composition.

FieldTypeRequiredDescription
authority_boundarystringYessame_service in v0.23. Reserved values such as same_package are rejected until specified.
stepsarrayYesOrdered internal steps. Each step references an atomic capability.
input_mappingobjectYesMaps parent inputs or previous step outputs into child step parameters.
output_mappingobjectYesMaps step outputs into the parent result.
failure_policystringYesHow child failures affect parent invocation.
empty_result_policystringNoHow empty/null child output should be handled.
empty_result_outputobjectRequired for return_success_no_results with an empty-result sourceParent output when empty-result success is returned.
audit_policyobjectYesChild invocation linkage and task-lineage behavior.

Composition is service-owned. The agent invokes one business capability; the service or runtime owns internal step execution and audit linkage.


Token Issuance​

POST /anip/tokens

Authentication: Bearer token (API key for bootstrap, existing JWT for delegation).

Request​

{
"scope": ["travel.search", "travel.book"],
"capability": "book_flight",
"subject": "agent-007",
"purpose_parameters": {
"task_id": "trip-planning-2026"
},
"budget": {
"currency": "USD",
"max_amount": 500
},
"concurrent_branches": "exclusive",
"ttl_hours": 2
}
FieldTypeRequiredDescription
scopestring[]YesRequested scope strings
capabilitystringNoSpecific capability this token is for
subjectstringYes (bootstrap)Subject identifier for the delegated principal
parent_tokenstringNoToken ID string of the parent token for delegated issuance. Omit for root issuance.
purpose_parametersobjectNoOpaque purpose metadata such as task_id
budgetobjectNoBudget constraint stored as constraints.budget in the token
caller_classstringNoIssuer-supplied caller classification for disclosure policy
concurrent_branchesstringNoallowed or exclusive. Default: allowed.
ttl_hoursnumberNoToken lifetime in hours. Default: 2

Root issuance authenticates with a bootstrap credential and omits parent_token. Delegated issuance authenticates with an existing ANIP JWT and includes parent_token.

parent_token is a token ID string, not a JWT. The service looks up the parent token by ID and validates narrowing against stored token state.

Response​

{
"issued": true,
"token_id": "tok_root_001",
"token": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9...",
"scope": ["travel.search", "travel.book"],
"capability": "book_flight",
"task_id": "trip-planning-2026",
"budget": {
"currency": "USD",
"max_amount": 500
},
"expires_at": "2026-03-28T12:00:00Z"
}

Budget constraints​

The token issuance request can include a budget field, which the service stores as constraints.budget in the JWT claims:

{
"scope": ["travel.search", "travel.book"],
"subject": "agent-007",
"budget": {
"currency": "USD",
"max_amount": 500
},
"ttl_hours": 2
}
FieldTypeRequiredDescription
budget.currencystringYesISO 4217 currency code
budget.max_amountnumberYesMaximum spend ceiling

Budget narrowing rule: When delegating from a parent token, the child budget MUST NOT exceed the parent's budget. If the parent has max_amount: 500, the child cannot request max_amount: 600. Currency must match. If the parent has no budget, the child MAY introduce one.

Delegation rules​

  • Scope can only narrow, never widen. A delegated token cannot have scope the parent doesn't have.
  • Budget can only narrow, never widen. The token's constraints.budget is the enforceable ceiling.
  • Capability binding can only narrow. A child token cannot escape the parent's bound capability.
  • Purpose/task constraints can only narrow. If a token has purpose.task_id, invocation task_id must match or be omitted.
  • The service signs tokens with its configured signing key. Any replica with the same key material can verify them.

Permission Discovery​

POST /anip/permissions

Authentication: Bearer JWT delegation token.

Request​

{}

Response​

{
"available": [
{
"capability": "search_flights",
"scope_match": "travel.search",
"constraints": {}
}
],
"restricted": [
{
"capability": "book_flight",
"reason": "missing scope: travel.book",
"reason_type": "insufficient_scope",
"grantable_by": "human:[email protected]",
"resolution_hint": "request_broader_scope"
}
],
"denied": [
{
"capability": "admin_reset",
"reason": "requires admin principal class",
"reason_type": "non_delegable"
}
]
}

Three-bucket model​

BucketMeaning
availableToken has sufficient scope. Fields: capability, scope_match, constraints
restrictedMissing a grantable scope. Fields: capability, reason, reason_type, grantable_by, unmet_token_requirements, resolution_hint
deniedStructurally impossible (wrong principal class). Fields: capability, reason, reason_type

Permission response fields — restricted entry (v0.15)​

FieldTypeRequiredDescription
capabilitystringYesCapability name
reasonstringYesHuman-readable explanation of the restriction
reason_typestringYesMachine-readable restriction category (see below)
grantable_bystringNoPrincipal who can grant the missing authority
unmet_token_requirementsstring[]NoUnsatisfied control_requirements types
resolution_hintstringNoShort actionable suggestion for resolving the restriction

Permission response fields — denied entry (v0.15)​

FieldTypeRequiredDescription
capabilitystringYesCapability name
reasonstringYesHuman-readable explanation of the denial
reason_typestringYesMachine-readable denial category (see below)

reason_type values​

ValueWhen used
insufficient_scopeToken lacks one or more required scope strings
insufficient_delegation_depthDelegation chain is too deep for this capability
stronger_delegation_requiredToken needs explicit capability binding or tighter purpose constraints
unmet_control_requirementToken does not satisfy a declared control requirement
non_delegableCapability requires the direct (root) principal; delegated agents are blocked

Unmet token requirements (v0.14)​

When a capability declares control_requirements with token-evaluable types (cost_ceiling, stronger_delegation_required), and the caller's token does not satisfy them, the capability appears in restricted with an unmet_token_requirements array listing the unsatisfied requirement types:

{
"restricted": [
{
"capability": "execute_trade",
"reason": "missing control requirements: cost_ceiling",
"reason_type": "unmet_control_requirement",
"grantable_by": "human:[email protected]",
"unmet_token_requirements": ["cost_ceiling"],
"resolution_hint": "request_budget_bound_delegation"
}
]
}

All control requirements are token-evaluable and surfaced in permission discovery.


Invocation​

POST /anip/invoke/{capability}

Authentication: Bearer JWT delegation token.

Request​

{
"parameters": {
"origin": "SEA",
"destination": "SFO"
},
"client_reference_id": "task:abc/step-3",
"task_id": "trip-planning-2026",
"parent_invocation_id": "inv-a1b2c3d4e5f6",
"approval_grant": "grant_456",
"stream": false
}
FieldTypeRequiredDescription
parametersobjectYesCapability input parameters
client_reference_idstringNoCaller-supplied correlation ID (max 256 chars), echoed in response
task_idstringNoTask/workflow identity for grouping related invocations (max 256 chars). If the delegation token has purpose.task_id, must match or be omitted.
parent_invocation_idstringNoReference to the invocation that triggered this one (format: inv-{hex12}). Syntactically validated, not referentially.
upstream_servicestringNoIdentifies the ANIP service that initiated this call as part of a cross-service workflow. Echoed in response and recorded in audit. (v0.18)
approval_grantstringNov0.23 grant ID for continuation after approval_required.
streambooleanNoRequest streaming response (SSE). Default: false

Success response (HTTP 200)​

{
"success": true,
"invocation_id": "inv-7f3a2b4c5d6e",
"client_reference_id": "task:abc/step-3",
"task_id": "trip-planning-2026",
"parent_invocation_id": "inv-a1b2c3d4e5f6",
"result": {
"flights": [
{ "flight_number": "AA100", "price": 420 },
{ "flight_number": "DL310", "price": 280 }
]
},
"cost_actual": {
"currency": "USD",
"amount": 0
}
}

Failure response (HTTP 4xx)​

{
"success": false,
"invocation_id": "inv-8b2f4a7c9d0e",
"task_id": "trip-planning-2026",
"parent_invocation_id": "inv-a1b2c3d4e5f6",
"client_reference_id": "task:abc/step-3",
"failure": {
"type": "budget_exceeded",
"detail": "Requested booking costs $487.00 which exceeds the delegated budget of $200.00",
"retry": false,
"resolution": {
"action": "request_budget_increase",
"requires": "higher_budget_delegation",
"grantable_by": "human:[email protected]",
"estimated_availability": "immediate"
}
}
}

Response fields​

FieldTypeAlways presentDescription
successbooleanYesWhether the invocation succeeded
invocation_idstringYesServer-generated unique ID (inv-{hex12})
client_reference_idstringIf provided in requestEchoed caller correlation ID
task_idstringIf provided or from token purposeTask/workflow identity
parent_invocation_idstringIf provided in requestEchoed parent invocation reference
upstream_servicestringIf provided in requestEchoed upstream service identifier (v0.18)
resultobjectOn successCapability-specific result data
cost_actualobjectIf capability has financial costcurrency and amount
failureobjectOn failureStructured failure (see below)

Budget enforcement (v0.14)​

The service enforces budget constraints from the delegation token's constraints.budget before executing the handler. Budget enforcement is pre-execution and deterministic — there is no post-execution "blessed overspend."

The check amount depends on cost certainty and whether a binding is present:

Cost certaintyBinding present?Check amountFailure on exceed
fixedN/Acost.financial.amountbudget_exceeded
estimatedYes (via requires_binding)Bound pricebudget_exceeded
estimatedNoN/A — reject immediatelybudget_not_enforceable
dynamicN/Acost.financial.upper_boundbudget_exceeded

If the token budget's currency does not match the capability's cost.financial.currency, the service rejects with budget_currency_mismatch.

When a budget was evaluated (success or failure), the response includes a budget_context object:

{
"budget_context": {
"budget_max": 500,
"budget_currency": "USD",
"cost_check_amount": 280,
"cost_certainty": "estimated"
}
}

ANIPFailure schema​

FieldTypeRequiredDescription
typestringYesMachine-readable failure category (e.g., insufficient_scope, budget_exceeded, rate_limited)
detailstringYesHuman-readable explanation
retrybooleanYesWhether retrying the same call might succeed. Default: true
resolutionobjectYesRecovery guidance (see below)
approval_request_idstringFor approval_requiredPending approval request ID
preview_digeststringFor approval_required when a preview existsDigest of the previewed action/result
requested_parameters_digeststringFor approval_requiredDigest of the parameters the grant must bind
grant_policyobjectFor approval_requiredAllowed grant types, expiry, and use-count bounds

Resolution schema​

FieldTypeRequiredDescription
actionstringYesWhat to do (e.g., request_broader_scope, request_budget_increase, wait_and_retry)
recovery_classstringYesCoarse recovery strategy (see vocabulary below). Advisory — does not override retry.
requiresstringNoWhat's needed to resolve
grantable_bystringNoWho can grant what's needed (principal identifier)
estimated_availabilitystringNoHow soon resolution is possible (e.g., immediate, 24h)

recovery_class vocabulary (v0.16)​

recovery_classMeaning
retry_nowRetry immediately — no external change required.
wait_then_retryWait for a time-bounded condition, then retry.
refresh_then_retryRefresh a local artifact (binding, quote, token) and retry.
redelegation_then_retryObtain a new or modified delegation token, then retry.
revalidate_then_retryRe-fetch and validate service-side state before retrying.
terminalNo automated recovery — requires human escalation. Always paired with retry: false.

Failure types — authority (v0.15)​

TypeWhenRetryTypical resolutionrecovery_class
non_delegable_actionCapability requires the root principal; a delegated agent attempted itNoinvoke_as_root_principal — the human must invoke directlyterminal

Canonical resolution actions (v0.16)​

Five new canonical resolution.action values added in v0.16, completing the full action vocabulary:

resolution.actionrecovery_classWhen used
retry_nowretry_nowTransient condition; safe to retry immediately without any change
provide_credentialsretry_nowCredentials are missing or need refreshing but no delegation change is required
wait_and_retrywait_then_retryRate-limit, cooldown, or time-bounded unavailability
revalidate_staterevalidate_then_retryService-side state has changed; re-fetch and verify before retrying
check_manifestrevalidate_then_retryCapability graph or manifest may be stale; re-fetch manifest and retry

Failure types — budget, binding, and control (v0.14)​

TypeWhenRetryTypical resolutionrecovery_class
budget_exceededCost exceeds the delegated budgetNorequest_budget_increase — obtain a higher budget delegationredelegation_then_retry
budget_currency_mismatchBudget and cost currencies differNoobtain_matching_currency — re-delegate with matching currencyredelegation_then_retry
budget_not_enforceableEstimated cost with no binding to pin a priceNoobtain_quote_first — invoke the source capability to get a bound pricerefresh_then_retry
binding_missingRequired binding field absent from parametersNoobtain_binding — invoke the source capability firstrefresh_then_retry
binding_staleBinding exceeded max_ageYesrefresh_binding — re-invoke the source capability for a fresh quoterefresh_then_retry
control_requirement_unsatisfiedA declared control requirement is not metNoDepends on requirement type (e.g., obtain budget delegation for cost_ceiling)redelegation_then_retry

Approval Grants​

POST /anip/approval_grants

Authentication: Bearer token for an approver. The approver must have authority for the capability attached to the loaded approval request, typically through approver:<capability> or a service-defined approver scope.

This endpoint issues a signed approval grant for a pending approval_required continuation. Agents do not mint grants for themselves; approver-side tools, admin UIs, queue workers, or on-call workflows call this endpoint or the equivalent runtime helper.

Request​

{
"approval_request_id": "apr_123",
"grant_type": "one_time",
"session_id": null,
"expires_in_seconds": 900,
"max_uses": 1
}
FieldTypeRequiredDescription
approval_request_idstringYesPending approval request returned by an approval_required failure
grant_typestringYesone_time or session_bound, constrained by the request's grant_policy
session_idstringRequired for session_boundSession binding for session-bound grants
expires_in_secondsnumberNoRequested lifetime, capped by grant_policy
max_usesnumberNoRequested use count, capped by grant_policy

Response​

{
"grant_id": "grant_456",
"approval_request_id": "apr_123",
"capability": "slack.message.prepare",
"parameters_digest": "sha256:...",
"grant_type": "one_time",
"session_id": null,
"expires_at": "2026-03-28T12:15:00Z",
"max_uses": 1,
"signature": "..."
}

The service validates the approval request before signing a grant:

  • Approval request exists.
  • Request is pending and not expired.
  • Approver is authorized for the request's capability.
  • Requested grant type is allowed by grant_policy.
  • Expiry, use count, and session binding are within policy.
  • Request transition and grant insert happen atomically.

Continuation invocations pass the grant ID as approval_grant in /anip/invoke/{capability}. The runtime validates signature, expiry, capability binding, parameter digest, session binding when applicable, and use count before executing the side effect.


Audit​

POST /anip/audit

Authentication: Bearer token. Results are scoped to the root principal of the caller's delegation chain — a principal can only see its own audit trail.

Request (query parameters)​

ParameterTypeDescription
capabilitystringFilter by capability name
sincestringISO 8601 timestamp — entries after this time
invocation_idstringFilter by specific invocation
client_reference_idstringFilter by caller correlation ID
task_idstringFilter by task identity
parent_invocation_idstringFilter by parent invocation
limitintegerMaximum entries to return

Response​

{
"entries": [
{
"invocation_id": "inv-7f3a2b4c5d6e",
"capability": "search_flights",
"actor_key": "agent:booking-bot",
"root_principal": "human:[email protected]",
"event_class": "low_risk_success",
"success": true,
"client_reference_id": "task:abc/step-3",
"task_id": "trip-planning-2026",
"parent_invocation_id": "inv-a1b2c3d4e5f6",
"approval_request_id": null,
"approval_grant_id": null,
"token_id": "tok_root_001",
"timestamp": "2026-03-28T10:30:00Z"
}
]
}

Event classification​

ClassWhen used
low_risk_successRead capability succeeded
high_risk_successWrite/irreversible/financial capability succeeded
low_risk_failureRead capability failed
high_risk_failureWrite/irreversible/financial capability failed

Checkpoints​

GET /anip/checkpoints

No authentication required.

Query parameters​

ParameterTypeDescription
limitintegerMaximum checkpoints to return. Default: 20

Response​

{
"checkpoints": [
{
"checkpoint_id": "cp_a1b2c3",
"sequence": 42,
"merkle_root": "sha256:7d3f8a...",
"entry_count": 150,
"created_at": "2026-03-28T11:00:00Z",
"signature": "eyJhbGciOi..."
}
]
}

Checkpoint Detail​

GET /anip/checkpoints/{id}

Returns a single checkpoint with optional consistency proof fields.

Response​

{
"checkpoint_id": "cp_a1b2c3",
"sequence": 42,
"merkle_root": "sha256:7d3f8a...",
"entry_count": 150,
"created_at": "2026-03-28T11:00:00Z",
"signature": "eyJhbGciOi...",
"tree_size": 150,
"tree_head": "sha256:7d3f8a..."
}

JSON Schema​

Machine-readable JSON Schema definitions are maintained alongside the spec:

The spec (SPEC.md) is authoritative for semantics. The schemas are authoritative for structure.