> ## Documentation Index
> Fetch the complete documentation index at: https://www.agentworldprotocol.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Command channels (normative)

> Agent→world frame channels for high-rate setpoints, bound to a streaming action.

Frame channels run in both directions. Worlds MAY declare **command channels** — writable channels carrying agent→world frames — for control that runs faster than per-submission JSON-RPC is suited to: torque- and servo-level setpoints at 100–1000 Hz. Action chunking at 10–50 Hz does not need them; use the chunk-replacement idiom in [Actions](/spec/loop/actions).

A command channel is not opened directly. The agent submits a granted action of `duration: "streaming"`; the action is the channel's anchor — grants, envelopes, lifecycle, preemption, and audit all apply through it. The action is best read as a mode switch ("enter servo control"), and the frames as data within that mode.

Fragment (illustrative) of a manifest declaring one command channel and its anchoring action; the complete, validated manifest is [`examples/v0.1/world-manifest-servo.json`](https://github.com/Hyperduality/agent-world-protocol/blob/main/examples/v0.1/world-manifest-servo.json):

```json theme={null}
"capabilities": { "command_channels": true },
"command_channels": [
  { "id": "servo_arm", "modality": "servo/json", "rate_hz": 500, "loss_class": "latest-wins",
    "schema": { "joints": 7, "control": "position", "fields": ["q_target_rad"] } }
],
"action_schemas": [
  { "type": "servo",
    "params_schema": { "$ref": "#/$defs/servo_params" },
    "duration": "streaming", "command_channel": "servo_arm", "watchdog_ms": 200,
    "preemption": ["replace", "reject"], "concurrency_group": "arm_motion" }
],
"$defs": {
  "servo_params": { "type": "object",
    "properties": { "control": { "type": "string", "enum": ["position"] },
                    "max_joint_velocity_radps": { "type": "number", "exclusiveMinimum": 0, "maximum": 2.0 } },
    "required": ["control"], "additionalProperties": false }
}
```

* Command channels are gated on the `command_channels` capability, declared in the manifest's top-level `command_channels` list using the standard [channel schema](/api-reference/schemas/observation-channel), and available only in the streaming time model. `[AWP-CMD-001]`
* Every action schema naming a `command_channel` MUST declare `duration: "streaming"` and reference a declared command channel; a granted streaming action type implies access to its bound channel, whose `channel_id` is assigned in `session.ready` like any other. `[AWP-CMD-002]`
* Frames are accepted on a command channel only while exactly one bound action is `executing`; worlds MUST discard frames received outside such a binding. `[AWP-CMD-003]`
* A streaming action never completes on its own: it remains `executing` while the stream is live and reaches a terminal state only via `action.cancel` (safe abort per AWP-LIF-005, then `cancelled`, closing the channel), preemption, failure, or deadline. `deadline_ms`, when given, bounds the total stream lifetime and is binding. `[AWP-CMD-004]`
* Streaming action types MUST declare `watchdog_ms`. If no valid frame arrives within `watchdog_ms` while the action is `executing`, the world MUST apply the type's safe-abort behavior and fail the action with reason `watchdog`. `[AWP-CMD-005]`
* Every inbound frame MUST be envelope-checked world-side before actuation (AWP-ENV-001): `clamp` executes at the limit; `reject` drops the frame. Persistent violations MAY fail the action with reason `envelope`. `[AWP-CMD-006]`
* Frames carry the standard [frame envelope](/spec/transport/frames) with per-channel monotonically increasing `seq` and `ts_mono_ns` as the setpoint's issue time on the session clock (AWP-CLK-009); worlds MUST apply frames in `seq` order and, on `latest-wins` channels, MUST drop a frame older than the last applied one. `[AWP-CMD-007]`
* The [audit log](/spec/safety/audit-log) records inbound frames — payload or SHA-256 hash plus header — exactly as observation frames. `[AWP-CMD-008]`

During `executing`, `progress` is not meaningful and MAY be omitted; status updates SHOULD instead carry a `stream` object (`{ frames_applied, last_seq, clamped_count }`, see [action.status](/api-reference/control/action-status)) at ≥1 Hz. Preemption and concurrency groups apply to streaming actions as to any other: a `replace` submission preempts the running stream and closes its channel.
