Send a message with conversation_id, an ordered parts[] array, and an Idempotency-Key:
Relay returns 202 Accepted with message_id and the stored message. Each stored part includes its assigned part_index.

Part types

A message carries 1–32 parts. Order is presentation order.
Upload a file to get an attachment_id, or pass a public url. See Attachments.
data parts carry integration-defined JSON such as tool results and artifacts. Relay also recognizes the v1 message component kinds: buttons, select, card, confirm, and agent_permission_request. Clients that cannot render a part use its component fallback when present, then the message’s fallback_text, derived from the first text part, first link preview, data fallback, Voice memo, or [attachment]. Use Voice memos when audio should appear in the inline voice player, and Rich link previews when a URL should render as a preview card.

Quick replies

Attach up to 8 suggestions to a message when a short list of answers covers what you need next:
Each suggestion is { "text": "…" } with 1 to 96 characters. The user can always type a free-form answer instead. Relay lays the options out for you: a short set renders as inline rows in the transcript, and a longer set collapses into a single card that opens a full-height picker sheet. You don’t choose the presentation.
Quick-reply suggestions are separate from message components. Suggestions are transient presentation on the newest message and send a text part. Components are durable data parts in the transcript and return an origin-tagged data message.

Message components

Use a component data part when the choices must remain attached to their source message or the tap must carry a stable option identity:
Tapping slot_sat_8 sends a normal user message through the existing message pipeline:
The agent receives this as the next ordinary message.received event. Normal message idempotency covers retries. The client marks the successful choice selected and disables its siblings; your agent should still treat option_id as idempotent because stale taps are possible. See the catalog and per-kind wire contracts in Message components, Buttons, Select, Card, Confirm, and Agent permission request.

Replying to a message or a part

In a group, Relay invokes an agent only when a human explicitly selects it or replies to one of its messages. The resulting message.received event includes an invocation_id; echo that value as invocation_id in the finalized JSON request, or as the query parameter for a streamed reply. Ambient group context is not delivered to agent backends and does not appear in agent history. reply_to targets a whole message or a single part:
Use the part_index from the stored message in message.received. Part indexes are dense, zero-based, and stable.

Idempotency

The Idempotency-Key header is required and accepts 8–255 characters. Derive it from the inbound event_id:
  • Same key + same request → Relay returns the original message instead of sending twice.
  • Same key + different request → 409 idempotency_conflict.
Generate the key once per logical send and reuse it across retries.

Long replies

Split content longer than the per-part limit across text parts or messages. Each part renders as its own bubble. Next: pipe your agent’s existing output with Streaming, or react to a user’s message with Reactions.

Next steps