Message Schema
Every OACP message is a YAML file with a defined set of required and optional fields. This page documents the complete schema, naming conventions, and field formats.
Complete Schema
Section titled “Complete Schema”A fully annotated message with all fields:
# Required fieldsid: "msg-20260313T1430Z-claude-a8f3" # Unique message identifierfrom: claude # Sender agent nameto: codex # Recipient (string or list for broadcast)type: task_request # One of 12 message typespriority: P2 # P0 | P1 | P2 | P3created_at_utc: "2026-03-13T14:30:00Z" # ISO 8601 UTCsubject: "Implement rate limiting" # Short subject linebody: | # Message content (free-form or structured) Add rate limiting to the /api/v1/* routes. Token bucket algorithm, 100 req/min per API key.
# Optional fieldsexpires_at: "2026-03-14T12:00:00Z" # When message expires (advisory)channel: review # Conversation category tagrelated_packet: "" # Packet ID referencerelated_pr: "42" # PR numberconversation_id: "conv-20260313-claude-001" # Thread groupingparent_message_id: "msg-20260313T1400Z-codex-b2e1" # Reply threadingcontext_keys: | # Summary of prior context for handoffs Key decisions and artifacts from prior conversation.autonomy_hint: auto_proceed # Advisory accept hint (see Receiver Autonomy)
# Optional signature trailer (v0.4.0) — always the final physical lineauth: "<base64url detached JWS over the raw bytes above>"Required Fields
Section titled “Required Fields”Every message must include these fields. Omitting any of them will cause oacp validate to reject the message.
| Field | Type | Format | Description |
|---|---|---|---|
id | string | msg-<timestamp>-<sender>-<rand> | Unique identifier for the message |
from | string | Agent name | Sender agent (e.g., claude, codex, gemini) |
to | string or list | Agent name(s) | Recipient agent or list for broadcast (max 10) |
type | string | Enum | One of the 12 defined message types |
priority | string | P0, P1, P2, P3 | Message priority |
created_at_utc | string | ISO 8601 UTC | When the message was created |
subject | string | Free text | Short description of the message purpose |
body | string or mapping | Varies by type | Message content — free-form text or structured data |
Optional Fields
Section titled “Optional Fields”These fields are not required but provide additional context when present.
| Field | Type | Format | Description |
|---|---|---|---|
expires_at | string | ISO 8601 UTC | When the message is no longer actionable (advisory) |
channel | string | Free text (max 64 chars) | Conversation category (e.g., review, deploy, incident) |
related_packet | string | Packet ID | Reference to a review/findings packet |
related_pr | string | PR number | Associated pull request |
conversation_id | string | conv-<YYYYMMDD>-<agent>-<seq> | Groups related messages into a thread |
parent_message_id | string | Message ID | Links a reply to the message it responds to |
context_keys | string | Multi-line text | Summary of prior context (under 500 words) |
autonomy_hint | string | auto_proceed | Advisory hint that the sender considers the message safe to auto-accept. Receiver config is authoritative — see Receiver Autonomy |
auth | string | base64url detached JWS | Ed25519 signature trailer over the exact raw bytes of the message above it (since v0.4.0). Always the final physical line — see Signed Messages below |
Autonomy Fields
Section titled “Autonomy Fields”When a receiver runs in auto_review mode, two fields decide whether a message can be accepted without human confirmation. See Receiver Autonomy for the full four-gate evaluator.
autonomy_hint(top-level, optional) —auto_proceedsignals that the sender considers the message safe to auto-accept. It is advisory only: the receiver’s config and gates are authoritative, and a hint never escalates a verdict.task_profile(body block) — underauto_review,task_requestandquestionmessages must declare a machine-parseable profile so the receiver can size risk against its thresholds:
task_profile: estimated_minutes: 20 risk_tier: P3 expected_files_touched: 3 destructive_ops: false external_side_effects: false touches_auth_config_or_secrets: false touches_dependencies: false public_visibility: falseA missing block pauses with task_profile_missing; an unparsable one pauses with task_profile_unparsable. Neither is a fatal schema error — both simply withhold auto-acceptance. Types in the receiver’s allow_without_task_profile list may auto-accept without the block.
Signed Messages (auth)
Section titled “Signed Messages (auth)”Since v0.4.0, a message may end with an optional auth trailer — a single final physical line carrying a base64url-encoded detached JWS signed over the exact raw bytes of everything above it. It is not an ordinary YAML field: its position is fixed (last line, nothing after it), its encodings are canonical-only, and receivers verify it against their own local key pins before parsing the message. Unsigned messages omit it entirely, and receivers without a verify knob treat it as an ordinary optional field.
auth: "<base64url of a detached General JWS JSON: {signatures: [{protected, signature} x 1-8]}>"The full wire format, trust root, and verification semantics live on the Message Signing protocol page; command-level flags at oacp verify.
Filename Convention
Section titled “Filename Convention”Message files follow a strict naming pattern:
<timestamp>_<from>_<type>.yaml| Component | Format | Example |
|---|---|---|
timestamp | YYYYMMDDTHHmmZ (compact ISO 8601) | 20260313T1430Z |
from | Sender agent name | codex |
type | Message type | task_request |
Full example:
20260211T1430Z_codex_task_request.yamlMessages are written to the recipient’s inbox and copied to the sender’s outbox:
agents/<recipient>/inbox/20260211T1430Z_codex_task_request.yamlagents/<sender>/outbox/20260211T1430Z_codex_task_request.yamlID Format
Section titled “ID Format”Message IDs follow a deterministic pattern that encodes the timestamp, sender, and a random suffix for uniqueness:
msg-<timestamp>-<sender>-<rand>| Component | Format | Description |
|---|---|---|
msg- | Literal prefix | Identifies the string as a message ID |
<timestamp> | YYYYMMDDTHHmmZ | Compact ISO 8601 timestamp |
<sender> | Agent name | Who created the message |
<rand> | 4-character alphanumeric | Random suffix for uniqueness |
Example:
msg-20260313T1430Z-claude-a8f3Priority Levels
Section titled “Priority Levels”Priority indicates urgency and whether the message blocks other work.
| Priority | Label | Description |
|---|---|---|
P0 | Urgent | Always blocking. Requires immediate attention. Production incidents, security issues, broken builds. |
P1 | Blocking | Blocks the sender’s current work. Review requests, critical questions, handoffs. |
P2 | Default | Normal priority. Most task requests and follow-ups. |
P3 | Low | Non-blocking. Informational notifications, deferred nits, brainstorm requests. |
When priority is omitted from a message, it defaults to P2.
Timestamp Format
Section titled “Timestamp Format”All timestamps in OACP use ISO 8601 in UTC:
YYYY-MM-DDTHH:MM:SSZThe trailing Z indicates UTC. Local time zones are not used.
Examples:
2026-03-13T14:30:00Z2026-01-15T09:00:00Z2026-12-31T23:59:59ZIn filenames, timestamps use a compact form without hyphens, colons, or seconds:
20260313T1430ZExample Messages
Section titled “Example Messages”Task Request
Section titled “Task Request”A straightforward task assignment from one agent to another.
id: "msg-20260313T1430Z-claude-a8f3"from: claudeto: codextype: task_requestpriority: P2created_at_utc: "2026-03-13T14:30:00Z"subject: "Add input validation to /api/users endpoint"body: | The /api/users POST endpoint currently accepts any payload. Please add: - Email format validation - Username length check (3-30 chars, alphanumeric + underscore) - Rate limiting on failed validation attempts
Reference: docs/api-spec.md section 3.2Review Request
Section titled “Review Request”Requesting a code review with reviewer constraints.
id: "msg-20260313T1600Z-claude-c4d7"from: claudeto: codextype: review_requestpriority: P1created_at_utc: "2026-03-13T16:00:00Z"related_pr: "42"subject: "Review: JWT auth middleware (#42)"body: | pr: 42 branch: feat/auth-middleware diff_summary: | Adds JWT validation middleware to the API gateway. - RS256 signature verification with key rotation - Token expiry and audience checks - 4 new files, 320 lines added - Full test coverage including expired/malformed token cases max_turns_reviewer: 8 max_runtime_s_reviewer: 600Notification
Section titled “Notification”An informational status update that requires no action.
id: "msg-20260313T1715Z-codex-e9b2"from: codexto: claudetype: notificationpriority: P3created_at_utc: "2026-03-13T17:15:00Z"subject: "CI green on feat/auth-middleware"body: | All checks passing on PR #42: - 87 unit tests passed - 12 integration tests passed - Coverage: 94% (above 90% threshold) - No lint warnings
Ready for final review when you have time.