createInngestAgent()
Breaking changes may occur without a major version bump until the API is stable.
createInngestAgent() wraps an existing Agent with Inngest-powered durable execution. Like createDurableAgent(), it streams events over PubSub and supports resumable streams, but runs the agentic loop on Inngest's execution engine instead of in-process. Use it when a run must survive process restarts or run in a distributed environment.
For in-process durable execution, use createDurableAgent(). For fire-and-forget execution on the built-in workflow engine, use createEventedAgent().
Usage exampleUsage example的直接链接
Set up the Inngest client, wrap an agent, register it with Mastra, and expose the Inngest serve endpoint:
import { Mastra } from '@mastra/core'
import { Agent } from '@mastra/core/agent'
import { createInngestAgent, serve as inngestServe } from '@mastra/inngest'
import { Inngest } from 'inngest'
const inngest = new Inngest({ id: 'my-app' })
const agent = new Agent({
id: 'my-agent',
name: 'My Agent',
instructions: 'You are a helpful assistant',
model: 'openai/gpt-5.6-sol',
})
const durableAgent = createInngestAgent({ agent, inngest })
export const mastra = new Mastra({
agents: { myAgent: durableAgent },
server: {
apiRoutes: [
{
path: '/inngest/api',
method: 'ALL',
createHandler: async ({ mastra }) => inngestServe({ mastra, inngest }),
},
],
},
})
Stream a response and read the result:
const { output, runId, cleanup } = await durableAgent.stream('Hello!')
const text = await output.text
cleanup()
createInngestAgent(options)createinngestagentoptions的直接链接
Wraps an Agent with Inngest-powered durable execution and resumable streams.
import { createInngestAgent } from '@mastra/inngest'
const durableAgent = createInngestAgent({ agent, inngest })
Returns: InngestAgent
ParametersParameters的直接链接
agent:
InngestAgent (e.g., listTools() and getMemory()) delegate to this agent via a Proxy.inngest:
id?:
name?:
pubsub?:
InngestPubSub uses Inngest Realtime, which works across processes.cache?:
CachingPubSub. If omitted, the agent inherits the cache from the Mastra instance.mastra?:
shouldPersistSnapshot?:
createDurableAgent, but ignored: Inngest's step memoization and replay own durability, so InngestAgent always persists suspended snapshots only (for human-in-the-loop resume). A warning is logged if set.InngestAgent interfaceinngestagent-interface的直接链接
The object returned by createInngestAgent(). It provides the durable execution methods below. Any property or method not explicitly defined (e.g., listTools() and getMemory()) is forwarded to the underlying agent via a Proxy. Thread APIs such as sendSignal(), sendStateSignal(), sendNotificationSignal(), and subscribeToThread() are forwarded too, but a signal that wakes an idle thread starts the run through the durable stream().
PropertiesProperties的直接链接
id:
name:
agent:
inngest:
cache:
pubsub:
MethodsMethods的直接链接
ExecutionExecution的直接链接
stream(messages, options?)streammessages-options的直接链接
Streams a response using Inngest's durable execution engine. The workflow is triggered via an Inngest event after the PubSub subscription is established.
const { output, runId, cleanup } = await durableAgent.stream('Hello!', {
onChunk: chunk => console.log(chunk),
onFinish: result => console.log('done', result),
})
const text = await output.text
cleanup()
Returns: Promise<InngestAgentStreamResult>
resume(runId, resumeData, options?)resumerunid-resumedata-options的直接链接
Resumes a suspended Inngest run, for example after a tool approval. Loads the workflow snapshot from storage and finds the suspended step before sending a resume event to Inngest.
const { output, cleanup } = await durableAgent.resume(
runId,
{
approved: true,
},
{ threadId: 'thread-1', resourceId: 'user-1' },
)
await output.text
cleanup()
The third argument accepts threadId and resourceId in addition to the lifecycle callbacks:
threadId?:
resourceId?:
onChunk?:
onStepFinish?:
onFinish?:
onError?:
onSuspended?:
Returns: Promise<InngestAgentStreamResult>
generate(messages, options?)generatemessages-options的直接链接
Runs a response on Inngest's durable execution engine and resolves with a single FullOutput. If the run suspends, generate() resolves with finishReason: 'suspended'. The runId option is optional. If you omit it, generate() creates a run ID and returns it in result.runId. Continue the run with resumeGenerate(). Use stream() with onSuspended when the caller needs a suspension callback.
const result = await durableAgent.generate('Delete the old records', {
requireToolApproval: true,
})
result.runId // Generated automatically
result.finishReason // 'suspended' when approval is required
Returns: Promise<FullOutput<TOutput>>
resumeGenerate(resumeData, options)resumegenerateresumedata-options的直接链接
Resumes a suspended generate() run and resolves with a single FullOutput. Pass the run ID as options.runId, the same as Agent.resumeGenerate(). The older resumeGenerate(runId, resumeData, options?) order still works but is deprecated.
if (!result.runId) {
throw new Error('Run ID is missing')
}
const resumedResult = await durableAgent.resumeGenerate({ approved: true }, { runId: result.runId })
Returns: Promise<FullOutput<TOutput>>
observe(runId, options?)observerunid-options的直接链接
Reconnects to an existing run, replaying cached events before delivering live ones. Use this after a network disconnection. Pass offset to start replay from a known position.
const { output, cleanup } = await durableAgent.observe(runId, {
offset: 0,
onChunk: chunk => console.log(chunk),
})
await output.text
The result from observe() doesn't include threadId or resourceId.
Returns: Promise<Omit<InngestAgentStreamResult, 'threadId' | 'resourceId'>>
The cleanup() returned by observe() destroys the run's registry entries and cached events. Only call it when you are done with the run. If the run is suspended and you intend to resume later, don't call cleanup().
prepare(messages, options?)preparemessages-options的直接链接
Prepares a run for durable execution without triggering it. Returns the serialized workflow input that can be used to manually trigger the Inngest workflow event.
const { runId, messageId, workflowInput, threadId, resourceId } = await durableAgent.prepare(
'Summarize the document',
{
memory: { threadId: 'thread-1', resourceId: 'user-1' },
},
)
Returns:
interface PrepareResult {
runId: string
messageId: string
workflowInput: any
threadId?: string
resourceId?: string
}
IntrospectionIntrospection的直接链接
isInngestAgent(obj)isinngestagentobj的直接链接
Type guard that checks whether an object is an InngestAgent.
import { isInngestAgent } from '@mastra/inngest'
if (isInngestAgent(agent)) {
// agent is InngestAgent
}
Returns: boolean
Stream optionsStream options的直接链接
stream() accepts an InngestAgentStreamOptions object. It supports the same agent execution options as DurableAgent.stream(), plus lifecycle callbacks.
runId?:
resume() or observe().instructions?:
context?:
memory?:
requestContext?:
maxSteps?:
toolsets?:
clientTools?:
toolChoice?:
modelSettings?:
requireToolApproval?:
autoResumeSuspendedTools?:
resume() call.closeOnSuspend?:
true, close the stream when the run suspends (for example for tool approval) so fullStream, text, and getFullOutput() resolve at the suspension boundary instead of staying open, matching non-durable Agent.stream(). Useful for callers such as AG-UI or A2A that need the stream to end. Defaults to false, which keeps the stream open across suspension so a later resume can continue streaming on the same reader. resume()/resumeStream() always return a fresh stream.toolCallConcurrency?:
includeRawChunks?:
maxProcessorRetries?:
untilIdle?:
true for the default 5-minute idle timeout, or { maxIdleMs } to customise.onChunk?:
onStepFinish?:
onFinish?:
onError?:
onSuspended?:
observe() accepts the lifecycle callbacks (onChunk, onStepFinish, onFinish, onError, onSuspended) plus an offset to control where replay starts.
InngestAgentStreamResultinngestagentstreamresult的直接链接
The object returned by stream() and resume(). The observe() method returns the same shape but omits threadId and resourceId.
interface InngestAgentStreamResult<OUTPUT = undefined> {
output: MastraModelOutput<OUTPUT>
readonly fullStream: ReadableStream<any>
runId: string
threadId?: string
resourceId?: string
cleanup: () => void
}
output:
output.text for the full text, or consume output.fullStream.fullStream:
output.fullStream.runId:
resume() or observe() to reconnect.threadId?:
resourceId?:
cleanup:
Event size limitEvent size limit的直接链接
Inngest Realtime caps each message at about 512 KB. The default InngestPubSub keeps every stream event under 480 KB:
- An oversized
finishevent is sent withoutoutput.steps. The final text, usage, and finish reason still arrive, butsteps,toolCalls, andtoolResultson the stream result are empty for that run. - Any other oversized event, such as a
tool-resultchunk carrying a large tool result, is replaced with adata-oversized-eventchunk. Itsdataholds the originaleventType,chunkType,bytes, andlimit. The chunk is transient, so it isn't saved to memory.
Both cases log a warning. Only the live stream is reduced: messages saved to memory and the run's workflow snapshot keep the full data.
To avoid the limit:
- Return small tool results, such as an ID or summary, and fetch large data separately.
- Read full results from memory or the workflow run after the stream finishes.
- Pass a
pubsubwithout the limit, such asRedisStreamsPubSub:
import { createInngestAgent } from '@mastra/inngest'
import { RedisStreamsPubSub } from '@mastra/redis-streams'
const durableAgent = createInngestAgent({
agent,
inngest,
pubsub: new RedisStreamsPubSub({ url: 'redis://localhost:6379' }),
})
Serving Inngest functionsServing Inngest functions的直接链接
The @mastra/inngest package provides serve() and createServe() to register Inngest workflow functions with your HTTP framework.
serve(options)serveoptions的直接链接
Serves Mastra workflows with Hono (the default framework). Collects all Inngest-backed workflows from Mastra and registers them as Inngest functions.
import { serve } from '@mastra/inngest'
app.use('/inngest/api', async c => {
return serve({ mastra, inngest })(c)
})
createServe(adapter)createserveadapter的直接链接
Factory that accepts any Inngest serve adapter (inngest/express, inngest/fastify, inngest/next, etc.) and returns a serve function for that framework.
import { createServe } from '@mastra/inngest'
import { serve } from 'inngest/express'
const serveExpress = createServe(serve)
app.use('/inngest/api', serveExpress({ mastra, inngest }))
import { createServe } from '@mastra/inngest'
import { serve } from 'inngest/next'
const serveNext = createServe(serve)
export const { GET, POST, PUT } = serveNext({ mastra, inngest })