April 30, 2026
New DurableAgent support lets agent streams resume after client disconnects and continue through server crashes/restarts by caching stream events and enabling reconnection via observe(runId, { offset }).
Agents can now run outside the HTTP request using workflow execution (createEventedAgent for built-in evented engine, createInngestAgent for Inngest), enabling reliable long-running tool loops while clients subscribe to progress.
Durable streaming is backed by a PubSub + ServerCache layer (defaults: EventEmitterPubSub + InMemoryServerCache), with recommended production configs using Redis-backed implementations so any instance can serve reconnect/replay.
@mastra/serverA2A streaming now emits incremental artifact updates during the full agent stream while still preserving final structured output artifacts.
Cloud observability uploads now filter model chunk spans by default and raise the default observability log level to warn, reducing data volume and chatter.
Add durable agents with resumable streams (#12557)
Durable agents make agent execution resilient to disconnections, crashes, and long-running operations.
Standard agent streaming has two fragility points:
Resumable streams solve connection drops. Every event is cached with a sequential index. If a client disconnects at event 5, they can reconnect and request events starting from index 6. They receive cached events immediately, then continue with live events as they arrive.
Durable execution solves long-running operations. Instead of executing the agent loop directly in the HTTP request, execution happens in a workflow engine (built-in evented engine or Inngest). The HTTP request just subscribes to events. If the connection drops, execution continues. The client can reconnect anytime to observe progress.
Wrap any existing Agent with durability using factory functions:
import { Agent } from '@mastra/core/agent';
import { createDurableAgent } from '@mastra/core/agent/durable';
const agent = new Agent({
id: 'my-agent',
model: openai('gpt-4'),
instructions: 'You are helpful',
});
const durableAgent = createDurableAgent({ agent });
Factory functions for different execution strategies:
| Factory | Execution | Use Case |
|---|---|---|
createDurableAgent({ agent }) | Local, synchronous | Development, simple deployments |
createEventedAgent({ agent }) | Fire-and-forget via workflow engine | Long-running operations |
createInngestAgent({ agent, inngest }) | Inngest-powered | Production, distributed systems |
// Start streaming
const { runId, output } = await durableAgent.stream('Analyze this data...');
// Client disconnects at event 5...
// Reconnect and resume from where we left off
const { output: resumed } = await durableAgent.observe(runId, { offset: 6 });
// Receives events 6, 7, 8... from cache, then continues with live events
Durable agents use two infrastructure components:
| Component | Purpose | Default |
|---|---|---|
| PubSub | Real-time event delivery during streaming | EventEmitterPubSub |
| Cache | Stores events for replay on reconnection | InMemoryServerCache |
When stream() is called, events flow through pubsub in real-time. The cache stores each event with a sequential index. When observe() is called, missed events replay from cache before continuing with live events.
Configure via Mastra instance (recommended):
const mastra = new Mastra({
cache: new RedisServerCache({ url: 'redis://...' }),
pubsub: new RedisPubSub({ url: 'redis://...' }),
agents: {
// Inherits cache and pubsub from Mastra
myAgent: createDurableAgent({ agent }),
},
});
Configure per-agent (overrides Mastra):
const durableAgent = createDurableAgent({
agent,
cache: new RedisServerCache({ url: 'redis://...' }),
pubsub: new RedisPubSub({ url: 'redis://...' }),
});
Disable caching (streams won't be resumable):
const durableAgent = createDurableAgent({ agent, cache: false });
For single-instance deployments, the defaults work fine. For multi-instance deployments (load balancer, horizontal scaling), use Redis-backed implementations so any instance can serve reconnection requests.
DurableAgent extends Agent - base class with resumable streamsEventedAgent extends DurableAgent - fire-and-forget executionInngestAgent extends DurableAgent - Inngest-powered executionFixed a regression in 1.29.0 where configuring an agent with channel adapters (e.g. channels.adapters.slack) caused server startup to crash with a "Custom API route ... must not start with /api" error. The custom-route prefix validation now skips framework-generated webhook routes. (#15952)
Update provider registry and model documentation with latest models and providers (d587199)
Fix MCP client support in the agent editor: (#15945)
Remove incorrect deprecation markers from getTask() and cancelTask() in the Mastra A2A client. (#15941)
Add durable agents with resumable streams (#12557)
Durable agents make agent execution resilient to disconnections, crashes, and long-running operations.
Standard agent streaming has two fragility points:
Resumable streams solve connection drops. Every event is cached with a sequential index. If a client disconnects at event 5, they can reconnect and request events starting from index 6. They receive cached events immediately, then continue with live events as they arrive.
Durable execution solves long-running operations. Instead of executing the agent loop directly in the HTTP request, execution happens in a workflow engine (built-in evented engine or Inngest). The HTTP request just subscribes to events. If the connection drops, execution continues. The client can reconnect anytime to observe progress.
Wrap any existing Agent with durability using factory functions:
import { Agent } from '@mastra/core/agent';
import { createDurableAgent } from '@mastra/core/agent/durable';
const agent = new Agent({
id: 'my-agent',
model: openai('gpt-4'),
instructions: 'You are helpful',
});
const durableAgent = createDurableAgent({ agent });
Factory functions for different execution strategies:
| Factory | Execution | Use Case |
|---|---|---|
createDurableAgent({ agent }) | Local, synchronous | Development, simple deployments |
createEventedAgent({ agent }) | Fire-and-forget via workflow engine | Long-running operations |
createInngestAgent({ agent, inngest }) | Inngest-powered | Production, distributed systems |
// Start streaming
const { runId, output } = await durableAgent.stream('Analyze this data...');
// Client disconnects at event 5...
// Reconnect and resume from where we left off
const { output: resumed } = await durableAgent.observe(runId, { offset: 6 });
// Receives events 6, 7, 8... from cache, then continues with live events
Durable agents use two infrastructure components:
| Component | Purpose | Default |
|---|---|---|
| PubSub | Real-time event delivery during streaming | EventEmitterPubSub |
| Cache | Stores events for replay on reconnection | InMemoryServerCache |
When stream() is called, events flow through pubsub in real-time. The cache stores each event with a sequential index. When observe() is called, missed events replay from cache before continuing with live events.
Configure via Mastra instance (recommended):
const mastra = new Mastra({
cache: new RedisServerCache({ url: 'redis://...' }),
pubsub: new RedisPubSub({ url: 'redis://...' }),
agents: {
// Inherits cache and pubsub from Mastra
myAgent: createDurableAgent({ agent }),
},
});
Configure per-agent (overrides Mastra):
const durableAgent = createDurableAgent({
agent,
cache: new RedisServerCache({ url: 'redis://...' }),
pubsub: new RedisPubSub({ url: 'redis://...' }),
});
Disable caching (streams won't be resumable):
const durableAgent = createDurableAgent({ agent, cache: false });
For single-instance deployments, the defaults work fine. For multi-instance deployments (load balancer, horizontal scaling), use Redis-backed implementations so any instance can serve reconnection requests.
DurableAgent extends Agent - base class with resumable streamsEventedAgent extends DurableAgent - fire-and-forget executionInngestAgent extends DurableAgent - Inngest-powered executionchannels.adapters.slack) caused server startup to crash with a "Custom API route ... must not start with /api" error. The custom-route prefix validation now skips framework-generated webhook routes. (#15952)Add durable agents with resumable streams (#12557)
Durable agents make agent execution resilient to disconnections, crashes, and long-running operations.
Standard agent streaming has two fragility points:
Resumable streams solve connection drops. Every event is cached with a sequential index. If a client disconnects at event 5, they can reconnect and request events starting from index 6. They receive cached events immediately, then continue with live events as they arrive.
Durable execution solves long-running operations. Instead of executing the agent loop directly in the HTTP request, execution happens in a workflow engine (built-in evented engine or Inngest). The HTTP request just subscribes to events. If the connection drops, execution continues. The client can reconnect anytime to observe progress.
Wrap any existing Agent with durability using factory functions:
import { Agent } from '@mastra/core/agent';
import { createDurableAgent } from '@mastra/core/agent/durable';
const agent = new Agent({
id: 'my-agent',
model: openai('gpt-4'),
instructions: 'You are helpful',
});
const durableAgent = createDurableAgent({ agent });
Factory functions for different execution strategies:
| Factory | Execution | Use Case |
|---|---|---|
createDurableAgent({ agent }) | Local, synchronous | Development, simple deployments |
createEventedAgent({ agent }) | Fire-and-forget via workflow engine | Long-running operations |
createInngestAgent({ agent, inngest }) | Inngest-powered | Production, distributed systems |
// Start streaming
const { runId, output } = await durableAgent.stream('Analyze this data...');
// Client disconnects at event 5...
// Reconnect and resume from where we left off
const { output: resumed } = await durableAgent.observe(runId, { offset: 6 });
// Receives events 6, 7, 8... from cache, then continues with live events
Durable agents use two infrastructure components:
| Component | Purpose | Default |
|---|---|---|
| PubSub | Real-time event delivery during streaming | EventEmitterPubSub |
| Cache | Stores events for replay on reconnection | InMemoryServerCache |
When stream() is called, events flow through pubsub in real-time. The cache stores each event with a sequential index. When observe() is called, missed events replay from cache before continuing with live events.
Configure via Mastra instance (recommended):
const mastra = new Mastra({
cache: new RedisServerCache({ url: 'redis://...' }),
pubsub: new RedisPubSub({ url: 'redis://...' }),
agents: {
// Inherits cache and pubsub from Mastra
myAgent: createDurableAgent({ agent }),
},
});
Configure per-agent (overrides Mastra):
const durableAgent = createDurableAgent({
agent,
cache: new RedisServerCache({ url: 'redis://...' }),
pubsub: new RedisPubSub({ url: 'redis://...' }),
});
Disable caching (streams won't be resumable):
const durableAgent = createDurableAgent({ agent, cache: false });
For single-instance deployments, the defaults work fine. For multi-instance deployments (load balancer, horizontal scaling), use Redis-backed implementations so any instance can serve reconnection requests.
DurableAgent extends Agent - base class with resumable streamsEventedAgent extends DurableAgent - fire-and-forget executionInngestAgent extends DurableAgent - Inngest-powered executionUpdate peer dependencies to match core package version bump (1.0.5) (#12557)
Add durable agents with resumable streams (#12557)
Durable agents make agent execution resilient to disconnections, crashes, and long-running operations.
Standard agent streaming has two fragility points:
Resumable streams solve connection drops. Every event is cached with a sequential index. If a client disconnects at event 5, they can reconnect and request events starting from index 6. They receive cached events immediately, then continue with live events as they arrive.
Durable execution solves long-running operations. Instead of executing the agent loop directly in the HTTP request, execution happens in a workflow engine (built-in evented engine or Inngest). The HTTP request just subscribes to events. If the connection drops, execution continues. The client can reconnect anytime to observe progress.
Wrap any existing Agent with durability using factory functions:
import { Agent } from '@mastra/core/agent';
import { createDurableAgent } from '@mastra/core/agent/durable';
const agent = new Agent({
id: 'my-agent',
model: openai('gpt-4'),
instructions: 'You are helpful',
});
const durableAgent = createDurableAgent({ agent });
Factory functions for different execution strategies:
| Factory | Execution | Use Case |
|---|---|---|
createDurableAgent({ agent }) | Local, synchronous | Development, simple deployments |
createEventedAgent({ agent }) | Fire-and-forget via workflow engine | Long-running operations |
createInngestAgent({ agent, inngest }) | Inngest-powered | Production, distributed systems |
// Start streaming
const { runId, output } = await durableAgent.stream('Analyze this data...');
// Client disconnects at event 5...
// Reconnect and resume from where we left off
const { output: resumed } = await durableAgent.observe(runId, { offset: 6 });
// Receives events 6, 7, 8... from cache, then continues with live events
Durable agents use two infrastructure components:
| Component | Purpose | Default |
|---|---|---|
| PubSub | Real-time event delivery during streaming | EventEmitterPubSub |
| Cache | Stores events for replay on reconnection | InMemoryServerCache |
When stream() is called, events flow through pubsub in real-time. The cache stores each event with a sequential index. When observe() is called, missed events replay from cache before continuing with live events.
Configure via Mastra instance (recommended):
const mastra = new Mastra({
cache: new RedisServerCache({ url: 'redis://...' }),
pubsub: new RedisPubSub({ url: 'redis://...' }),
agents: {
// Inherits cache and pubsub from Mastra
myAgent: createDurableAgent({ agent }),
},
});
Configure per-agent (overrides Mastra):
const durableAgent = createDurableAgent({
agent,
cache: new RedisServerCache({ url: 'redis://...' }),
pubsub: new RedisPubSub({ url: 'redis://...' }),
});
Disable caching (streams won't be resumable):
const durableAgent = createDurableAgent({ agent, cache: false });
For single-instance deployments, the defaults work fine. For multi-instance deployments (load balancer, horizontal scaling), use Redis-backed implementations so any instance can serve reconnection requests.
DurableAgent extends Agent - base class with resumable streamsEventedAgent extends DurableAgent - fire-and-forget executionInngestAgent extends DurableAgent - Inngest-powered executionReduced default cloud observability volume by filtering model chunk spans from CloudExporter uploads by default and raising the default observability log level to warn. (#15815)
Updated the look and motion of Dialog. The surface is now lighter and translucent with a subtle backdrop blur, the typography is tighter, and the open/close animation feels snappier. SideDialog and AlertDialog pick up the refined ambient shadow as well, since they share the same shadow style. (#15958)
Polished DataList visuals: removed the trailing "No more data to load" message and dropped the bottom border on the last row for a cleaner end-of-list appearance. (#15959)
Refined the DataPanel loading state with a smaller spinner and tightened layout for a less prominent appearance. (#15965)
Add durable agents with resumable streams (#12557)
Durable agents make agent execution resilient to disconnections, crashes, and long-running operations.
Standard agent streaming has two fragility points:
Resumable streams solve connection drops. Every event is cached with a sequential index. If a client disconnects at event 5, they can reconnect and request events starting from index 6. They receive cached events immediately, then continue with live events as they arrive.
Durable execution solves long-running operations. Instead of executing the agent loop directly in the HTTP request, execution happens in a workflow engine (built-in evented engine or Inngest). The HTTP request just subscribes to events. If the connection drops, execution continues. The client can reconnect anytime to observe progress.
Wrap any existing Agent with durability using factory functions:
import { Agent } from '@mastra/core/agent';
import { createDurableAgent } from '@mastra/core/agent/durable';
const agent = new Agent({
id: 'my-agent',
model: openai('gpt-4'),
instructions: 'You are helpful',
});
const durableAgent = createDurableAgent({ agent });
Factory functions for different execution strategies:
| Factory | Execution | Use Case |
|---|---|---|
createDurableAgent({ agent }) | Local, synchronous | Development, simple deployments |
createEventedAgent({ agent }) | Fire-and-forget via workflow engine | Long-running operations |
createInngestAgent({ agent, inngest }) | Inngest-powered | Production, distributed systems |
// Start streaming
const { runId, output } = await durableAgent.stream('Analyze this data...');
// Client disconnects at event 5...
// Reconnect and resume from where we left off
const { output: resumed } = await durableAgent.observe(runId, { offset: 6 });
// Receives events 6, 7, 8... from cache, then continues with live events
Durable agents use two infrastructure components:
| Component | Purpose | Default |
|---|---|---|
| PubSub | Real-time event delivery during streaming | EventEmitterPubSub |
| Cache | Stores events for replay on reconnection | InMemoryServerCache |
When stream() is called, events flow through pubsub in real-time. The cache stores each event with a sequential index. When observe() is called, missed events replay from cache before continuing with live events.
Configure via Mastra instance (recommended):
const mastra = new Mastra({
cache: new RedisServerCache({ url: 'redis://...' }),
pubsub: new RedisPubSub({ url: 'redis://...' }),
agents: {
// Inherits cache and pubsub from Mastra
myAgent: createDurableAgent({ agent }),
},
});
Configure per-agent (overrides Mastra):
const durableAgent = createDurableAgent({
agent,
cache: new RedisServerCache({ url: 'redis://...' }),
pubsub: new RedisPubSub({ url: 'redis://...' }),
});
Disable caching (streams won't be resumable):
const durableAgent = createDurableAgent({ agent, cache: false });
For single-instance deployments, the defaults work fine. For multi-instance deployments (load balancer, horizontal scaling), use Redis-backed implementations so any instance can serve reconnection requests.
DurableAgent extends Agent - base class with resumable streamsEventedAgent extends DurableAgent - fire-and-forget executionInngestAgent extends DurableAgent - Inngest-powered executionFixed a regression in 1.29.0 where configuring an agent with channel adapters (e.g. channels.adapters.slack) caused server startup to crash with a "Custom API route ... must not start with /api" error. The custom-route prefix validation now skips framework-generated webhook routes. (#15952)
Fix MCP client support in the agent editor: (#15945)
Add durable agents with resumable streams (#12557)
Durable agents make agent execution resilient to disconnections, crashes, and long-running operations.
Standard agent streaming has two fragility points:
Resumable streams solve connection drops. Every event is cached with a sequential index. If a client disconnects at event 5, they can reconnect and request events starting from index 6. They receive cached events immediately, then continue with live events as they arrive.
Durable execution solves long-running operations. Instead of executing the agent loop directly in the HTTP request, execution happens in a workflow engine (built-in evented engine or Inngest). The HTTP request just subscribes to events. If the connection drops, execution continues. The client can reconnect anytime to observe progress.
Wrap any existing Agent with durability using factory functions:
import { Agent } from '@mastra/core/agent';
import { createDurableAgent } from '@mastra/core/agent/durable';
const agent = new Agent({
id: 'my-agent',
model: openai('gpt-4'),
instructions: 'You are helpful',
});
const durableAgent = createDurableAgent({ agent });
Factory functions for different execution strategies:
| Factory | Execution | Use Case |
|---|---|---|
createDurableAgent({ agent }) | Local, synchronous | Development, simple deployments |
createEventedAgent({ agent }) | Fire-and-forget via workflow engine | Long-running operations |
createInngestAgent({ agent, inngest }) | Inngest-powered | Production, distributed systems |
// Start streaming
const { runId, output } = await durableAgent.stream('Analyze this data...');
// Client disconnects at event 5...
// Reconnect and resume from where we left off
const { output: resumed } = await durableAgent.observe(runId, { offset: 6 });
// Receives events 6, 7, 8... from cache, then continues with live events
Durable agents use two infrastructure components:
| Component | Purpose | Default |
|---|---|---|
| PubSub | Real-time event delivery during streaming | EventEmitterPubSub |
| Cache | Stores events for replay on reconnection | InMemoryServerCache |
When stream() is called, events flow through pubsub in real-time. The cache stores each event with a sequential index. When observe() is called, missed events replay from cache before continuing with live events.
Configure via Mastra instance (recommended):
const mastra = new Mastra({
cache: new RedisServerCache({ url: 'redis://...' }),
pubsub: new RedisPubSub({ url: 'redis://...' }),
agents: {
// Inherits cache and pubsub from Mastra
myAgent: createDurableAgent({ agent }),
},
});
Configure per-agent (overrides Mastra):
const durableAgent = createDurableAgent({
agent,
cache: new RedisServerCache({ url: 'redis://...' }),
pubsub: new RedisPubSub({ url: 'redis://...' }),
});
Disable caching (streams won't be resumable):
const durableAgent = createDurableAgent({ agent, cache: false });
For single-instance deployments, the defaults work fine. For multi-instance deployments (load balancer, horizontal scaling), use Redis-backed implementations so any instance can serve reconnection requests.
DurableAgent extends Agent - base class with resumable streamsEventedAgent extends DurableAgent - fire-and-forget executionInngestAgent extends DurableAgent - Inngest-powered executionFix A2A streaming to emit incremental artifact updates from the agent full stream while preserving final structured output artifacts. (#15941)
Add durable agents with resumable streams (#12557)
Durable agents make agent execution resilient to disconnections, crashes, and long-running operations.
Standard agent streaming has two fragility points:
Resumable streams solve connection drops. Every event is cached with a sequential index. If a client disconnects at event 5, they can reconnect and request events starting from index 6. They receive cached events immediately, then continue with live events as they arrive.
Durable execution solves long-running operations. Instead of executing the agent loop directly in the HTTP request, execution happens in a workflow engine (built-in evented engine or Inngest). The HTTP request just subscribes to events. If the connection drops, execution continues. The client can reconnect anytime to observe progress.
Wrap any existing Agent with durability using factory functions:
import { Agent } from '@mastra/core/agent';
import { createDurableAgent } from '@mastra/core/agent/durable';
const agent = new Agent({
id: 'my-agent',
model: openai('gpt-4'),
instructions: 'You are helpful',
});
const durableAgent = createDurableAgent({ agent });
Factory functions for different execution strategies:
| Factory | Execution | Use Case |
|---|---|---|
createDurableAgent({ agent }) | Local, synchronous | Development, simple deployments |
createEventedAgent({ agent }) | Fire-and-forget via workflow engine | Long-running operations |
createInngestAgent({ agent, inngest }) | Inngest-powered | Production, distributed systems |
// Start streaming
const { runId, output } = await durableAgent.stream('Analyze this data...');
// Client disconnects at event 5...
// Reconnect and resume from where we left off
const { output: resumed } = await durableAgent.observe(runId, { offset: 6 });
// Receives events 6, 7, 8... from cache, then continues with live events
Durable agents use two infrastructure components:
| Component | Purpose | Default |
|---|---|---|
| PubSub | Real-time event delivery during streaming | EventEmitterPubSub |
| Cache | Stores events for replay on reconnection | InMemoryServerCache |
When stream() is called, events flow through pubsub in real-time. The cache stores each event with a sequential index. When observe() is called, missed events replay from cache before continuing with live events.
Configure via Mastra instance (recommended):
const mastra = new Mastra({
cache: new RedisServerCache({ url: 'redis://...' }),
pubsub: new RedisPubSub({ url: 'redis://...' }),
agents: {
// Inherits cache and pubsub from Mastra
myAgent: createDurableAgent({ agent }),
},
});
Configure per-agent (overrides Mastra):
const durableAgent = createDurableAgent({
agent,
cache: new RedisServerCache({ url: 'redis://...' }),
pubsub: new RedisPubSub({ url: 'redis://...' }),
});
Disable caching (streams won't be resumable):
const durableAgent = createDurableAgent({ agent, cache: false });
For single-instance deployments, the defaults work fine. For multi-instance deployments (load balancer, horizontal scaling), use Redis-backed implementations so any instance can serve reconnection requests.
DurableAgent extends Agent - base class with resumable streamsEventedAgent extends DurableAgent - fire-and-forget executionInngestAgent extends DurableAgent - Inngest-powered executionThe following packages were updated with dependency changes only:
Fetched May 1, 2026
Highlights Azure Blob Storage workspace + blob store ( ) New adds an Azure Blob Storage provider ( ) and an content-addressable store for s…
Highlights AI Gateway Tool Support in the Agentic Loop now supports AI Gateway tools (e.g. ) as provider-executed tools: it infers , merges…