| Internet-Draft | AOCL | February 2026 |
| Cowles | Expires 1 September 2026 | [Page] |
Agent Orchestration Control Layers (AOCL) is a protocol that standardizes how an orchestrator processes incoming events by passing them through a layered control pipeline. AOCL defines an eleven-layer taxonomy covering ingress normalization, identity scoping, smart routing, policy gating, plan decomposition, context retrieval, prompt shaping, delegation and execution, verification, response assembly, and audit writeback. The protocol is runtime-agnostic and framework-agnostic, producing auditable governance traces as a first-class output. AOCL supports both sequential pipeline and directed acyclic graph (DAG) execution modes, with explicit bypass and branch semantics that mandate audit records for all control-flow deviations.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 1 September 2026.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document.¶
Autonomous AI agents are increasingly deployed in enterprise environments where they perform consequential actions: executing code, accessing databases, managing infrastructure, and interacting with external services. Despite this growing responsibility, there is no widely adopted standard for how agent actions flow through identity verification, policy enforcement, execution delegation, and audit recording.¶
Without a structured control pipeline, agent systems exhibit several governance failures: actions are taken without policy checks, bypass decisions are unrecorded, identity and permission scoping is ad-hoc, and there is no reproducible trace explaining why a particular action was taken or what evidence supports the result.¶
The Agent Orchestration Control Layers (AOCL) protocol addresses these problems by defining a layered control pipeline that an orchestrator runs when processing any incoming event. AOCL does not prescribe how agents are built, how tools execute, or how workers are scheduled. Instead, it standardizes the control layers through which work flows, the minimum contract each layer MUST follow, and the audit records that MUST be emitted.¶
AOCL is designed to be runtime-agnostic and framework-agnostic. It operates alongside the Agent Envelope Exchange (AEE) protocol [AEE], using AEE envelopes as the audit and delegation format without requiring any changes to the AEE specification. Verifiable audit trails MAY additionally be anchored using the VOLT protocol [VOLT].¶
The protocol defines eleven canonical layers (L0 through L10), a structured context bundle with seven partitions (C0 through C6), and two stack execution modes (pipeline and DAG). All control-flow deviations, including layer bypasses and branch decisions, MUST produce explicit audit records.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
The following terms are used throughout this document:¶
AOCL defines a control-plane architecture for agent orchestration. The architecture consists of four primary components: layers, stacks, context bundles, and the orchestrator.¶
A layer is the fundamental unit of control logic. Each layer receives an input context bundle, performs its designated function (normalization, policy checking, planning, etc.), and produces an output consisting of:¶
Layers are intentionally opaque in their implementation. A layer MAY be implemented as deterministic code, an LLM inference call, a rules engine, a remote service invocation, or any combination thereof. AOCL specifies only the input and output contracts, not the internal mechanism.¶
A stack is a configured arrangement of layers for a particular class of work. Stacks MAY be expressed as a sequential pipeline (ordered list) or as a directed acyclic graph (DAG) with conditional edges. An orchestrator MAY support multiple named stacks and select among them based on the characteristics of the incoming intent.¶
The context bundle is the shared state object that flows through layers. It is partitioned into seven segments (C0 through C6) to separate concerns and enable selective access. Layers SHOULD emit context deltas (patches) and references/digests rather than re-transmitting large objects. The context bundle SHOULD remain inspectable and replayable.¶
The orchestrator is responsible for:¶
AOCL explicitly does NOT define:¶
These concerns are deferred to runtime implementations or future revisions of this specification.¶
Work flows through ordered layers with clearly separated responsibilities. Each layer has a single primary concern (e.g., identity scoping, policy enforcement, context retrieval). This separation enables independent evolution, testing, and replacement of individual layers without affecting the overall pipeline structure.¶
AOCL supports alternate execution paths (branches) and the ability to skip layers (bypasses). However, all branch and bypass decisions MUST be auditable. The orchestrator MUST emit explicit records documenting which layers were bypassed or which branch was taken, who authorized the deviation, and why it was permitted.¶
Layers SHOULD emit context deltas (patches) and references/digests rather than re-transmitting entire context objects. This principle keeps audit payloads small, enables efficient replay, and allows integrity verification through digest comparison. Large data (e.g., RAG results, file contents) SHOULD be referenced by URI or content hash rather than embedded inline.¶
AOCL is designed to produce traces that answer five fundamental governance questions:¶
Every layer activation, decision, and control-flow change MUST produce an audit record. Observability is a first-class output of the protocol, not an optional add-on.¶
The context bundle is the structured state object that flows through all AOCL layers. AOCL does not mandate a single rigid schema, but RECOMMENDS partitioning the bundle into seven segments (C0 through C6) to maintain clear separation of concerns.¶
Contains metadata about the triggering event: source identifier, timestamp, channel (chat, webhook, API, schedule), correlation IDs, and any attachments or raw input data. This partition is populated during L0 (ingress normalization) and is generally read-only for subsequent layers.¶
Contains the authenticated identity context: user and/or organization identifiers, roles, permissions, secret scope boundaries, and redaction rules. This partition is populated during L1 (identity scoping) and is consumed by policy and execution layers to enforce access control.¶
Contains the structured task definition: goal statement, constraints, definition of done, priority level, and any decomposition into sub-tasks. This partition is refined during L4 (plan decomposition) and consumed during L7 (delegation and execution).¶
Contains retrieved contextual information: memory notes, retrieval-augmented generation (RAG) results, file references, and bounded summaries. This partition is populated during L5 (context retrieval) and consumed during L6 (shape and rewrite) and L7 (delegation and execution). Large data objects SHOULD be stored as references rather than inline values.¶
Contains active policy constraints: safety and compliance rules, allowed tool lists, model restrictions, content filtering requirements, and human-in-the-loop (HITL) thresholds. This partition is populated during L3 (policy gating) and enforced throughout subsequent layers.¶
Contains runtime execution parameters: budgets (token limits, cost ceilings), timeouts, concurrency limits, the tool registry, model routing preferences, and execution mode (e.g., "restricted-readonly", "full", "analysis-only").¶
Contains audit configuration: log level, required evidence types, compliance checkpoint identifiers, and references to external audit sinks. This partition governs what level of audit detail is emitted by each layer and what evidence MUST accompany the final result.¶
When serialized, the context bundle SHOULD be represented as a JSON [RFC8259] object with top-level keys corresponding to the partition identifiers (C0 through C6). The following is an illustrative example of a minimal context bundle:¶
{
"C0": {
"source": "chat",
"ts": "2026-01-26T12:00:00Z",
"channel": "web",
"corr": "01AOCL_CORR_0001"
},
"C1": {
"user_id": "user-42",
"org_id": "org-7",
"roles": ["operator"],
"redact": ["ssn", "credit_card"]
},
"C2": {
"goal": "Check backup status for production cluster",
"priority": "high"
},
"C3": {},
"C4": {
"allowed_tools": ["tool.readonly.*"],
"model_restrictions": []
},
"C5": {
"timeout_ms": 30000,
"max_parallel": 4,
"mode": "restricted-readonly"
},
"C6": {
"log_level": "info",
"evidence_required": true
}
}
¶
AOCL defines eleven canonical layers (L0 through L10). Implementations are not required to use these exact names, but adopting the shared taxonomy makes stacks portable, debuggable, and interoperable across different orchestrator implementations.¶
Each layer is described below with its canonical identifier, purpose, input contract, output contract, and key behaviors.¶
AOCL stacks define the arrangement and configuration of layers for a particular class of work. Two execution modes are supported: pipeline mode and DAG mode.¶
Pipeline mode arranges layers in a strict sequential order. Each layer executes after the previous one completes, unless a control flag causes a skip, branch, or halt. This is the simplest execution mode and is RECOMMENDED for most use cases.¶
A pipeline stack definition MUST include a stack_id, version, mode set to "pipeline", and an ordered array of layer entries. Each layer entry MUST include an id and ref field, and MAY include an enabled flag.¶
{
"stack_id": "default",
"version": "0.1",
"mode": "pipeline",
"layers": [
{"id": "L0.ingress.normalize", "ref": "builtin:l0.normalize",
"enabled": true},
{"id": "L1.identity.scope", "ref": "builtin:l1.identity",
"enabled": true},
{"id": "L2.route.smart", "ref": "builtin:l2.router",
"enabled": true},
{"id": "L3.policy.gate", "ref": "builtin:l3.policy",
"enabled": true},
{"id": "L4.plan.decompose", "ref": "builtin:l4.plan",
"enabled": true},
{"id": "L5.context.retrieve", "ref": "builtin:l5.context",
"enabled": true},
{"id": "L6.shape.rewrite", "ref": "builtin:l6.shape",
"enabled": true},
{"id": "L7.delegate.execute", "ref": "builtin:l7.delegate",
"enabled": true},
{"id": "L8.verify.check", "ref": "builtin:l8.verify",
"enabled": true},
{"id": "L9.assemble.respond", "ref": "builtin:l9.respond",
"enabled": true},
{"id": "L10.audit.writeback", "ref": "builtin:l10.audit",
"enabled": true}
],
"defaults": {
"bypass_allowed_for_roles": ["admin"],
"max_parallel_actions": 8,
"timeout_ms": 60000
}
}
¶
The "ref" field is an implementation pointer (plugin ID, module path, container image, etc.). AOCL does not define ref resolution semantics; it standardizes only the stack structure and layer input/output contracts.¶
DAG mode arranges layers as nodes in a directed acyclic graph with conditional edges. This mode supports conditional routing, parallel branches, fast-path exits, and restricted execution paths.¶
A DAG stack definition MUST include a stack_id, version, mode set to "dag", an array of nodes, and an array of edges. Each edge MUST include "from" and "to" fields, and MAY include a "when" condition.¶
{
"stack_id": "default-dag",
"version": "0.1",
"mode": "dag",
"nodes": [
{"id": "L0.ingress.normalize",
"ref": "builtin:l0.normalize"},
{"id": "L1.identity.scope",
"ref": "builtin:l1.identity"},
{"id": "L2.route.smart",
"ref": "builtin:l2.router"},
{"id": "L3.policy.gate",
"ref": "builtin:l3.policy"},
{"id": "L5.context.retrieve",
"ref": "builtin:l5.context"},
{"id": "L7.delegate.execute",
"ref": "builtin:l7.delegate"},
{"id": "L9.assemble.respond",
"ref": "builtin:l9.respond"},
{"id": "L10.audit.writeback",
"ref": "builtin:l10.audit"},
{"id": "BR.realtime_alert",
"ref": "builtin:branch.alert_fast"},
{"id": "BR.restricted_mode",
"ref": "builtin:branch.restricted"}
],
"edges": [
{"from": "L0.ingress.normalize",
"to": "L1.identity.scope"},
{"from": "L1.identity.scope",
"to": "L2.route.smart"},
{"from": "L2.route.smart",
"to": "L9.assemble.respond",
"when": "control.halt_pipeline == true"},
{"from": "L2.route.smart",
"to": "L3.policy.gate",
"when": "control.halt_pipeline != true"},
{"from": "L3.policy.gate",
"to": "BR.restricted_mode",
"when": "control.require_hitl == true"},
{"from": "L3.policy.gate",
"to": "L5.context.retrieve",
"when": "control.require_hitl != true"},
{"from": "L5.context.retrieve",
"to": "L7.delegate.execute"},
{"from": "L7.delegate.execute",
"to": "L9.assemble.respond"},
{"from": "L9.assemble.respond",
"to": "L10.audit.writeback"}
],
"defaults": {
"max_parallel_actions": 8,
"timeout_ms": 60000
}
}
¶
The "when" field is expressed as a string condition. In this version of the specification, implementations MAY treat it as simple boolean expressions over "context" and "control" namespaces. A formal expression language is deferred to future revisions.¶
Branch nodes (prefixed with "BR.") MAY represent sub-stacks that contain their own layer sequences. The resolution of branch node internals is implementation-defined.¶
Implementations are encouraged to define variant stacks tailored to specific workload classes. The following variants are RECOMMENDED:¶
AOCL is designed to work alongside the Agent Envelope Exchange (AEE) protocol [AEE]. AEE standardizes the message envelope for agent-to-agent and human-to-agent exchange, providing identity, intent, and causality semantics. AOCL standardizes the layered control pipeline that an orchestrator runs to decide what happens.¶
This binding defines how AOCL uses AEE without requiring any changes to the AEE envelope specification. AOCL operates entirely through intent conventions and payload schemas within existing AEE envelope types.¶
AOCL uses existing AEE envelope type categories:¶
AOCL does not require any new AEE type values.¶
AOCL defines the following intent namespace for layer-level audit and control. All intents use the "aocl." prefix:¶
| Intent | Description |
|---|---|
| aocl.stack.select | Stack selection decision |
| aocl.layer.enter | Layer activation (entry) |
| aocl.layer.exit | Layer completion (exit) |
| aocl.layer.decision | Layer decision with coded reasons |
| aocl.context.patch | Context bundle modification (delta) |
| aocl.control.branch | Branch decision (alternate path taken) |
| aocl.control.bypass | Layer bypass decision |
| aocl.verify.result | Verification outcome |
| aocl.run.summary | Complete run summary |
For business-level delegation, AOCL does not impose intent names. Delegated tasks use the caller's intent (e.g., "ops.backup.status.check") or a derived intent convention appropriate to the domain.¶
All envelopes generated during processing of a single work item MUST share the same "corr" (correlation) value as the originating request envelope. This enables grep-able traces across layer events, agent tasks and results, verification records, and final responses.¶
AOCL supports two reply-chaining strategies for the "reply_to" field:¶
Implementations SHOULD choose one strategy and apply it consistently within a deployment. Mixing strategies within a single processing run is NOT RECOMMENDED.¶
AOCL layer envelopes SHOULD NOT contain the full context bundle. Instead, payloads SHOULD include only the following fields:¶
The following example shows an AOCL layer decision emitted as an AEE event envelope:¶
{
"v": "1",
"id": "01AOCL_LAYER_EVENT_0001",
"ts": "2026-01-26T12:00:01Z",
"type": "event",
"from": "agent.orchestrator",
"to": "log.aocl",
"intent": "aocl.layer.decision",
"corr": "01AOCL_CORR_0001",
"reply_to": "01ORIGIN_TASK_0001",
"trace": null,
"priority": "normal",
"requires": null,
"payload": {
"run_id": "RUN-01AOCL-0001",
"layer": {
"id": "L3.policy.gate",
"version": "0.1"
},
"decisions": [
{
"code": "POLICY_ALLOW",
"reason": "No restricted content; tools allowed: read-only"
}
],
"delta": {
"C4.Policy.allowed_tools": ["tool.readonly.*"],
"C5.Execution.mode": "restricted-readonly"
},
"refs": [],
"digests": {
"context_in": "sha256:abc123...",
"context_out": "sha256:def456..."
},
"control": {
"halt_pipeline": false
}
},
"sig": null
}
¶
The following example shows an AOCL delegation emitted as an AEE task envelope:¶
{
"v": "1",
"id": "01AOCL_DELEGATE_TASK_0001",
"ts": "2026-01-26T12:00:03Z",
"type": "task",
"from": "agent.orchestrator",
"to": "agent.backup_auditor",
"intent": "ops.backup.status.check",
"corr": "01AOCL_CORR_0001",
"reply_to": "01ORIGIN_TASK_0001",
"trace": null,
"priority": "high",
"requires": {
"timeout_ms": 30000,
"evidence": true
},
"payload": {
"cluster_ref": "inv://clusters/node.lan",
"window": "24h",
"context_refs": [
"mem://run/RUN-01AOCL-0001/context-snapshot"
]
},
"sig": null
}
¶
Note that the "to" field is a logical sink identifier (e.g., "log.aocl", "agent.backup_auditor") that MAY map to a file, message queue topic, streaming subject, or any other transport endpoint. The AOCL semantics are carried entirely in the intent and payload fields, while the AEE envelope structure remains stable and unchanged.¶
AOCL supports two forms of control-flow deviation: bypasses (skipping one or more layers) and branches (taking an alternate execution path). Both forms are permitted but MUST be explicitly audited.¶
When a layer bypass is requested or applied, the orchestrator MUST emit an AEE event envelope with intent "aocl.control.bypass" containing:¶
Stacks SHOULD declare bypass policy in their configuration. The following example shows a bypass policy declaration:¶
{
"bypass_policy": {
"allowed_roles": ["admin"],
"never_bypass": [
"L1.identity.scope",
"L3.policy.gate"
],
"audit_required": true
}
}
¶
Implementations SHOULD NOT allow bypass of the identity layer (L1.identity.scope) or the policy layer (L3.policy.gate) in production deployments. If bypass of these layers is permitted (e.g., in development or testing environments), the orchestrator MUST still emit a bypass audit record.¶
When the orchestrator takes a branch (alternate execution path), it MUST emit an AEE event envelope with intent "aocl.control.branch" containing:¶
Branch decisions are typically emitted by the smart router (L2) or the policy gate (L3), but any layer MAY produce branch control flags if the stack configuration permits it.¶
The combination of bypass and branch audit records, together with layer enter/exit events, MUST provide a complete and reconstructable picture of which layers were executed, which were skipped, and which alternate paths were taken for every processing run. An observer with access to the audit trail MUST be able to reconstruct the exact execution path without any implicit or hidden state transitions.¶
AOCL is a control-plane protocol that governs how AI agent operations flow through identity, policy, execution, and audit stages. The security properties of a deployment depend critically on the integrity of each layer and the trustworthiness of the orchestrator. This section describes the primary security considerations.¶
The policy gate (L3.policy.gate) is the primary governance checkpoint. If an attacker can manipulate, bypass, or disable this layer, they can cause the orchestrator to execute actions that violate organizational policies. Implementations MUST ensure that the policy layer cannot be circumvented through context manipulation, layer reconfiguration, or control-flag injection.¶
Policy rules SHOULD be loaded from a trusted, integrity- protected source. Changes to policy configuration SHOULD require authenticated authorization and SHOULD themselves be audited.¶
Layer bypasses represent a significant security-relevant event. The bypass audit trail is the primary mechanism for detecting unauthorized control-flow deviations. Implementations MUST ensure that:¶
The identity layer (L1.identity.scope) populates the C1 partition that all subsequent layers rely on for access control decisions. If the identity layer produces incorrect or forged identity information, all downstream policy enforcement and access control becomes unreliable.¶
Implementations MUST use authenticated identity sources (e.g., verified tokens, mutual TLS, signed assertions) rather than self-reported identity claims. The identity layer SHOULD validate identity assertions against a trusted identity provider before populating C1.¶
When AOCL operates in a multi-tenant environment, implementations MUST ensure that identity scoping prevents cross-tenant data access through context bundle isolation or equivalent mechanisms.¶
Layers SHOULD be isolated from one another to prevent a compromised or malfunctioning layer from corrupting the context bundle or control flags of other layers. The orchestrator SHOULD validate context bundle modifications against expected schemas and reject unexpected mutations.¶
When layers are implemented as external services or plugins, the orchestrator SHOULD authenticate layer implementations and validate their outputs. A malicious layer implementation could inject false decisions, corrupt the context bundle, or emit misleading audit records.¶
The delegation layer (L7.delegate.execute) poses particular isolation challenges because it invokes external agents and tools. Implementations SHOULD sandbox delegated execution and validate returned results against expected schemas before incorporating them into the context bundle.¶
An attacker who can submit intents to the orchestrator may attempt to cause denial of service by:¶
Implementations SHOULD enforce resource budgets at the stack level (timeout_ms, max_parallel_actions) and at individual layer level. The orchestrator SHOULD implement rate limiting on incoming intents and circuit breakers on layers that exhibit abnormal latency or error rates. Verification loops (L7 to L8 retry cycles) MUST be bounded by a configurable maximum retry count.¶
The context bundle may contain sensitive information across multiple partitions: authentication credentials in C1, proprietary task details in C2, retrieved knowledge in C3, and policy rules in C4. Implementations MUST protect the context bundle from unauthorized access during transmission between layers and at rest.¶
When layers are distributed across network boundaries, the context bundle MUST be transmitted over encrypted channels (e.g., TLS). When layers are implemented by third-party services, the orchestrator SHOULD apply data minimization by providing only the context partitions that a layer requires, rather than the full bundle.¶
Audit records emitted as AEE envelopes contain context deltas that may include sensitive data. Implementations SHOULD apply redaction rules from C1 to audit payloads before persisting them, or ensure that audit sinks have equivalent access protections to the data sources referenced in the context bundle.¶
This document has no IANA actions.¶
The author wishes to thank the early adopters and reviewers of the AOCL specification within the Quox ecosystem, whose feedback on real-world agent orchestration challenges shaped the design of this control-layer protocol.¶