Skip to navigation

Inbound message anatomy

The Message shape every platform adapter normalizes to
View as Markdown

An incoming message is a Message. The same shape applies whether it came from Slack, the web chat, or any other adapter.

Message

FieldTypeRequiredNotes
idstringyesUUID assigned by the sidecar.
timestampTimestampyesWhen the platform received the message.
platformstringyes"slack", "web", "discord", etc.
platformContextPlatformContextyesPlatform-native IDs and event metadata.
userUseryesSender identity.
contentstringyesCleaned text. Adapters strip the bot’s @-mention before forwarding.
attachmentsAttachment[]noFiles, images, video, audio, link previews.
conversationIdstringyesStable correlation ID across the message lifecycle. Always echo back on responses.
historyConversationHistorynoSet when the earlier turns differ from what the agent last answered. See Edited messages. null otherwise.

ConversationHistory

FieldTypeNotes
messagesHistoryMessage[]The turns before this message, oldest first. Can be empty.
isCompletebooleanfalse when older turns were left out to bound the size.

HistoryMessage

FieldTypeNotes
idstringMessage ID in the chat.
rolestring"user" or "assistant".
contentstringText only. No attachments.

Timestamp (google.protobuf.Timestamp)

FieldTypeNotes
secondsstringSeconds since UNIX epoch. Encoded as a string (can exceed JS safe int).
nanosnumberNanoseconds within the second.

User

FieldTypeRequiredNotes
idstringyesPlatform-specific user ID.
usernamestringnoDisplay name or handle.
avatarUrlstringnoAvatar URL.
emailstringnoEmail if available.
userData{ [key: string]: string }noPlatform-specific extras (workspace, role, etc.).

Attachment

FieldTypeRequiredNotes
typestringyesOne of the enum values below.
urlstringnoDownload URL when the source provides one. Filesystem-backed web uploads leave this empty.
filenamestringnoOriginal filename.
sizeBytesnumbernoFile size in bytes.
mimeTypestringnoMIME type.
titlestringnoDisplay title (rich attachments).
descriptionstringnoDisplay description.
widthnumbernoFor images/videos.
heightnumbernoFor images/videos.
storageKeystringnoOpaque Files API key for a web-chat upload. Resolve it through AGENT_FILES_DIR; never construct an input path from filename.

Attachment.type values: TYPE_UNSPECIFIED, IMAGE, FILE, VIDEO, AUDIO, LINK.

PlatformContext

FieldTypeRequiredNotes
messageIdstringyesOriginal platform message ID.
channelIdstringyesChannel/room/chat ID.
threadIdstringnoAgent’s reply target. Also set on top-level messages whose response should open a new thread.
threadRootIdstringnoParent thread root timestamp. Set only when this message is a reply inside an existing thread.
channelNamestringnoDisplay channel name.
workspaceIdstringnoSlack workspace, Discord guild, etc.
botUserIdstringnoThe bot’s own user ID in the source platform.
userIdstringnoRaw platform-native sender ID before any cross-platform identity resolution.
eventKindstringyesSee PlatformContextEventKind below.
platformData{ [key: string]: string }noPlatform-specific extras (Slack ts, Discord snowflake, Teams activity ID).

PlatformContextEventKind

ValueWhen the adapter emits it
EVENT_KIND_UNSPECIFIEDFallback. Should not appear in production traffic.
EVENT_KIND_DM1:1 / private chat (Slack DM, web chat session).
EVENT_KIND_APP_MENTIONBot was @-mentioned in a channel or thread.
EVENT_KIND_THREAD_REPLYReply inside an existing thread, no @-mention.
EVENT_KIND_OBSERVEDObserve-channel forward (listen-only).
EVENT_KIND_REACTIONReaction added/removed.
EVENT_KIND_BUTTON_CLICKInteractive button click on a CardAttachment.
EVENT_KIND_SLASH_COMMANDSlash command (Slack/Discord).
EVENT_KIND_ASSISTANT_THREAD_STARTEDSlack assistant thread opened.

Edited messages

In the web chat, a user can edit a message they sent. The chat keeps the old message and its replies as another version, and the user can switch between versions. The history your agent stores for the conversation then holds turns the user replaced.

When that happens, the next message carries history: the turns before it, on the version the user is looking at. Replace the history you store for conversationId with history, then handle the message as usual. An empty history means the message has no earlier turns, as when the user edits their first message. The same field arrives when the user switches to another version and continues there, and after a turn your agent did not answer.

history carries text only; a user turn that carried only files arrives as a line naming them. It holds the newest turns that fit in 512 KiB, and isComplete is false when it left older ones out.

The chat offers editing only for agents that set supportsHistory in the config they send at startup. The Mastra and LangChain adapters and the AI SDK adapter set it and reset their memory for you. In your own adapter the flag defaults to off, so an agent that ignores history never receives an edit.

getConfig() {
return { systemPrompt: "You are a helpful assistant.", tools: [], supportsHistory: true };
}

For web-chat file input and agent-produced downloads, see Files in chat.

Next steps