Messaging SDK (Node)
Messaging SDK (Node)
The messaging SDK is how your agent container talks to the messaging sidecar that ships next to it. When you declare agent.interfaces.messaging: true in astropods.yml, the platform deploys a messaging container alongside your agent. That sidecar runs platform adapters (Slack, web chat, etc.), normalises every incoming event into a single protobuf shape, and routes it to your agent over a bidirectional gRPC stream.
This page covers the TypeScript SDK, @astropods/messaging. For Python, see Messaging SDK (Python).
If you’re building on a supported framework, prefer a higher-level adapter (e.g. @astropods/adapter-mastra). Those wrap the SDK and handle the streaming loop for you. Reach for the SDK directly when you need full control or when there is no adapter for your framework yet.
Field names below are camelCase — that’s how @grpc/proto-loader exposes proto fields to TypeScript. The corresponding proto names are snake_case.
Install
Connect to the sidecar
The sidecar listens on gRPC port 9090. Inside the same pod the address is always localhost:9090; locally with ast dev it’s the same.
The sidecar talks plaintext gRPC on the loopback interface — no TLS, no auth. The trust boundary is the pod itself.
ReconnectOptions (used by connectWithRetry() and createConversationStream())
The conversation stream
The primary RPC is ProcessConversation — a bidirectional stream. The sidecar pushes incoming user messages, feedback, and audio. Your agent pushes back status updates, content chunks, errors, and other responses on the same stream.
ConversationStream events
ConversationStream send methods
Inbound message anatomy
An incoming message is a Message. The same shape applies whether it came from Slack, the web chat, or any other adapter.
Message
Timestamp (google.protobuf.Timestamp)
User
Attachment
Attachment.type values: TYPE_UNSPECIFIED, IMAGE, FILE, VIDEO, AUDIO, LINK.
PlatformContext
PlatformContextEventKind
Sending a response
AgentResponse
AgentResponse payload variants
Streaming text content
ContentChunk
ContentChunk.type lifecycle
MessageOptions
ResponseAttachment (set exactly one variant)
Example:
Status updates
StatusUpdate
StatusUpdate.status values: THINKING, SEARCHING, GENERATING, PROCESSING, ANALYZING, CUSTOM.
Suggested prompts
SuggestedPrompts
Prompt
Errors
ErrorResponse
ErrorResponse.code values: RATE_LIMIT, CONTEXT_TOO_LONG, INVALID_REQUEST, AGENT_ERROR, TOOL_ERROR, PLATFORM_ERROR.
Thread metadata
ThreadMetadata
Transcript
Sent after STT to replace the “[audio]” placeholder on the platform.
Transcript
Receiving platform feedback
The sidecar sends PlatformFeedback on the same stream when the user interacts with a previous response.
PlatformFeedback
PlatformFeedback variants
MessageReaction
PromptSelection
ButtonClick
StreamControl
MessageEdit
MessageDelete
TextFeedback
Audio
Audio flows agent-side as raw bytes — the messaging system does no STT, transcoding, or VAD.
AudioStreamConfig
AudioChunk
AudioEncoding
Use audioAsReadable() to feed Mastra’s voice.listen():
Auxiliary RPCs
ThreadHistoryRequest
ThreadHistoryResponse
ThreadMessage
Reconnection
The Node SDK has a built-in reconnect loop on both connectWithRetry() and createConversationStream(). It retries with full-jitter exponential backoff and buffers writes until the stream is back.
Local development
ast dev runs the messaging sidecar locally so the SDK flow is identical to production. Enable platform adapters per project under dev.interfaces.messaging.adapters in astropods.yml:
Open the bundled playground at http://localhost:8080 to drive your agent end-to-end without touching Slack. See the package spec for the full dev.interfaces.messaging schema.
Worked examples
Slack
The Slack adapter forwards five flavours of event:
Status updates translate to Slack’s assistant.threads.setStatus. Suggested prompts translate to assistant.threads.setSuggestedPrompts. CardAttachment ships Block Kit JSON straight through.
A Block Kit card with an action button:
When the user clicks View logs, you’ll get a PlatformFeedback.buttonClick event with buttonId: "view_logs" and value: "deploy-4837".
Web (playground / browser chat)
Every message arrives with platform: "web" and eventKind: 'EVENT_KIND_DM'. The two web-specific concerns are audio input and session-scoped conversations (one conversationId per browser tab).
The bundled playground emits WEBM_OPUS at 48 kHz from MediaRecorder. Firefox emits OGG_OPUS. audioEncodingToFiletype(config.encoding) picks the right STT filetype.
Cross-platform agent
In practice a single agent serves both. The only platform-specific code is whether you open a Slack thread:
Exported symbols
The full proto source lives in modules/messaging/proto/astro/messaging/v1/ — service.proto, message.proto, response.proto, feedback.proto, audio.proto, config.proto.