conversation_id, an ordered parts[] array, and an Idempotency-Key:
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 8suggestions to a message when a short list of answers covers what you need next:
{ "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:slot_sat_8 sends a normal user message through the existing message pipeline:
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 resultingmessage.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:
part_index from the stored message in message.received. Part indexes are dense, zero-based, and stable.
Idempotency
TheIdempotency-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.
Long replies
Split content longer than the per-part limit acrosstext 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.