@s2-dev/mastra-pubsub.
The package provides an S2PubSub implementation for
Mastra durable agents.
Each durable-agent topic maps to an S2 stream. When S2PubSub appends an
event, the S2 sequence number becomes the event’s Mastra index. Live delivery
and replay therefore use the same index, which lets Mastra replay and
deduplicate events without a separate counter.

Install
@mastra/core 1.45 or later
in the 1.x release line. @mastra/core is a peer dependency.
Create a basin with Create Stream on Append and Create Stream on Read
enabled. These settings let S2PubSub create a run stream when it first writes
or reads the topic.
You can create the basin in the dashboard or with
the CLI:
Configure Mastra
Create anS2PubSub and pass it to the Mastra instance that registers your
durable agent:
src/mastra/index.ts
src/mastra/agents/research-agent.ts
S2PubSub persists topics beginning with agent.stream.; other topics only
use the live-delivery transport.
Reconnect to a run
Starting a durable-agent stream returns arunId. Keep that ID where a
reconnecting client can retrieve it.
observe with the same
runId:
offset when the caller already has part of the stream. The offset is
the first event index to replay, so use 42 if index 41 was the last event
processed:
How persistence works
S2PubSub extends Mastra’s CachingPubSub and replaces its in-memory history
operations for persisted topics:
publishserializes the event and appends it to the topic’s S2 stream. It adds the returnedseqNumas the eventindex, then sends the event through the inner pubsub for live delivery.getHistoryreads the S2 stream from the requested offset and restores each record’sseqNumas its eventindex.clearTopicdeletes the corresponding S2 stream.
S2PubSub logs the error and still sends the event through
the inner pubsub without an index. That event is available to live subscribers
but cannot be replayed from S2.
Cleanup and retention
When Mastra cleans up a run, it callsclearTopic, which deletes that run’s S2
stream. Do not treat these streams as permanent run history.
If a process exits before cleanup, its stream can remain. You can apply an
age-based retention policy and
delete_on_empty in the basin’s default stream configuration to remove these
orphaned streams. Keep the retention period longer than the maximum run time
and reconnection window you support.
Options
new S2PubSub(config, options?)
S2 Lite
Install the S2 SDK for its environment helper:S2_ACCOUNT_ENDPOINT and S2_BASIN_ENDPOINT,
then pass the parsed endpoints to S2PubSub:
Example
The package repository includes a runnable example adapted from Mastra’s durable-agents example:examples/durable-agents.
