AID-M-009.001: Operating Scope & Functional Autonomy Profiles

Version 1.20261015 · Actionable sub-technique

Define what kind of autonomy an agent is approved to have before deployment. This sub-technique records the operating scope and the per-function autonomy profile across Observe, Analyze, Decide, Execute, Delegate, and Persist.
Key question: what may this agent do on its own? This gives downstream policy, monitoring, and approvals a clear contract to enforce.
Example: a customer-support agent may Observe and Analyze autonomously, but Execute refunds and Persist long-term customer memory still remain supervised.

Pillars: app, infra

Lifecycle: scoping, operation

Scope boundary

Owns the approved operating scope and per-function autonomy profile across Observe, Analyze, Decide, Execute, Delegate, and Persist. It answers which functions the agent may perform independently or only under supervision.

AID-M-009.002: AID-M-009.001 classifies the degree of autonomy allowed for each functional stage; AID-M-009.002 defines hard limits on concrete tools, data, environments, effects, budgets, and delegation depth. An agent may be autonomous for a function yet still be prohibited from particular actions inside that function.

AID-M-009.006: AID-M-009.001 defines the functional autonomy profile; AID-M-009.006 maps the resulting capability and blast-radius tier to mandatory defensive control evidence. Autonomy classification is an input to assurance requirements, not proof that those controls are deployed and effective.

Implementation guidance

AID-M-009.001-G001

Classify each agent deployment by operating scope and define a per-function autonomy profile.
Concept:

Start governance by classifying what kind of agent you are deploying and how much autonomy it gets for each function type. This is a design-time control owned by the product, security, and platform teams before runtime policy is written.

Step 1: Assign an operating scope

Classify each deployment as No Agency, Prescribed Agency, Supervised Agency, or Full Agency. Scope selection determines the default oversight posture and whether autonomous execution is allowed at all.

Step 2: Define per-function autonomy
# File: profiles/tier2_support_agent.yaml
agent:
  id: support-agent-prod-001
  operating_scope: prescribed
  autonomy_profile:
    observe: autonomous
    analyze: autonomous
    decide: supervised
    execute: supervised
    delegate: forbidden
    persist: supervised

Action: Store this profile in version control and require design review approval whenever an agent's operating scope or function-level autonomy changes.

AID-M-009.001-G002

Validate autonomy profiles in CI and emit an approval evidence record before deployment.
Concept

Validate the complete autonomy profile against a signed governance policy and a signed approval receipt. The validator must reject duplicate keys, unknown fields or functions, an unsupported operating scope, and an approval that is expired or bound to different profile bytes.

Validate the closed schemas and approval binding

The approval service is an external dependency: it authenticates reviewers and authorizes approver IDs. Its adapter emits a signed receipt containing the exact profile and policy digests; this validator does not accept approver IDs from the profile itself.

# File: governance/validate_autonomy_profile.py
from __future__ import annotations

import hashlib
import json
import os
from datetime import datetime, timezone
from pathlib import Path

import yaml


class StrictSafeLoader(yaml.SafeLoader):
    pass


def unique_mapping(loader, node, deep=False):
    loader.flatten_mapping(node)
    result = {}
    for key_node, value_node in node.value:
        key = loader.construct_object(key_node, deep=deep)
        if key in result:
            raise ValueError(f"duplicate YAML key: {key}")
        result[key] = loader.construct_object(value_node, deep=deep)
    return result


StrictSafeLoader.add_constructor(
    yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
    unique_mapping,
)


def unique_object(pairs):
    result = {}
    for key, value in pairs:
        if key in result:
            raise ValueError(f"duplicate JSON key: {key}")
        result[key] = value
    return result


def regular_bytes(path: Path) -> bytes:
    if path.is_symlink() or not path.is_file():
        raise ValueError(f"governance input is not a regular file: {path}")
    raw = path.read_bytes()
    if not raw:
        raise ValueError(f"governance input is empty: {path}")
    return raw


def sha256(raw: bytes) -> str:
    return hashlib.sha256(raw).hexdigest()


profile_path = Path(os.environ["AUTONOMY_PROFILE"])
policy_path = Path(os.environ["AUTONOMY_PROFILE_POLICY"])
approval_path = Path(os.environ["AUTONOMY_PROFILE_APPROVAL"])
profile_raw = regular_bytes(profile_path)
policy_raw = regular_bytes(policy_path)
approval_raw = regular_bytes(approval_path)
profile_doc = yaml.load(profile_raw.decode("utf-8", errors="strict"), Loader=StrictSafeLoader)
policy = json.loads(policy_raw.decode("utf-8", errors="strict"), object_pairs_hook=unique_object)
approval = json.loads(approval_raw.decode("utf-8", errors="strict"), object_pairs_hook=unique_object)

if not isinstance(profile_doc, dict) or set(profile_doc) != {"agent"}:
    raise ValueError("profile document schema differs")
agent = profile_doc["agent"]
if not isinstance(agent, dict) or set(agent) != {"id", "operating_scope", "autonomy_profile"}:
    raise ValueError("agent profile fields differ")
if not isinstance(agent["id"], str) or not agent["id"]:
    raise ValueError("agent ID is invalid")

policy_keys = {
    "schema_version", "policy_version", "allowed_operating_scopes",
    "required_functions", "allowed_modes",
}
if not isinstance(policy, dict) or set(policy) != policy_keys:
    raise ValueError("autonomy policy fields differ")
if policy["schema_version"] != "aidefend.autonomy-profile-policy.v1":
    raise ValueError("autonomy policy schema differs")
for field in ("allowed_operating_scopes", "required_functions", "allowed_modes"):
    values = policy[field]
    if (
        not isinstance(values, list)
        or not values
        or any(not isinstance(value, str) or not value for value in values)
        or len(values) != len(set(values))
    ):
        raise ValueError(f"autonomy policy population is invalid: {field}")
if agent["operating_scope"] not in policy["allowed_operating_scopes"]:
    raise ValueError("operating scope is not allowed")

profile = agent["autonomy_profile"]
if not isinstance(profile, dict) or set(profile) != set(policy["required_functions"]):
    raise ValueError("autonomy function population differs")
invalid_modes = {
    name: mode for name, mode in profile.items()
    if mode not in policy["allowed_modes"]
}
if invalid_modes:
    raise ValueError(f"unsupported autonomy modes: {invalid_modes}")

approval_keys = {
    "schema_version", "approval_id", "decision", "profile_sha256",
    "policy_sha256", "approver_ids", "issued_at", "expires_at",
}
if not isinstance(approval, dict) or set(approval) != approval_keys:
    raise ValueError("approval receipt fields differ")
if (
    approval["schema_version"] != "aidefend.autonomy-profile-approval.v1"
    or approval["decision"] != "APPROVED"
    or approval["profile_sha256"] != sha256(profile_raw)
    or approval["policy_sha256"] != sha256(policy_raw)
    or not isinstance(approval["approval_id"], str)
    or not approval["approval_id"]
):
    raise ValueError("approval decision or digest binding differs")
approvers = approval["approver_ids"]
if (
    not isinstance(approvers, list)
    or not approvers
    or any(not isinstance(item, str) or not item for item in approvers)
    or len(approvers) != len(set(approvers))
):
    raise ValueError("approval identity population is invalid")
issued = datetime.fromisoformat(approval["issued_at"].replace("Z", "+00:00"))
expires = datetime.fromisoformat(approval["expires_at"].replace("Z", "+00:00"))
now = datetime.now(timezone.utc)
if issued.tzinfo is None or expires.tzinfo is None or issued > now or expires <= now or expires <= issued:
    raise ValueError("approval validity window is invalid")

result = {
    "schema_version": "aidefend.autonomy-profile-validation.v1",
    "agent_id": agent["id"],
    "operating_scope": agent["operating_scope"],
    "profile_sha256": sha256(profile_raw),
    "policy_version": policy["policy_version"],
    "policy_sha256": sha256(policy_raw),
    "approval_id": approval["approval_id"],
    "approver_ids": approvers,
    "approval_receipt_sha256": sha256(approval_raw),
    "function_count": len(profile),
    "validation_status": "PASS",
}
output = Path("evidence/autonomy-profile-validation.json")
output.parent.mkdir(parents=True, exist_ok=True)
output.write_text(json.dumps(result, indent=2, sort_keys=True) + "\n", encoding="utf-8")
if json.loads(output.read_text(encoding="utf-8")) != result:
    raise RuntimeError("autonomy validation readback differs")
Verify signed inputs before running the validator
set -euo pipefail
umask 077
root="$(mktemp -d)"
trap 'rm -rf -- "$root"' EXIT
install -m 0400 -- "$AUTONOMY_PROFILE" "$root/profile.yaml"
install -m 0400 -- "$AUTONOMY_PROFILE_POLICY" "$root/policy.json"
install -m 0400 -- "$AUTONOMY_PROFILE_POLICY_BUNDLE" "$root/policy.sigstore.json"
install -m 0400 -- "$AUTONOMY_PROFILE_APPROVAL" "$root/approval.json"
install -m 0400 -- "$AUTONOMY_PROFILE_APPROVAL_BUNDLE" "$root/approval.sigstore.json"
cosign verify-blob --key "$AUTONOMY_POLICY_VERIFY_KEY"   --bundle "$root/policy.sigstore.json" "$root/policy.json" >/dev/null
cosign verify-blob --key "$AUTONOMY_APPROVAL_VERIFY_KEY"   --bundle "$root/approval.sigstore.json" "$root/approval.json" >/dev/null
export AUTONOMY_PROFILE="$root/profile.yaml"
export AUTONOMY_PROFILE_POLICY="$root/policy.json"
export AUTONOMY_PROFILE_APPROVAL="$root/approval.json"
python governance/validate_autonomy_profile.py

Action: Block deployment unless the validator emits PASS for the exact profile, policy, and approval receipt. Duplicate YAML keys, extra functions, omitted functions, unsupported modes or scope, stale approval, or a digest mismatch must never be downgraded to a warning.

Open-source tools

Commercial / hosted tools

Threat mappings

MITRE ATLAS

MAESTRO

OWASP LLM Top 10 2026

OWASP ML Top 10 2023

OWASP Top 10 for Agentic Applications 2026

NIST Adversarial Machine Learning 2025

Cisco Integrated AI Security and Safety Framework

Google Secure AI Framework 2.0 - Risks

Databricks AI Security Framework 3.0

AID-M-009.001: Operating Scope & Functional Autonomy Profiles | AIDEFEND

Loading interactive view…

A Practical Knowledge Base for AI Security Defenses

Version