1
Resources
The allow list: tools, models and data, named scope:name, with wildcards.
"resources": [ "tool:emp_records/read", "llm:openai/*" ]Learn more
MAPL: MACAW Agentic Policy Language · Open spec
A policy language and composition algebra for agentic actions. Every action is verified against policy before it runs, and provably scoped to what the policy allows.
“Alice can read employee records1, up to 100 at a time2. Any update needs a manager’s approval3. Deletes aren’t allowed4.”
{ "policy_id": "user:alice", "resources": [ "tool:emp_records/read",1 "tool:emp_records/update" ], "denied_resources": ["tool:emp_records/delete"],4 "constraints": { "parameters": { "tool:emp_records/read": { "limit": { "max": 100 } }2 }, "tool:emp_records/update": { "attestations": ["manager_approval"]3 }, "attestations": { "manager_approval": { "approval_criteria": "role:manager" }3 } } }
Policy languages were built for a pre-agentic era: known callers making known requests. Agents act on behalf of people, delegate to other agents, chain calls across services owned by different teams, decide what to do at runtime, and occasionally lie.
Four parts, no code. Policies are validated before they deploy, and every decision is deterministic and reproducible.
Policies name scopes, not people. Your IdP binds the caller when the call arrives, so a role change needs no policy change.
Caller, service and data owners each write their own policy. They combine by intersection: authority only narrows, and a denial is final.
Decisions can depend on approvals, passkey logins and completed steps. A call can wait for an approver, and the agent can’t approve itself.
Every action is provably scoped to what its policies allow. The proofs are mechanized in Lean. The formal foundations, in the guide
Every MAPL policy, at every level, has the same structure.
1
The allow list: tools, models and data, named scope:name, with wildcards.
"resources": [ "tool:emp_records/read", "llm:openai/*" ]Learn more
2
The deny list. A denial at any level is final.
"denied_resources": [ "tool:emp_records/delete", "secrets:**" ]Learn more
3
Limits on a call’s arguments, and patterns its arguments may not contain.
"tool:emp_records/read": {
"limit": { "max": 100 }
}Learn more4
Attestations a call needs: a manager’s approval, a passkey login, a completed step.
"attestations": [ "manager_approval", "phishing_resistant" ]Learn more
Minimal, and expressive. Allow and deny lists combine into any boolean rule over operations; constraints can test any decidable condition on arguments; approvals put steps in order. Your first policy
From the guide’s best practices.
"attestations": [
"lead_ok::{params.amount > 1000}",
"manager_ok::{params.amount > 10000}"
]Injection defenseArguments that must never appear."denied_parameters": {
"tool:shell/*": {
"command": ["*sudo*", "*rm -*"]
}
}Data with its own policyA table binds whoever touches it."policy_id": "data:employee_comp", "resources": ["tool:reporting/query"], "denied_resources": ["tool:*/export"]An app acting for a personThe person and the service must both allow.
maya → app:assistant
→ app:orchestrator
→ tool:banking/transferEmergency access, no overridesA time-bounded policy instead."policy_id": "team:incident-response",
"validity": {
"not_after": "2025-01-17T17:00:00Z"
}Only a person can approveApprovals that need a passkey login."attestations": [ "manager_approval", "phishing_resistant" ]
Every party in a call has a policy: the person, the agent acting for them, and the service it calls. MAPL intersects them into one effective policy.
Click any policy to see it in MAPL. Each value in the effective policy is the tightest any party set.
model claude-opusrefused: Alice’s policy allows only Sonnetmax_tokens 4000refused: Claude Desktop allows at most 1,000query(rows=4000)refused: the database allows at most 1,000claude-sonnet, 1,000 tokens, 1,000 rowsallowedResources ∩Denied ∪Constraints tightest winsApprovals ∪The intersection rules
company:macawthe rootmax_tokens ≤ 4,000bu:financeextends company:macawmax_tokens ≤ 1,000user:aliceextends bu:financemax_tokens ≤ 8,000Alice’s policy asks for 8,000 tokens. Her effective limit is still 1,000. There are no overrides.
Inheritance in the guideSome decisions need more than the request: a person’s say-so, a step that already happened, a scope the caller holds right now. MAPL calls these attestations: facts a call can require, proved and signed by someone other than the agent.
One requirement, three kinds of proof
"tool:payments/send": { "attestations": ["payments_scope",from Alice’s token"kyc_checked",recorded by a tool"manager_approval::{params.amount > 25000}"a person, only over 25,000 ] }
proved by a person or agent with authority
"approval_criteria": "role:manager"The call waits. Only approvers who match the criteria can approve it; once approved it runs, and the approval is spent.
proved by the requester’s token
"claim": { "scopes": "Banking.Write" }Holds only while the token carries the scope. Nothing to approve or store: it ends when the token does.
proved by a tool, after it runs
"internal": trueA tool records a fact: identity verified, data anonymized, a classifier’s verdict. Later calls can require it.
proved by the login
"phishing_resistant"Minted only from a passkey or hardware-key login. An agent holding a password can’t have it.
How an approval is routed
payments.send(amount = 30,000)pending · for alice · approval_criteria: role:managerIdP token roles: managersees it, approvesCarolIdP token roles: analystdoesn’t see itThe agentthe requestercan never approveapproval signed by Bob · spentA requirement can depend on the call, like the amount above, and a condition that can’t be evaluated requires the proof. Approvals can be single-use or expire; a denial or a timeout fails the call; and when two policies name approvers, the approver must satisfy both. Attestations in the guide
Every call passes eight stages. Three are hooks for your own verification logic, in Python.
Extractoryour code
Your extractor reads a value in the call, such as a SQL string or a JSON body, and returns facts policy can test. It decides nothing on its own.
extract(value, **config) -> dictLibrary: secrets. Or write your own.
Hooks make domain-specific verification easy to add.
llm:openai/chat.completions“Summarize this config: AWS_KEY=AKIAIOSFODNN7EXAMPLE …”
Alice’s policies, the agent’s and the model service’s combine
secret_scanner reads the prompt and finds an AWS key
RefusedThe prompt never reached the model.
Keep OPA, Cedar and IAM for the access they already control. MAPL adds what agents need on top: authority that follows the person through every agent and service, approvals, and checks on what each call actually does.
| Capability | Detail | MAPL | Cedar | OPA/Rego | AWS IAM | OpenFGA | NeMo Guardrails |
|---|---|---|---|---|---|---|---|
| Composition | Authority only narrows as policies compose, proved | ●One intersection over every policy: authors, org hierarchy, service hops. Lean-proved that no author can loosen another’s rule. | ◐Any author’s permit adds authority. Source | ◐Hand-coded per policy. Source | ◐Intersects account layers inside AWS only; no hops, no proof. Source | ○Grants are a union. Source | ○No composition algebra. Source |
| Explicit deny cannot be overridden | ●Any policy’s deny is the result’s deny. | ●Forbid overrides permit. Source | ◐Depends on how the rules are written. Source | ●An explicit deny overrides any allow. Source | ◐Exclusion only. Source | ◐In code, not a law of the language. Source | |
| Caller and service policies both constrain access | ●The caller’s policies and the receiving service’s policy are evaluated separately, then intersected. | ◐One policy set per request; a service’s own rules must be written into it. Source | ◐Possible if each service writes and queries its own policy. Source | ◐Identity- and resource-based policies both apply, inside AWS. Source | ◐Relations on both sides can be modeled by hand. Source | ○Not supported. Source | |
| Policies attached to data and objects | ●An object policy binds whoever consumes the data, whatever their role. | ●Resource scope and entity hierarchy. Source | ◐Custom. Source | ●Resource-based policies. Source | ●Object relations are its core. Source | ○Not supported. Source | |
| Restrictions follow derived data through references | ●Derived objects carry their source’s policy through references. | ○No notion of derived data. Source | ◐Can be modeled with custom data. Source | ○Not supported. Source | ◐Can be modeled with relations between objects. Source | ○Not supported. Source | |
| Identity and delegation | Identity bound from IdP claims at call time | ●Filled from validated claims; policies never name principals. | ◐Through AWS Verified Permissions. Source | ◐Hand-coded. Source | ◐AWS principals. Source | ◐Tuples written in advance. Source | ○Not supported. Source |
| Authority narrows at every agent hop | ●Person → agent → service → sub-agent, one layer per hop. | ○One request, one principal. Source | ◐Custom. Source | ◐Role chaining inside AWS. Source | ◐Usersets can model it; grants union. Source | ○Not supported. Source | |
| Agent actions | Native model, tool and MCP resources | ●Tool calls, MCP, model calls and effects such as shell, files and network are first-class resources. | ◐Tool name and arguments through AgentCore; no effects, approvals or results. Source | ◐General purpose. Source | ○AWS APIs only. Source | ○Not supported. Source | ◐Centered on the dialog. Source |
| Model, parameter and token constraints | ●Allowed models, max_tokens and any parameter limit, at every policy level. | ◐Conditions on attributes the application passes in. Source | ◐Expressible in Rego over the request input. Source | ○AWS APIs only. Source | ○Models relationships, not call parameters. Source | ◐Model settings in configuration, not policy. Source | |
| Approvals and evidence | Named approvers, conditions, pending decisions, expiry | ●A human or agent approver named by policy, required on stated conditions, with timeouts and expiry. | ○Allow or deny only. Source | ◐Built by the application. Source | ○Allow or deny only. Source | ○True or false only. Source | ◐In-chat confirmation, with no approver identity. Source |
| Signed, single-use evidence the agent can’t forge | ●Approvals, claims and tool-recorded facts, signed by someone other than the agent; one-time evidence is spent by the call it allows. | ○Context comes unsigned from the application. Source | ○Can verify a JWT; nothing is single-use. Source | ○Fixed condition keys, such as MFA present; nothing is spent. Source | ○Contextual tuples are unsigned. Source | ○Not supported. Source | |
| Extensibility and assurance | Custom logic that can only tighten a decision | ●Extractors, input verifiers and result processors. Theorem: a decision is at most what the policies allow. | ○No custom functions. Source | ◐Arbitrary, with no guarantee for combined rules. Source | ○Not supported. Source | ◐CEL conditions, with no guarantee. Source | ◐Python rails; any rail can override another. Source |
| Rich logic over structured request data | ●Conditions over parameters, and extractors that read SQL, JSON and other structured payloads. | ◐Fixed operators over typed attributes. Source | ●A general-purpose language over JSON input. Source | ○Fixed condition operators. Source | ◐CEL conditions over context. Source | ◐Arbitrary Python, outside any policy model. Source | |
| Mechanized proofs (Lean) | ●The language’s laws and the pipeline theorem, mechanized in Lean. | ●Semantics and validator formalized in Lean. Source | ○Not supported. Source | ◐Automated reasoning over policies, not a mechanized language. Source | ○Not supported. Source | ○Not supported. Source | |
| Validated before deployment; effective policy explained | ●Policies are validated before they deploy; the console shows and explains the effective policy. | ●Validator and SMT-based analysis. Source | ◐Type checking and tests. Source | ●Policy validation and Access Analyzer. Source | ◐Model validation and tests. Source | ○Not supported. Source |
● built in · ◐ partial, or with custom code · ○ not supported. Hover or tap a mark for the reason and the source. From each project’s public documentation, November 2026.
Already on Cedar or OPA? Your policies port to MAPL.
Install the MACAW plugin for Claude Code or Codex and use the /mapl skill. Say what your agents may do; it writes the policy.
You say
“Alice can read employee records, up to 100 at a time. Any update needs a manager’s approval. Deletes aren’t allowed.”
Install
/plugin marketplace add macawsecurity/macaw-plugin /plugin install macaw-cc@macaw
Tested with Claude (Sonnet, Haiku, Opus), Codex (Terra, Luna, Sol) and Qwen3 8B.
Policy Assistant · in the console
Open a policy and ask. You get what it allows, what it blocks and its limits, in plain English.
The consoleτ²-bench gives an airline agent and a retail agent their business rules in plain prose. We wrote them in MAPL and ran the benchmark’s calls through MACAW.
The full language: policies, inheritance, approvals, functions, and the formal foundations.