@mastra/core
Version:
Mastra is a framework for building AI-powered applications and agents with a modern TypeScript stack.
422 lines • 17.2 kB
TypeScript
import type { MastraServerCache } from '../../cache/base.js';
import type { PubSub } from '../../events/pubsub.js';
import type { Mastra } from '../../mastra/index.js';
import type { MastraModelOutput } from '../../stream/base/output.js';
import type { ChunkType } from '../../stream/types.js';
import { Agent } from '../agent.js';
import type { AgentExecutionOptions } from '../agent.types.js';
import type { MessageListInput } from '../message-list/index.js';
import type { ToolsInput } from '../types.js';
import { ExtendedRunRegistry } from './run-registry.js';
import type { AgentFinishEventData, AgentStepFinishEventData, AgentSuspendedEventData, DurableAgenticWorkflowInput } from './types.js';
import { createDurableAgenticWorkflow } from './workflows/index.js';
/**
* Options for DurableAgent.stream()
*/
export interface DurableAgentStreamOptions<OUTPUT = undefined> {
/** Custom instructions that override the agent's default instructions for this execution */
instructions?: AgentExecutionOptions<OUTPUT>['instructions'];
/** Additional context messages to provide to the agent */
context?: AgentExecutionOptions<OUTPUT>['context'];
/** Memory configuration for conversation persistence and retrieval */
memory?: AgentExecutionOptions<OUTPUT>['memory'];
/** Unique identifier for this execution run */
runId?: string;
/** Request Context containing dynamic configuration and state */
requestContext?: AgentExecutionOptions<OUTPUT>['requestContext'];
/** Maximum number of steps to run */
maxSteps?: number;
/** Additional tool sets that can be used for this execution */
toolsets?: AgentExecutionOptions<OUTPUT>['toolsets'];
/** Client-side tools available during execution */
clientTools?: AgentExecutionOptions<OUTPUT>['clientTools'];
/** Tool selection strategy */
toolChoice?: AgentExecutionOptions<OUTPUT>['toolChoice'];
/** Tool names enabled for this execution */
activeTools?: AgentExecutionOptions<OUTPUT>['activeTools'];
/** Model-specific settings like temperature */
modelSettings?: AgentExecutionOptions<OUTPUT>['modelSettings'];
/** Require approval for all tool calls */
requireToolApproval?: boolean;
/** Automatically resume suspended tools */
autoResumeSuspendedTools?: boolean;
/** Maximum number of tool calls to execute concurrently */
toolCallConcurrency?: number;
/** Whether to include raw chunks in the stream output */
includeRawChunks?: boolean;
/** Maximum processor retries */
maxProcessorRetries?: number;
/** Structured output configuration */
structuredOutput?: AgentExecutionOptions<OUTPUT>['structuredOutput'];
/** Version overrides for sub-agent delegation */
versions?: AgentExecutionOptions<OUTPUT>['versions'];
/** Callback when chunk is received */
onChunk?: (chunk: ChunkType<OUTPUT>) => void | Promise<void>;
/** Callback when step finishes */
onStepFinish?: (result: AgentStepFinishEventData) => void | Promise<void>;
/** Callback when execution finishes */
onFinish?: (result: AgentFinishEventData) => void | Promise<void>;
/** Callback on error */
onError?: (error: Error) => void | Promise<void>;
/** Callback when workflow suspends (e.g., for tool approval) */
onSuspended?: (data: AgentSuspendedEventData) => void | Promise<void>;
/** When true, the in-loop background task check step skips waiting (streamUntilIdle sets this) */
_skipBgTaskWait?: boolean;
}
/**
* Result from DurableAgent.stream()
*/
export interface DurableAgentStreamResult<OUTPUT = undefined> {
/** The streaming output */
output: MastraModelOutput<OUTPUT>;
/** The full stream - delegates to output.fullStream for server compatibility */
readonly fullStream: ReadableStream<any>;
/** The unique run ID for this execution */
runId: string;
/** Thread ID if using memory */
threadId?: string;
/** Resource ID if using memory */
resourceId?: string;
/** Cleanup function to call when done (unsubscribes from pubsub) */
cleanup: () => void;
}
/**
* Configuration for DurableAgent - wraps an existing Agent with durable execution
*/
export interface DurableAgentConfig<TAgentId extends string = string, TTools extends ToolsInput = ToolsInput, TOutput = undefined> {
/**
* The Agent to wrap with durable execution capabilities.
* All agent methods (getModel, listTools, etc.) delegate to this agent.
*/
agent: Agent<TAgentId, TTools, TOutput>;
/**
* Optional ID override. Defaults to agent.id.
*/
id?: TAgentId;
/**
* Optional name override. Defaults to agent.name.
*/
name?: string;
/**
* PubSub instance for streaming events.
* Optional - if not provided, defaults to EventEmitterPubSub.
*/
pubsub?: PubSub;
/**
* Cache instance for storing stream events.
* Enables resumable streams - clients can disconnect and reconnect
* without missing events.
*
* - If not provided: Inherits from Mastra instance, or uses InMemoryServerCache
* - If provided: Uses the provided cache backend (e.g., Redis)
* - If set to `false`: Disables caching (streams are not resumable)
*/
cache?: MastraServerCache | false;
/**
* Maximum steps for the agentic loop.
* Defaults to the workflow default if not specified.
*/
maxSteps?: number;
/**
* Timeout in milliseconds before automatic cleanup of registry entries
* after a stream finishes or errors. This provides a grace period for
* late observers to access the stream.
*
* Defaults to 30000 (30 seconds).
* Set to 0 to disable auto-cleanup (manual cleanup() required).
*/
cleanupTimeoutMs?: number;
}
/**
* DurableAgent wraps an existing Agent with durable execution capabilities.
*
* Key features:
* 1. Resumable streams - clients can disconnect and reconnect without missing events
* 2. Serializable workflow inputs - works with durable execution engines
* 3. PubSub-based streaming - events flow through pubsub for distribution
*
* DurableAgent extends Agent, delegating most methods to the wrapped agent.
* It overrides stream() to use durable execution with the agentic workflow.
*
* Subclasses (EventedAgent, InngestAgent) override executeWorkflow() to
* customize how the workflow is executed.
*
* @example
* ```typescript
* import { Agent } from '@mastra/core/agent';
* import { DurableAgent } from '@mastra/core/agent/durable';
*
* const agent = new Agent({
* id: 'my-agent',
* instructions: 'You are a helpful assistant',
* model: openai('gpt-4'),
* });
*
* const durableAgent = new DurableAgent({ agent });
*
* const { output, runId, cleanup } = await durableAgent.stream('Hello!');
* const text = await output.text;
* cleanup();
* ```
*/
export declare class DurableAgent<TAgentId extends string = string, TTools extends ToolsInput = ToolsInput, TOutput = undefined> extends Agent<TAgentId, TTools, TOutput> {
#private;
/**
* Create a new DurableAgent that wraps an existing Agent
*/
constructor(config: DurableAgentConfig<TAgentId, TTools, TOutput>);
/**
* Get the resolved cache instance.
* Lazily initialized to allow inheriting from Mastra.
*/
get cache(): MastraServerCache | null;
/**
* Get the PubSub instance.
* Returns CachingPubSub if caching is enabled, otherwise the inner pubsub.
*/
get pubsub(): PubSub;
/**
* Get the wrapped agent instance.
*/
get agent(): Agent<TAgentId, TTools, TOutput>;
/**
* Get the run registry (for testing and advanced usage)
*/
get runRegistry(): ExtendedRunRegistry;
/**
* Get the max steps configured for this agent
*/
get maxSteps(): number | undefined;
/**
* Get the cleanup timeout in milliseconds.
* Returns 0 if auto-cleanup is disabled.
*/
get cleanupTimeoutMs(): number;
getModel(options?: any): import("../../_types/@internal_ai-sdk-v4/dist/index.js").LanguageModelV1 | import("..").MastraLanguageModel | Promise<import("../../_types/@internal_ai-sdk-v4/dist/index.js").LanguageModelV1 | import("..").MastraLanguageModel>;
getInstructions(options?: any): import("../../llm").SystemMessage | Promise<import("../../llm").SystemMessage>;
listTools(options?: any): TTools | Promise<TTools>;
getMemory(): Promise<import("../../memory").MastraMemory | undefined>;
getVoice(): Promise<import("../../voice").MastraVoice<unknown, unknown, unknown, ToolsInput, import("../../voice").VoiceEventMap, unknown>>;
/**
* Get the PubSub instance for use by subclasses.
* @internal
*/
protected get pubsubInternal(): PubSub;
/**
* Get the run registry for use by subclasses.
* @internal
*/
protected get runRegistryInternal(): ExtendedRunRegistry;
/**
* Execute the durable workflow.
*
* Subclasses override this method to customize how the workflow is executed:
* - DurableAgent (this): Runs the workflow directly via createRun + start
* - EventedAgent: Uses run.startAsync() for fire-and-forget execution
* - InngestAgent: Uses inngest.send() to trigger Inngest function
*
* @param runId - The unique run ID
* @param workflowInput - The serialized workflow input
* @internal
*/
protected executeWorkflow(runId: string, workflowInput: DurableAgenticWorkflowInput): Promise<void>;
/**
* Create the durable workflow for this agent.
*
* Subclasses can override this method to use a different workflow implementation:
* - DurableAgent (this): Uses createDurableAgenticWorkflow()
* - InngestAgent: Uses createInngestDurableAgenticWorkflow()
*
* @internal
*/
protected createWorkflow(): ReturnType<typeof createDurableAgenticWorkflow>;
/**
* Emit an error event to pubsub.
*
* @param runId - The run ID
* @param error - The error to emit
* @internal
*/
protected emitError(runId: string, error: Error): Promise<void>;
/**
* Stream a response from the agent using durable execution.
*/
stream(messages: MessageListInput, options?: DurableAgentStreamOptions<TOutput>): Promise<DurableAgentStreamResult<TOutput>>;
/**
* Resume a suspended workflow execution.
*/
resume(runId: string, resumeData: unknown, options?: {
onChunk?: (chunk: ChunkType<TOutput>) => void | Promise<void>;
onStepFinish?: (result: AgentStepFinishEventData) => void | Promise<void>;
onFinish?: (result: AgentFinishEventData) => void | Promise<void>;
onError?: (error: Error) => void | Promise<void>;
onSuspended?: (data: AgentSuspendedEventData) => void | Promise<void>;
}): Promise<DurableAgentStreamResult<TOutput>>;
/**
* Observe an existing stream.
* Use this to reconnect to a stream after a network disconnection.
*
* **Warning:** The returned `cleanup()` function destroys the run's registry
* entries and cached PubSub events. Only call it when you are done with the
* run entirely. If the workflow is suspended and you intend to resume later,
* do not call cleanup — let the auto-cleanup timer handle it after
* FINISH/ERROR. Auto-cleanup does not fire on SUSPENDED events.
*/
observe(runId: string, options?: {
offset?: number;
onChunk?: (chunk: ChunkType<TOutput>) => void | Promise<void>;
onStepFinish?: (result: AgentStepFinishEventData) => void | Promise<void>;
onFinish?: (result: AgentFinishEventData) => void | Promise<void>;
onError?: (error: Error) => void | Promise<void>;
onSuspended?: (data: AgentSuspendedEventData) => void | Promise<void>;
}): Promise<Omit<DurableAgentStreamResult<TOutput>, 'runId'> & {
runId: string;
}>;
/**
* Get the workflow instance for direct execution.
* Lazily creates the workflow and registers Mastra on it (needed for
* getAgentById in execution steps).
*/
getWorkflow(): import("../../workflows").Workflow<import("../../workflows").DefaultEngineType, import("../../workflows").Step<string, unknown, unknown, unknown, unknown, unknown, any, unknown>[], "durable-agentic-loop", unknown, {
__workflowKind: "durable-agent";
runId: string;
agentId: string;
messageListState: any;
toolsMetadata: any[];
modelConfig: {
provider: string;
modelId: string;
specificationVersion?: string | undefined;
settings?: Record<string, any> | undefined;
providerOptions?: Record<string, any> | undefined;
};
options: any;
state: any;
messageId: string;
agentName?: string | undefined;
modelList?: {
id: string;
config: {
provider: string;
modelId: string;
specificationVersion?: string | undefined;
originalConfig?: string | Record<string, any> | undefined;
providerOptions?: Record<string, any> | undefined;
};
maxRetries: number;
enabled: boolean;
}[] | undefined;
}, {
messageListState: any;
messageId: string;
stepResult: any;
output: {
usage: any;
steps: any[];
text?: string | undefined;
};
state: any;
}, {
messageListState: any;
messageId: string;
stepResult: any;
output: {
usage: any;
steps: any[];
text?: string | undefined;
};
state: any;
}, unknown>;
/**
* Stream until all background tasks complete and the agent is idle.
* Mirrors the regular Agent's streamUntilIdle but adapted for durable execution.
*/
streamUntilIdle<OUTPUT = TOutput>(messages: MessageListInput, streamOptions?: DurableAgentStreamOptions<OUTPUT> & {
maxIdleMs?: number;
}): Promise<DurableAgentStreamResult<OUTPUT>>;
/**
* Prepare for durable execution without starting it.
*/
prepare(messages: MessageListInput, options?: AgentExecutionOptions<TOutput>): Promise<{
runId: string;
messageId: string;
workflowInput: DurableAgenticWorkflowInput;
registryEntry: import("./types").RunRegistryEntry;
threadId: string | undefined;
resourceId: string | undefined;
}>;
/**
* Get the durable workflows required by this agent.
* Called by Mastra during agent registration.
* @internal
*/
getDurableWorkflows(): import("../../workflows").Workflow<import("../../workflows").DefaultEngineType, import("../../workflows").Step<string, unknown, unknown, unknown, unknown, unknown, any, unknown>[], "durable-agentic-loop", unknown, {
__workflowKind: "durable-agent";
runId: string;
agentId: string;
messageListState: any;
toolsMetadata: any[];
modelConfig: {
provider: string;
modelId: string;
specificationVersion?: string | undefined;
settings?: Record<string, any> | undefined;
providerOptions?: Record<string, any> | undefined;
};
options: any;
state: any;
messageId: string;
agentName?: string | undefined;
modelList?: {
id: string;
config: {
provider: string;
modelId: string;
specificationVersion?: string | undefined;
originalConfig?: string | Record<string, any> | undefined;
providerOptions?: Record<string, any> | undefined;
};
maxRetries: number;
enabled: boolean;
}[] | undefined;
}, {
messageListState: any;
messageId: string;
stepResult: any;
output: {
usage: any;
steps: any[];
text?: string | undefined;
};
state: any;
}, {
messageListState: any;
messageId: string;
stepResult: any;
output: {
usage: any;
steps: any[];
text?: string | undefined;
};
state: any;
}, unknown>[];
/**
* Set the Mastra instance.
* Called by the durable agent registration path in addAgent().
* Delegates to __registerMastra so the pubsub wiring and agent
* registration happen regardless of which entry point is called first.
* @internal
*/
__setMastra(mastra: Mastra): void;
/**
* Register the Mastra instance.
* Called by Mastra during agent registration (normal Agent path).
*
* Also wires mastra.pubsub as the inner pubsub (if the user didn't provide
* a custom one), so that the OBSERVE_AGENT_STREAM_ROUTE handler can subscribe
* to the same PubSub instance that this agent publishes to.
* @internal
*/
__registerMastra(mastra: Mastra): void;
}
//# sourceMappingURL=durable-agent.d.ts.map