@mastra/core@1.30.0

mastra-ai/mastra@mastra/core@1.30.0May 1, 2026by PaulieScanlon

AI Summary

This release introduces Durable Agents with resumable streams and workflow-backed execution strategies (Evented and Inngest). It also adds pluggable PubSub and Cache infrastructure, improves A2A streaming artifacts, and reduces observability noise by default.

Key Highlights

  • Durable Agents + Resumable Streams (crash/disconnect resilient execution)
  • Workflow-backed “Durable Execution” (Evented + Inngest strategies)
  • Pluggable PubSub + Cache infrastructure (Redis/Upstash-ready)
  • Improved A2A streaming artifacts in @mastra/server
  • Observability noise/volume reduction by default

New Features

  • DurableAgent, EventedAgent, and InngestAgent classes
  • observe() method for resuming streams with offset
  • streamUntilIdle() method for background task integration
  • resumeStream() endpoint and client method
  • A2A streaming artifact improvements
  • CloudExporter filtering of model chunk spans

Full Release Notes

## Highlights

### Durable Agents + Resumable Streams (crash/disconnect resilient execution)
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 })`.

### Workflow-backed “Durable Execution” (Evented + Inngest strategies)
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.

### Pluggable PubSub + Cache infrastructure (Redis/Upstash-ready)
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.

### Improved A2A streaming artifacts in `@mastra/server`
A2A streaming now emits incremental artifact updates during the full agent stream while still preserving final structured output artifacts.

### Observability noise/volume reduction by default
Cloud observability uploads now filter model chunk spans by default and raise the default observability log level to `warn`, reducing data volume and chatter.

### Breaking Changes
- None called out in this changelog.

## Changelog

### [@mastra/core@1.30.0](https://github.com/mastra-ai/mastra/blob/@mastra/core@1.30.0/packages/core/CHANGELOG.md)
#### Minor Changes

- Add durable agents with resumable streams ([#12557](https://github.com/mastra-ai/mastra/pull/12557))

  Durable agents make agent execution resilient to disconnections, crashes, and long-running operations.

  ### The Problem

  Standard agent streaming has two fragility points:
  1. **Connection drops** - If a client disconnects mid-stream (network blip, browser refresh, mobile app backgrounded), all subsequent events are lost. The client has no way to "catch up" on what they missed.
  2. **Long-running operations** - Agent loops with tool calls can take minutes. Holding an HTTP connection open that long is unreliable. If the server restarts or the connection times out, the work is lost.

  ### The Solution

  **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.

  ### Usage

  Wrap any existing `Agent` with durability using factory functions:

  ```typescript
  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 |

  ### Resumable Streams

  ```typescript
  // 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
  ```

  ### PubSub and Cache

  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):**

  ```typescript
  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):**

  ```typescript
  const durableAgent = createDurableAgent({
    agent,
    cache: new RedisServerCache({ url: 'redis://...' }),
    pubsub: new RedisPubSub({ url: 'redis://...' }),
  });
  ```

  **Disable caching (streams won't be resumable):**

  ```typescript
  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.

  ### Class Hierarchy
  - `DurableAgent` extends `Agent` - base class with resumable streams
  - `EventedAgent` extends `DurableAgent` - fire-and-forget execution
  - `InngestAgent` extends `DurableAgent` - Inngest-powered execution

#### Patch Changes

- Fixed 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](https://github.com/mastra-ai/mastra/pull/15952))

- Update provider registry and model documentation with latest models and providers ([`d587199`](https://github.com/mastra-ai/mastra/commit/d5871993c0371bde2b0717d6b47194755baa1443))

- Fix MCP client support in the agent editor: ([#15945](https://github.com/mastra-ai/mastra/pull/15945))
  - MCP client form dirty state: Save button now enables after adding/removing MCP clients
  - MCP tool name matching: Both bare and namespaced tool names are matched correctly
  - Auth token forwarding: Token from cookie or header is forwarded to auth-protected MCP servers
  - String interpolation: Request context variables in system prompts now resolve correctly

### [@mastra/client-js@1.15.2](https://github.com/mastra-ai/mastra/blob/@mastra/client-js@1.15.2/client-sdks/client-js/CHANGELOG.md)
#### Patch Changes

- Remove incorrect deprecation markers from `getTask()` and `cancelTask()` in the Mastra A2A client. ([#15941](https://github.com/mastra-ai/mastra/pull/15941))

- Add durable agents with resumable streams ([#12557](https://github.com/mastra-ai/mastra/pull/12557))

  Durable agents make agent execution resilient to disconnections, crashes, and long-running operations.

  ### The Problem

  Standard agent streaming has two fragility points:
  1. **Connection drops** - If a client disconnects mid-stream (network blip, browser refresh, mobile app backgrounded), all subsequent events are lost. The client has no way to "catch up" on what they missed.
  2. **Long-running operations** - Agent loops with tool calls can take minutes. Holding an HTTP connection open that long is unreliable. If the server restarts or the connection times out, the work is lost.

  ### The Solution

  **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.

  ### Usage

  Wrap any existing `Agent` with durability using factory functions:

  ```typescript
  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 |

  ### Resumable Streams

  ```typescript
  // 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
  ```

  ### PubSub and Cache

  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):**

  ```typescript
  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):**

  ```typescript
  const durableAgent = createDurableAgent({
    agent,
    cache: new RedisServerCache({ url: 'redis://...' }),
    pubsub: new RedisPubSub({ url: 'redis://...' }),
  });
  ```

  **Disable caching (streams won't be resumable):**

  ```typescript
  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.

  ### Class Hierarchy
  - `DurableAgent` extends `Agent` - base class with resumable streams
  - `EventedAgent` extends `DurableAgent` - fire-and-forget execution
  - `InngestAgent` extends `DurableAgent` - Inngest-powered execution

### [@mastra/editor@0.7.22](https://github.com/mastra-ai/mastra/blob/@mastra/editor@0.7.22/packages/editor/CHANGELOG.md)
#### Patch Changes

- Fix MCP client support in the agent editor: ([#15945](https://github.com/mastra-ai/mastra/pull/15945))
  - MCP client form dirty state: Save button now enables after adding/removing MCP clients
  - MCP tool name matching: Both bare and namespaced tool names are matched correctly
  - Auth token forwarding: Token from cookie or header is forwarded to auth-protected MCP servers
  - String interpolation: Request context variables in system prompts now resolve correctly

### [@mastra/hono@1.4.10](https://github.com/mastra-ai/mastra/blob/@mastra/hono@1.4.10/server-adapters/hono/CHANGELOG.md)
#### Patch Changes

- Fixed 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](https://github.com/mastra-ai/mastra/pull/15952))

### [@mastra/inngest@1.3.0](https://github.com/mastra-ai/mastra/blob/@mastra/inngest@1.3.0/workflows/inngest/CHANGELOG.md)
#### Minor Changes

- Add durable agents with resumable streams ([#12557](https://github.com/mastra-ai/mastra/pull/12557))

  Durable agents make agent execution resilient to disconnections, crashes, and long-running operations.

  ### The Problem

  Standard agent streaming has two fragility points:
  1. **Connection drops** - If a client disconnects mid-stream (network blip, browser refresh, mobile app backgrounded), all subsequent events are lost. The client has no way to "catch up" on what they missed.
  2. **Long-running operations** - Agent loops with tool calls can take minutes. Holding an HTTP connection open that long is unreliable. If the server restarts or the connection times out, the work is lost.

  ### The Solution

  **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.

  ### Usage

  Wrap any existing `Agent` with durability using factory functions:

  ```typescript
  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 |

  ### Resumable Streams

  ```typescript
  // 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
  ```

  ### PubSub and Cache

  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):**

  ```typescript
  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):**

  ```typescript
  const durableAgent = createDurableAgent({
    agent,
    cache: new RedisServerCache({ url: 'redis://...' }),
    pubsub: new RedisPubSub({ url: 'redis://...' }),
  });
  ```

  **Disable caching (streams won't be resumable):**

  ```typescript
  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.

  ### Class Hierarchy
  - `DurableAgent` extends `Agent` - base class with resumable streams
  - `EventedAgent` extends `DurableAgent` - fire-and-forget execution
  - `InngestAgent` extends `DurableAgent` - Inngest-powered execution

- Update peer dependencies to match core package version bump (1.0.5) ([#12557](https://github.com/mastra-ai/mastra/pull/12557))

#### Patch Changes

### [@mastra/memory@1.17.4](https://github.com/mastra-ai/mastra/blob/@mastra/memory@1.17.4/packages/memory/CHANGELOG.md)
#### Patch Changes

- Fixed idle timeout and provider-change observation activations blocking on in-progress reflection buffering. These triggers now return immediately, letting the background reflection complete asynchronously. ([#15937](https://github.com/mastra-ai/mastra/pull/15937))

### [@mastra/observability@1.10.3](https://github.com/mastra-ai/mastra/blob/@mastra/observability@1.10.3/observability/mastra/CHANGELOG.md)
#### Patch Changes

- Add durable agents with resumable streams ([#12557](https://github.com/mastra-ai/mastra/pull/12557))

  Durable agents make agent execution resilient to disconnections, crashes, and long-running operations.

  ### The Problem

  Standard agent streaming has two fragility points:
  1. **Connection drops** - If a client disconnects mid-stream (network blip, browser refresh, mobile app backgrounded), all subsequent events are lost. The client has no way to "catch up" on what they missed.
  2. **Long-running operations** - Agent loops with tool calls can take minutes. Holding an HTTP connection open that long is unreliable. If the server restarts or the connection times out, the work is lost.

  ### The Solution

  **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.

  ### Usage

  Wrap any existing `Agent` with durability using factory functions:

  ```typescript
  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 |

  ### Resumable Streams

  ```typescript
  // 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
  ```

  ### PubSub and Cache

  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):**

  ```typescript
  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):**

  ```typescript
  const durableAgent = createDurableAgent({
    agent,
    cache: new RedisServerCache({ url: 'redis://...' }),
    pubsub: new RedisPubSub({ url: 'redis://...' }),
  });
  ```

  **Disable caching (streams won't be resumable):**

  ```typescript
  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.

  ### Class Hierarchy
  - `DurableAgent` extends `Agent` - base class with resumable streams
  - `EventedAgent` extends `DurableAgent` - fire-and-forget execution
  - `InngestAgent` extends `DurableAgent` - Inngest-powered execution

- Reduced default cloud observability volume by filtering model chunk spans from CloudExporter uploads by default and raising the default observability log level to `warn`. ([#15815](https://github.com/mastra-ai/mastra/pull/15815))

### [@mastra/playground-ui@24.0.2](https://github.com/mastra-ai/mastra/blob/@mastra/playground-ui@24.0.2/packages/playground-ui/CHANGELOG.md)
#### Patch Changes

- 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](https://github.com/mastra-ai/mastra/pull/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](https://github.com/mastra-ai/mastra/pull/15959))

- Refined the DataPanel loading state with a smaller spinner and tightened layout for a less prominent appearance. ([#15965](https://github.com/mastra-ai/mastra/pull/15965))

### [@mastra/redis@1.1.0](https://github.com/mastra-ai/mastra/blob/@mastra/redis@1.1.0/stores/redis/CHANGELOG.md)
#### Minor Changes

- Update peer dependencies to match core package version bump (1.0.5) ([#12557](https://github.com/mastra-ai/mastra/pull/12557))

#### Patch Changes

- Add durable agents with resumable streams ([#12557](https://github.com/mastra-ai/mastra/pull/12557))

  Durable agents make agent execution resilient to disconnections, crashes, and long-running operations.

  ### The Problem

  Standard agent streaming has two fragility points:
  1. **Connection drops** - If a client disconnects mid-stream (network blip, browser refresh, mobile app backgrounded), all subsequent events are lost. The client has no way to "catch up" on what they missed.
  2. **Long-running operations** - Agent loops with tool calls can take minutes. Holding an HTTP connection open that long is unreliable. If the server restarts or the connection times out, the work is lost.

  ### The Solution

  **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.

  ### Usage

  Wrap any existing `Agent` with durability using factory functions:

  ```typescript
  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 |

  ### Resumable Streams

  ```typescript
  // 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
  ```

  ### PubSub and Cache

  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):**

  ```typescript
  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):**

  ```typescript
  const durableAgent = createDurableAgent({
    agent,
    cache: new RedisServerCache({ url: 'redis://...' }),
    pubsub: new RedisPubSub({ url: 'redis://...' }),
  });
  ```

  **Disable caching (streams won't be resumable):**

  ```typescript
  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.

  ### Class Hierarchy
  - `DurableAgent` extends `Agent` - base class with resumable streams
  - `EventedAgent` extends `DurableAgent` - fire-and-forget execution
  - `InngestAgent` extends `DurableAgent` - Inngest-powered execution

### [@mastra/server@1.30.0](https://github.com/mastra-ai/mastra/blob/@mastra/server@1.30.0/packages/server/CHANGELOG.md)
#### Minor Changes

- Update peer dependencies to match core package version bump (1.0.5) ([#12557](https://github.com/mastra-ai/mastra/pull/12557))

#### Patch Changes

- Fixed 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](https://github.com/mastra-ai/mastra/pull/15952))

- Fix MCP client support in the agent editor: ([#15945](https://github.com/mastra-ai/mastra/pull/15945))
  - MCP client form dirty state: Save button now enables after adding/removing MCP clients
  - MCP tool name matching: Both bare and namespaced tool names are matched correctly
  - Auth token forwarding: Token from cookie or header is forwarded to auth-protected MCP servers
  - String interpolation: Request context variables in system prompts now resolve correctly

- Add durable agents with resumable streams ([#12557](https://github.com/mastra-ai/mastra/pull/12557))

  Durable agents make agent execution resilient to disconnections, crashes, and long-running operations.

  ### The Problem

  Standard agent streaming has two fragility points:
  1. **Connection drops** - If a client disconnects mid-stream (network blip, browser refresh, mobile app backgrounded), all subsequent events are lost. The client has no way to "catch up" on what they missed.
  2. **Long-running operations** - Agent loops with tool calls can take minutes. Holding an HTTP connection open that long is unreliable. If the server restarts or the connection times out, the work is lost.

  ### The Solution

  **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.

  ### Usage

  Wrap any existing `Agent` with durability using factory functions:

  ```typescript
  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 |

  ### Resumable Streams

  ```typescript
  // 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
  ```

  ### PubSub and Cache

  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):**

  ```typescript
  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):**

  ```typescript
  const durableAgent = createDurableAgent({
    agent,
    cache: new RedisServerCache({ url: 'redis://...' }),
    pubsub: new RedisPubSub({ url: 'redis://...' }),
  });
  ```

  **Disable caching (streams won't be resumable):**

  ```typescript
  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.

  ### Class Hierarchy
  - `DurableAgent` extends `Agent` - base class with resumable streams
  - `EventedAgent` extends `DurableAgent` - fire-and-forget execution
  - `InngestAgent` extends `DurableAgent` - Inngest-powered execution

- Fix A2A streaming to emit incremental artifact updates from the agent full stream while preserving final structured output artifacts. ([#15941](https://github.com/mastra-ai/mastra/pull/15941))

### [@mastra/upstash@1.1.0](https://github.com/mastra-ai/mastra/blob/@mastra/upstash@1.1.0/stores/upstash/CHANGELOG.md)
#### Minor Changes

- Update peer dependencies to match core package version bump (1.0.5) ([#12557](https://github.com/mastra-ai/mastra/pull/12557))

#### Patch Changes

- Add durable agents with resumable streams ([#12557](https://github.com/mastra-ai/mastra/pull/12557))

  Durable agents make agent execution resilient to disconnections, crashes, and long-running operations.

  ### The Problem

  Standard agent streaming has two fragility points:
  1. **Connection drops** - If a client disconnects mid-stream (network blip, browser refresh, mobile app backgrounded), all subsequent events are lost. The client has no way to "catch up" on what they missed.
  2. **Long-running operations** - Agent loops with tool calls can take minutes. Holding an HTTP connection open that long is unreliable. If the server restarts or the connection times out, the work is lost.

  ### The Solution

  **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.

  ### Usage

  Wrap any existing `Agent` with durability using factory functions:

  ```typescript
  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 |

  ### Resumable Streams

  ```typescript
  // 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
  ```

  ### PubSub and Cache

  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):**

  ```typescript
  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):**

  ```typescript
  const durableAgent = createDurableAgent({
    agent,
    cache: new RedisServerCache({ url: 'redis://...' }),
    pubsub: new RedisPubSub({ url: 'redis://...' }),
  });
  ```

  **Disable caching (streams won't be resumable):**

  ```typescript
  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.

  ### Class Hierarchy
  - `DurableAgent` extends `Agent` - base class with resumable streams
  - `EventedAgent` extends `DurableAgent` - fire-and-forget execution
  - `InngestAgent` extends `DurableAgent` - Inngest-powered execution

### Other updated packages

The following packages were updated with dependency changes only:

- [@mastra/agent-builder@1.0.32](https://github.com/mastra-ai/mastra/blob/@mastra/agent-builder@1.0.32/packages/agent-builder/CHANGELOG.md)
- [@mastra/arize@1.0.21](https://github.com/mastra-ai/mastra/blob/@mastra/arize@1.0.21/observability/arize/CHANGELOG.md)
- [@mastra/arthur@0.2.7](https://github.com/mastra-ai/mastra/blob/@mastra/arthur@0.2.7/observability/arthur/CHANGELOG.md)
- [@mastra/braintrust@1.0.21](https://github.com/mastra-ai/mastra/blob/@mastra/braintrust@1.0.21/observability/braintrust/CHANGELOG.md)
- [@mastra/datadog@1.0.21](https://github.com/mastra-ai/mastra/blob/@mastra/datadog@1.0.21/observability/datadog/CHANGELOG.md)
- [@mastra/deployer@1.30.0](https://github.com/mastra-ai/mastra/blob/@mastra/deployer@1.30.0/packages/deployer/CHANGELOG.md)
- [@mastra/deployer-cloud@1.30.0](https://github.com/mastra-ai/mastra/blob/@mastra/deployer-cloud@1.30.0/deployers/cloud/CHANGELOG.md)
- [@mastra/deployer-cloudflare@1.1.29](https://github.com/mastra-ai/mastra/blob/@mastra/deployer-cloudflare@1.1.29/deployers/cloudflare/CHANGELOG.md)
- [@mastra/deployer-netlify@1.1.5](https://github.com/mastra-ai/mastra/blob/@mastra/deployer-netlify@1.1.5/deployers/netlify/CHANGELOG.md)
- [@mastra/deployer-vercel@1.1.23](https://github.com/mastra-ai/mastra/blob/@mastra/deployer-vercel@1.1.23/deployers/vercel/CHANGELOG.md)
- [@mastra/express@1.3.15](https://github.com/mastra-ai/mastra/blob/@mastra/express@1.3.15/server-adapters/express/CHANGELOG.md)
- [@mastra/fastify@1.3.15](https://github.com/mastra-ai/mastra/blob/@mastra/fastify@1.3.15/server-adapters/fastify/CHANGELOG.md)
- [@mastra/koa@1.4.15](https://github.com/mastra-ai/mastra/blob/@mastra/koa@1.4.15/server-adapters/koa/CHANGELOG.md)
- [@mastra/laminar@1.0.20](https://github.com/mastra-ai/mastra/blob/@mastra/laminar@1.0.20/observability/laminar/CHANGELOG.md)
- [@mastra/langfuse@1.2.3](https://github.com/mastra-ai/mastra/blob/@mastra/langfuse@1.2.3/observability/langfuse/CHANGELOG.md)
- [@mastra/langsmith@1.1.18](https://github.com/mastra-ai/mastra/blob/@mastra/langsmith@1.1.18/observability/langsmith/CHANGELOG.md)
- [@mastra/longmemeval@1.0.34](https://github.com/mastra-ai/mastra/blob/@mastra/longmemeval@1.0.34/explorations/longmemeval/CHANGELOG.md)
- [@mastra/mcp-docs-server@1.1.31](https://github.com/mastra-ai/mastra/blob/@mastra/mcp-docs-server@1.1.31/packages/mcp-docs-server/CHANGELOG.md)
- [@mastra/opencode@0.0.31](https://github.com/mastra-ai/mastra/blob/@mastra/opencode@0.0.31/integrations/opencode/CHANGELOG.md)
- [@mastra/otel-bridge@1.0.20](https://github.com/mastra-ai/mastra/blob/@mastra/otel-bridge@1.0.20/observability/otel-bridge/CHANGELOG.md)
- [@mastra/otel-exporter@1.0.20](https://github.com/mastra-ai/mastra/blob/@mastra/otel-exporter@1.0.20/observability/otel-exporter/CHANGELOG.md)
- [@mastra/posthog@1.0.21](https://github.com/mastra-ai/mastra/blob/@mastra/posthog@1.0.21/observability/posthog/CHANGELOG.md)
- [@mastra/react@0.2.32](https://github.com/mastra-ai/mastra/blob/@mastra/react@0.2.32/client-sdks/react/CHANGELOG.md)
- [@mastra/sentry@1.0.20](https://github.com/mastra-ai/mastra/blob/@mastra/sentry@1.0.20/observability/sentry/CHANGELOG.md)