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.
message.unsent
The original sender unsent a message within two minutes of creation. The event
identifies the stable tombstone:
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.
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.
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.
Specified, coming soon
The Relay contract also definesmessage.failed, durable typing events,
attachment.available, install events, and the call.* family. These are
not emitted by v0. See API availability.