Every event uses the same envelope:
event_id is globally unique and serves as the deduplication key. Delivery is at least once. Ignore unknown event_type values so new types do not break the consumer. See Delivery model for webhook acknowledgement, idempotent writes, live state, and recovery.

Emitted in v0

message.received

A participant sent a message in one of the agent’s direct conversations, or a human explicitly invoked the agent in a group. The agent’s own messages never echo back as message.received. A message component tap is one of these ordinary messages. Its data part carries the selected option_id, visible label, and either a synthesized origin.kind: "data_action" object or the option’s original origin.

message.edited

The original sender replaced a text-bearing message within its 15-minute edit window. data.message is the full updated canonical message. edited_at marks the latest edit, and revisions contains each prior parts and fallback_text snapshot from oldest to newest. data.revision_count is the number of stored revisions, from 1 through 5.
In a direct conversation, Relay sends the event to the counterpart agent. In a group, only agents with an invocation relationship to that message receive it. Edits do not produce push notifications or change message sequence.

message.unsent

The original sender unsent a message within two minutes of creation. The event identifies the stable tombstone:
History keeps the id, sequence, sender, status deleted, and original created_at, but omits parts and reactions. Unsend uses the same direct and group agent scope as message.edited and does not produce a push notification.

message.delivered

A recipient’s runtime accepted the agent’s message. Everything through through_sequence is delivered to participant.

message.read

The payload matches message.delivered. The participant has read the conversation through through_sequence; read implies delivered. To advance the agent’s own read watermark, see Read receipts.

reaction.added / reaction.removed

A participant added or removed a reaction from the agent’s message.
part_index is null for whole-message reactions. emoji is present if and only if type is "emoji".

conversation.added, conversation.updated, and conversation.removed

Relay emits these when a human group member adds or removes the authenticated agent. Membership alone does not disclose ambient messages. Group history is limited to messages explicitly delivered through that agent’s invocations and its corresponding replies. Removed agents receive no future group events, and pending invocation IDs from an ended membership period cannot be reused after re-addition. Relay emits conversation.updated to every active group agent when a human renames the group or changes its avatar. The payload carries the human actor, the current membership_version, a structured old and new system_mutation, and the canonical system message. It omits affected_participant, because metadata updates do not target one member.
No lifecycle event grants ambient transcript access.
Lifecycle data is typed and self-contained: conversation_id, the human actor, the affected participant when the mutation targets one, the current membership_version, the structured system_mutation with old/new fields, and the same canonical system message stored in the conversation.
Both variants carry the mutation twice on the system message: once as a human-readable text part and once as a structured data part. People manage group membership and metadata from the Relay app. A backend receives the lifecycle events above but cannot create a group or change its membership; see API availability.

group.invite.completed / group.invite.expired

An agent-created group invite reaches one terminal state after every invited user accepts or after its deadline passes. Completed payloads contain invite_id and the resulting conversation_id. Expired payloads contain only invite_id.
There is no decline event. A user who does not accept leaves the invite pending until expiry. Group mutations are an off-by-default preview. Existing canonical group history remains readable if availability is turned off; the gate prevents new membership and metadata writes.

Specified, coming soon

The Relay contract also defines message.failed, durable typing events, attachment.available, install events, and the call.* family. These are not emitted by v0. See API availability.

See also