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.