Skip to main content

ActionContext Reference

Version française : ../../fr/guides/action-context.md

This page describes the ActionContext: the record of one decision on one action of an agent, a tool or a user acting through a delegation. It lists its fields, the layers of the decision, and how to obtain and read one. Who: developers of agents, tools and MCP servers, security officers and auditors.

Contract​

The schema is contracts/v1/action-context.schema.json (Action Context v1). Required fields: schema_version, action_id, action, execution_id, subject, decisions, requested_at. It links an action to the signed ExecutionContext through context_id (the jti of the token).

Fields​

subject: principal_id and on_behalf_of required, plus root_principal_id, agent, subagent, workload, delegation_id. target: kind, ref, operation, destination, classification. decisions: allow required, plus policy_decision_id, openfga, opa, layers. requested describes the intent, observed what was seen to happen; result is allowed, denied, succeeded, failed or pending_approval; audit_event_ids links the action to the audit log.

Decision layers​

The answer of POST /v1/delegations/authorize carries one verdict per layer in layers; allow is true only when every layer allows, and a refused layer gives its reason.

LayerWhat it checks
chainthe delegation chain is valid: not revoked, not expired, depth within bounds
sessionwhen a run_id is given, the run may still act (state and session checks)
userthe original user holds the right
agentthe agent manifest allows the scope
delegationthe delegation grants the scope
resourcethe resource is inside the resource restriction of the delegation
audiencethe audience is allowed by the delegation
classificationthe data classification does not exceed data_classification_max
relationshipwith resource and relation, OpenFGA confirms both the original user and the caller hold the relation (fail closed when OpenFGA does not answer)
policythe OPA or builtin policy allows the action

Produce an ActionContext​

POST /v1/delegations/authorize (services/control-plane/src/eai/domains/delegation/runtime.py, function authorize) computes the effective right user AND agent AND delegation AND resource AND relationship AND policy, records the decision and the audit, then returns the ActionContext; allow is true only when every layer allows.

await client.delegations.authorize({ action: "crm.read", resource: "crm:contact:42" });

Procedures​

  1. Grant a delegation. Without a delegation the platform cannot know on whose behalf the action runs, so the decision is refused.

    Screen: Security and governance > Delegations > New delegation. API: POST /v1/delegations with delegate (required), plus scopes, resources, audience, data_classification_max, ttl_seconds or expires_at, max_depth, redelegation_allowed, purpose.

    Expected result: a delegation identifier, readable with GET /v1/delegations/{delegation_id}.

    If it fails: 403 delegation_scope_exceeds means you delegate a scope you do not hold yourself.

  2. Ask for a decision before acting. A tool or an MCP server calls it before every sensitive action, with the run or the delegation it acts under.

    API: POST /v1/delegations/authorize with action (for example crm.read), and run_id or delegation_id, plus scope, resource (<type>:<id>), relation, audience, data_classification.

    Expected result: an ActionContext with action_id, allow, layers, subject, delegation, decisions and decided_at.

    If it fails: 403 delegation_required means neither a run with a delegation nor a delegation_id was given; 404 delegation_not_found means an unknown delegation; 422 validation_error means an action or resource that does not follow the expected form.

  3. Act only when allow is true. A refused layer is a refusal, never a warning: stop the action and report the reason of the refused layer.

    Expected result: the action runs, and the decision is in the audit log as authz.authorize.

    If it fails: when allow is false, read layers to find which layer refused.

  4. Trace the action in the audit. The audit event authz.authorize records the action, the scope, the resource, the layers and the run, refusals included.

    Expected result: GET /v1/audit/events lists the event of the decision.

    If it fails: 403 forbidden means your role cannot read the audit log.

  5. Revoke when needed. Revoking a delegation stops every later decision made under it.

    API: POST /v1/delegations/{delegation_id}/revoke, or POST /v1/delegations/{delegation_id}/restrict to narrow it.

    Expected result: the next decision refuses the chain layer.

    If it fails: 404 delegation_not_found.

Troubleshooting​

StatusCodeCauseFix
403delegation_requiredno run with a delegation and no delegation_idgrant a delegation, pass its identifier or the run
404delegation_not_foundunknown delegationcheck the identifier and the tenant
403delegation_scope_exceedsdelegating a scope you do not holddelegate a subset of your scopes
403delegation_expiredthe delegation is overgrant a new delegation
422validation_erroraction not of the form domain.verb, or resource not of the form type:idfix the request body
200allow: falseone layer refusedread the reason of the refused layer

Next steps​