Skip to content

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.

A fully annotated message with all fields:

# Required fields
id: "msg-20260313T1430Z-claude-a8f3" # Unique message identifier
from: claude # Sender agent name
to: codex # Recipient (string or list for broadcast)
type: task_request # One of 12 message types
priority: P2 # P0 | P1 | P2 | P3
created_at_utc: "2026-03-13T14:30:00Z" # ISO 8601 UTC
subject: "Implement rate limiting" # Short subject line
body: | # Message content (free-form or structured)
Add rate limiting to the /api/v1/* routes.
Token bucket algorithm, 100 req/min per API key.
# Optional fields
expires_at: "2026-03-14T12:00:00Z" # When message expires (advisory)
channel: review # Conversation category tag
related_packet: "" # Packet ID reference
related_pr: "42" # PR number
conversation_id: "conv-20260313-claude-001" # Thread grouping
parent_message_id: "msg-20260313T1400Z-codex-b2e1" # Reply threading
context_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 line
auth: "<base64url detached JWS over the raw bytes above>"

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

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

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_proceed signals 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) – under auto_review, task_request and question messages 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: false

A 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.


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.


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.yaml

Messages are written to the recipient’s inbox and copied to the sender’s outbox:

agents/<recipient>/inbox/20260211T1430Z_codex_task_request.yaml
agents/<sender>/outbox/20260211T1430Z_codex_task_request.yaml

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-a8f3

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.


All timestamps in OACP use ISO 8601 in UTC:

YYYY-MM-DDTHH:MM:SSZ

The trailing Z indicates UTC. Local time zones are not used.

Examples:

2026-03-13T14:30:00Z
2026-01-15T09:00:00Z
2026-12-31T23:59:59Z

In filenames, timestamps use a compact form without hyphens, colons, or seconds:

20260313T1430Z

A straightforward task assignment from one agent to another.

id: "msg-20260313T1430Z-claude-a8f3"
from: claude
to: codex
type: task_request
priority: P2
created_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.2

Requesting a code review with reviewer constraints.

id: "msg-20260313T1600Z-claude-c4d7"
from: claude
to: codex
type: review_request
priority: P1
created_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: 600

An informational status update that requires no action.

id: "msg-20260313T1715Z-codex-e9b2"
from: codex
to: claude
type: notification
priority: P3
created_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.