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.
| Layer | What it checks |
|---|---|
chain | the delegation chain is valid: not revoked, not expired, depth within bounds |
session | when a run_id is given, the run may still act (state and session checks) |
user | the original user holds the right |
agent | the agent manifest allows the scope |
delegation | the delegation grants the scope |
resource | the resource is inside the resource restriction of the delegation |
audience | the audience is allowed by the delegation |
classification | the data classification does not exceed data_classification_max |
relationship | with resource and relation, OpenFGA confirms both the original user and the caller hold the relation (fail closed when OpenFGA does not answer) |
policy | the 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
-
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), plusscopes,resources,audience,data_classification_max,ttl_secondsorexpires_at,max_depth,redelegation_allowed,purpose.Expected result: a delegation identifier, readable with GET /v1/delegations/{delegation_id}.
If it fails: 403
delegation_scope_exceedsmeans you delegate a scope you do not hold yourself. -
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 examplecrm.read), andrun_idordelegation_id, plusscope,resource(<type>:<id>),relation,audience,data_classification.Expected result: an ActionContext with
action_id,allow,layers,subject,delegation,decisionsanddecided_at.If it fails: 403
delegation_requiredmeans neither a run with a delegation nor adelegation_idwas given; 404delegation_not_foundmeans an unknown delegation; 422validation_errormeans anactionorresourcethat does not follow the expected form. -
Act only when
allowis true. A refused layer is a refusal, never a warning: stop the action and report thereasonof the refused layer.Expected result: the action runs, and the decision is in the audit log as
authz.authorize.If it fails: when
allowis false, readlayersto find which layer refused. -
Trace the action in the audit. The audit event
authz.authorizerecords 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
forbiddenmeans your role cannot read the audit log. -
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
chainlayer.If it fails: 404
delegation_not_found.
Troubleshooting
| Status | Code | Cause | Fix |
|---|---|---|---|
| 403 | delegation_required | no run with a delegation and no delegation_id | grant a delegation, pass its identifier or the run |
| 404 | delegation_not_found | unknown delegation | check the identifier and the tenant |
| 403 | delegation_scope_exceeds | delegating a scope you do not hold | delegate a subset of your scopes |
| 403 | delegation_expired | the delegation is over | grant a new delegation |
| 422 | validation_error | action not of the form domain.verb, or resource not of the form type:id | fix the request body |
| 200 | allow: false | one layer refused | read the reason of the refused layer |
Next steps
- ExecutionContext Reference
- Policy Development Guide: write the policy layer.
- API Reference