Capability Authorization Gate
Overview
Self-aware agents must understand their own capabilities and limitations. The
Capability Model Pattern (Ch3, Example 3-5) makes operational parameters
explicit, queryable structure: each capability declares what it requires, an
authorization-level, and an optional quantitative limit. During planning the
agent determines whether it has the access, authorization, and headroom to
fulfill a request before attempting it — and routes/escalates when it does
not.
The chapter's worked example: a Customer-Support-Agent can
Answer-Product-Question (Public, needs only Product-Knowledge) but
Process-Refund requires Supervisor authorization, Financial-System-Access, and
caps at 500 USD. A 600-USD refund must be recognized as exceeding authority and
routed appropriately — "creating more reliable, trustworthy automation with
appropriate human oversight" — instead of attempting a prohibited action.
The gate returns three decisions:
- allow — capability declared, granted auth level >= required, all required
resources present, amount (if any) within limit.
- escalate — the agent itself cannot, but a higher authority could:
authorization too low, a required grant missing, or the amount over the limit.
This is the "route appropriately" path.
- deny — the capability is undeclared. The agent has no such ability at all.
The DevOps manifestation (anchored in fictional AWS account 123456789012):
capabilities like read_metrics (Public), query_logs (User),
restart_instance (Supervisor + ec2:write), and scale_autoscaling_group
(Supervisor, limit 10 instances) become the queryable authority model that gates
tool orchestration in Ch6. A User-level latency investigator can read metrics
and logs but escalates a restart or an over-limit scale.
When to Use
- An agent must decide "can I do this?" before invoking a tool or taking an action
- Modeling agent operational boundaries (authority, required grants, limits)
- Building the queryable authority layer that gates tool orchestration (Ch6)
- Implementing graceful escalation/routing instead of attempting prohibited actions
Phrases: "capability model", "can the agent do X", "authorization level",
"operational limit", "escalate", "refund limit", "agent authority",
"queryable authority", "tool authorization gate".
When NOT to Use
- Human RBAC/IAM enforcement. This is the agent's planning-time self-check,
not your platform's identity policy. Real credential checks still happen at the
API boundary.
- Validating the capability NODE shape. Use
schema-pattern-selector
(capability_model validation) to confirm a capability declaration is
well-formed; this skill consumes well-formed declarations and decides.
- As the only security control. The gate prevents the agent from ATTEMPTING
an over-authority action; it does not replace server-side authorization. Defense
in depth: gate at planning AND enforce at the boundary.
Process
| Step |
Input |
Action |
Output |
Verification |
| 1 |
agent spec JSON (id, granted_level, granted_resources, capabilities[]) |
lib.agent_from_spec(spec) |
Agent with Capability map |
unknown auth level raises at construction |
| 2 |
agent + capability type + optional amount |
lib.authorize(agent, cap, amount) |
{decision, capability, reasons, required_level, granted_level} |
allow only if level met, resources present, within limit |
| 3 |
over-limit amount |
lib.authorize(agent, "Process-Refund", 600) |
decision == "escalate", reason cites limit |
$600 vs $500 limit escalates, never allows |
| 4 |
undeclared capability |
lib.authorize(agent, "X") |
decision == "deny" |
deny is distinct from escalate |
| 5 |
agent + capability + amount |
lib.can_do(agent, cap, amount) |
bool |
True only when decision is allow |
Rationalizations
| Agent rationalization |
Documented rebuttal |
| "I'll just try the refund and let it fail downstream if it's too big." |
Attempting a prohibited action is the failure mode the pattern exists to prevent. The chapter: recognize $600 exceeds the $500 limit and route it — do not attempt. Trying-and-failing leaks intent, may partially execute, and erodes the trustworthy-automation guarantee. |
| "Escalate and deny are the same — both mean 'no'." |
They are different and the difference is actionable. Deny = the agent has no such capability at all (dead end). Escalate = a higher authority CAN do it (route to a supervisor / human). Collapsing them loses the routing decision the pattern enables. |
| "The agent is Supervisor now, so any refund amount is fine." |
Authorization level and quantitative limit are independent checks. Even a Supervisor escalates a $600 refund if the capability's limit is $500. Raising the actor's level does not raise the capability's limit. |
| "Required resources are implicit — skip the grants check." |
The chapter ties capabilities to concrete requirements (Financial-System-Access; in DevOps, ec2:write). A capability the agent is authorized for but lacks the resource grant for must still escalate. Skipping the grant check produces a confident "allow" the downstream API will reject. |
| "This duplicates IAM, just rely on AWS IAM." |
This is the planning-time self-check that lets the agent decide BEFORE making the call (and route gracefully). IAM enforces at the boundary. They compose — defense in depth — they do not substitute. |
Red Flags
- Gate returns
allow for an action the downstream API then rejects. The
agent's granted_resources/level are out of sync with reality — refresh the
capability model from the actual authority source.
- Everything escalates. The agent's granted_level/resources are
under-provisioned, or the capability declarations over-require. Re-check the
spec; constant escalation defeats automation.
- A capability has a limit but callers never pass an amount. The gate warns;
an unchecked limit is a silent over-authority risk. Always pass the amount for
limited capabilities.
deny for a capability the agent clearly should have. The capability is
missing from the declaration — add it, do not work around the gate.
Non-Negotiable Verification
- Run the benchmark battery.
python cli.py benchmark must report 10/10:
- Public capability with resources -> allow
- $600 refund over $500 limit -> escalate (reason cites the limit)
- undeclared capability -> deny (distinct from escalate)
- Supervisor + resources allows $400 but still escalates $600
- DevOps: User escalates restart_instance and over-limit scale, allows read_metrics
- unknown authorization level raises at construction
- Run the scenarios.
python cli.py scenario support-refund and
python cli.py scenario devops-latency print allow/escalate/deny across the
chapter's cases (DevOps anchored in AWS account 123456789012).
- Verify CLI help.
python cli.py --help exits 0 and prints this SKILL.md
description (so any harness can discover the skill from --help).
Security Posture
- Prompt injection. The agent spec JSON is untrusted configuration: an
adversarial spec that inflates granted_level, pads granted_resources, or
raises a capability limit turns the gate into a rubber stamp. The gate never
executes spec content - load specs only from the real authority source, not
from agent- or user-supplied text.
- Data exfiltration. No network calls, no file writes. Capability
declarations may reveal internal authority topology; decisions go to stdout
and the caller owns downstream piping.
- Privilege escalation. The gate is itself an anti-escalation control, but
it is planning-time and advisory: an "allow" grants no credential, and a
bypassed gate must still hit server-side IAM at the API boundary. Defense in
depth - never let this replace boundary enforcement.
Source Attribution
Distilled from Agentic GraphRAG (O'Reilly, by Anthony Alcaraz and Sam Julien) Ch3 — Knowledge
Representation, section "Capability Model Pattern" (Example 3-5: the
Customer-Support-Agent with a $500 refund limit that escalates a $600 request).
The DevOps capability-as-queryable-authority manifestation is from "Applying
schema patterns to infrastructure", feeding the tool-orchestration authority
model in Ch6.
1---2name: capability-authorization-gate3description: Runtime authorization gate built on the Ch3 Capability Model Pattern — a self-aware agent represents its own capabilities, required resources/grants, authorization level, and quantitative limits as queryable structure, then checks at PLANNING time whether it may perform an action BEFORE attempting it. Returns allow, escalate (the agent itself cannot but a higher authority could — route appropriately), or deny (the capability is undeclared). The canonical case: a support agent with a $500 refund limit escalates a $600 request. Use when an agent must decide can-I-do-this before acting, when modeling agent operational boundaries, or when building the queryable authority layer that gates tool use (Ch6). NOT for human RBAC/IAM policy enforcement (use the platform's IAM), NOT for validating that a capability NODE is well-formed (use schema-pattern-selector's capability_model validation), NOT a replacement for actual credential checks at the API boundary (this is the planning-time gate).4---56# Capability Authorization Gate78## Overview910Self-aware agents must understand their own capabilities and limitations. The11Capability Model Pattern (Ch3, Example 3-5) makes operational parameters12explicit, queryable structure: each capability declares what it `requires`, an13`authorization-level`, and an optional quantitative `limit`. During planning the14agent determines whether it has the access, authorization, and headroom to15fulfill a request **before attempting it** — and routes/escalates when it does16not.1718The chapter's worked example: a `Customer-Support-Agent` can19`Answer-Product-Question` (Public, needs only Product-Knowledge) but20`Process-Refund` requires Supervisor authorization, Financial-System-Access, and21caps at 500 USD. A 600-USD refund must be recognized as exceeding authority and22routed appropriately — "creating more reliable, trustworthy automation with23appropriate human oversight" — instead of attempting a prohibited action.2425The gate returns three decisions:2627- **allow** — capability declared, granted auth level >= required, all required28 resources present, amount (if any) within limit.29- **escalate** — the agent itself cannot, but a higher authority could:30 authorization too low, a required grant missing, or the amount over the limit.31 This is the "route appropriately" path.32- **deny** — the capability is undeclared. The agent has no such ability at all.3334The DevOps manifestation (anchored in fictional AWS account `123456789012`):35capabilities like `read_metrics` (Public), `query_logs` (User),36`restart_instance` (Supervisor + `ec2:write`), and `scale_autoscaling_group`37(Supervisor, limit 10 instances) become the queryable authority model that gates38tool orchestration in Ch6. A User-level latency investigator can read metrics39and logs but escalates a restart or an over-limit scale.4041## When to Use4243- An agent must decide "can I do this?" before invoking a tool or taking an action44- Modeling agent operational boundaries (authority, required grants, limits)45- Building the queryable authority layer that gates tool orchestration (Ch6)46- Implementing graceful escalation/routing instead of attempting prohibited actions4748Phrases: "capability model", "can the agent do X", "authorization level",49"operational limit", "escalate", "refund limit", "agent authority",50"queryable authority", "tool authorization gate".5152## When NOT to Use5354- **Human RBAC/IAM enforcement.** This is the agent's planning-time self-check,55 not your platform's identity policy. Real credential checks still happen at the56 API boundary.57- **Validating the capability NODE shape.** Use `schema-pattern-selector`58 (`capability_model` validation) to confirm a capability declaration is59 well-formed; this skill consumes well-formed declarations and decides.60- **As the only security control.** The gate prevents the agent from ATTEMPTING61 an over-authority action; it does not replace server-side authorization. Defense62 in depth: gate at planning AND enforce at the boundary.6364## Process6566| Step | Input | Action | Output | Verification |67|------|-------|--------|--------|--------------|68| 1 | agent spec JSON (id, granted_level, granted_resources, capabilities[]) | `lib.agent_from_spec(spec)` | `Agent` with `Capability` map | unknown auth level raises at construction |69| 2 | agent + capability type + optional amount | `lib.authorize(agent, cap, amount)` | `{decision, capability, reasons, required_level, granted_level}` | allow only if level met, resources present, within limit |70| 3 | over-limit amount | `lib.authorize(agent, "Process-Refund", 600)` | `decision == "escalate"`, reason cites limit | $600 vs $500 limit escalates, never allows |71| 4 | undeclared capability | `lib.authorize(agent, "X")` | `decision == "deny"` | deny is distinct from escalate |72| 5 | agent + capability + amount | `lib.can_do(agent, cap, amount)` | bool | True only when decision is allow |7374## Rationalizations7576| Agent rationalization | Documented rebuttal |77|------------------------|--------------------|78| "I'll just try the refund and let it fail downstream if it's too big." | Attempting a prohibited action is the failure mode the pattern exists to prevent. The chapter: recognize $600 exceeds the $500 limit and route it — do not attempt. Trying-and-failing leaks intent, may partially execute, and erodes the trustworthy-automation guarantee. |79| "Escalate and deny are the same — both mean 'no'." | They are different and the difference is actionable. Deny = the agent has no such capability at all (dead end). Escalate = a higher authority CAN do it (route to a supervisor / human). Collapsing them loses the routing decision the pattern enables. |80| "The agent is Supervisor now, so any refund amount is fine." | Authorization level and quantitative limit are independent checks. Even a Supervisor escalates a $600 refund if the capability's limit is $500. Raising the actor's level does not raise the capability's limit. |81| "Required resources are implicit — skip the grants check." | The chapter ties capabilities to concrete requirements (Financial-System-Access; in DevOps, `ec2:write`). A capability the agent is authorized for but lacks the resource grant for must still escalate. Skipping the grant check produces a confident "allow" the downstream API will reject. |82| "This duplicates IAM, just rely on AWS IAM." | This is the planning-time self-check that lets the agent decide BEFORE making the call (and route gracefully). IAM enforces at the boundary. They compose — defense in depth — they do not substitute. |8384## Red Flags8586- **Gate returns `allow` for an action the downstream API then rejects.** The87 agent's granted_resources/level are out of sync with reality — refresh the88 capability model from the actual authority source.89- **Everything escalates.** The agent's granted_level/resources are90 under-provisioned, or the capability declarations over-require. Re-check the91 spec; constant escalation defeats automation.92- **A capability has a limit but callers never pass an amount.** The gate warns;93 an unchecked limit is a silent over-authority risk. Always pass the amount for94 limited capabilities.95- **`deny` for a capability the agent clearly should have.** The capability is96 missing from the declaration — add it, do not work around the gate.9798## Non-Negotiable Verification991001. **Run the benchmark battery.** `python cli.py benchmark` must report 10/10:101 - Public capability with resources -> allow102 - $600 refund over $500 limit -> escalate (reason cites the limit)103 - undeclared capability -> deny (distinct from escalate)104 - Supervisor + resources allows $400 but still escalates $600105 - DevOps: User escalates restart_instance and over-limit scale, allows read_metrics106 - unknown authorization level raises at construction1072. **Run the scenarios.** `python cli.py scenario support-refund` and108 `python cli.py scenario devops-latency` print allow/escalate/deny across the109 chapter's cases (DevOps anchored in AWS account 123456789012).1103. **Verify CLI help.** `python cli.py --help` exits 0 and prints this SKILL.md111 description (so any harness can discover the skill from --help).112113## Security Posture114115- **Prompt injection.** The agent spec JSON is untrusted configuration: an116 adversarial spec that inflates granted_level, pads granted_resources, or117 raises a capability limit turns the gate into a rubber stamp. The gate never118 executes spec content - load specs only from the real authority source, not119 from agent- or user-supplied text.120- **Data exfiltration.** No network calls, no file writes. Capability121 declarations may reveal internal authority topology; decisions go to stdout122 and the caller owns downstream piping.123- **Privilege escalation.** The gate is itself an anti-escalation control, but124 it is planning-time and advisory: an "allow" grants no credential, and a125 bypassed gate must still hit server-side IAM at the API boundary. Defense in126 depth - never let this replace boundary enforcement.127128## Source Attribution129130Distilled from *Agentic GraphRAG* (O'Reilly, by Anthony Alcaraz and Sam Julien) Ch3 — Knowledge131Representation, section "Capability Model Pattern" (Example 3-5: the132Customer-Support-Agent with a $500 refund limit that escalates a $600 request).133The DevOps capability-as-queryable-authority manifestation is from "Applying134schema patterns to infrastructure", feeding the tool-orchestration authority135model in Ch6.