Anchorage API reference
    Preparing search index...

    Class FlowsafeDurableAgent<TAgentId, TTools, TOutput>

    A DurableAgent whose loop runs through RunnerRuntime rather than the base createRun + run.start. Construct via createFlowsafeDurableAgent so the loop workflow is registered on the runtime.

    Type Parameters

    • TAgentId extends string = string
    • TTools extends ToolsInput = ToolsInput
    • TOutput = undefined

    Hierarchy

    Index

    Constructors

    Properties

    "[RUNTIME_DRIVEN_AGENT]": true

    The runtime-driven brand the thread-Durable-Object signal wake requires (see RUNTIME_DRIVEN_AGENT). A unique symbol field, so it cannot collide with an inherited property and a plain Agent never carries it.

    Methods

    • Refuse the network tool-approval resume. It is a one-line forward to FlowsafeDurableAgent.resumeNetwork; blocking it here closes the same door from the side a tool-approval caller reaches for.

      Parameters

      • _options: Omit<MultiPrimitiveExecutionOptions, "runId"> & {}

      Returns Promise<never>

    • Refuse Mastra's own tool-approval resume. Tool approval in FlowSafe is a decided ApprovalRecord resumed through the approval-decision path, which mints the leg's connector grant; approveToolCall() funnels into resumeStream() -> resume() and mints nothing.

      Parameters

      • _options: {} & Record<string, any>

      Returns Promise<never>

    • The 1.53.0 generate-shaped tool-approval pair. They funnel into resumeGenerate() -> resume(), so they are the same entry point wearing a different return type.

      Signature caveat for both halves: the base method is GENERIC in its OUTPUT type, which Parameters<> cannot carry, so the parameter type below is hand-written rather than derived. Re-check it against the base on every peer bump — nothing here fails if core changes the shape.

      Type Parameters

      • OUTPUT = undefined

      Parameters

      • _options: {} & Partial<ObservabilityContext> & (
            [NonNullable<OUTPUT>] extends [never] ? {} : OUTPUT extends {} ? {} : {}
        ) & { runId: string; toolCallId?: string }

      Returns Promise<never>

    • The decline half of FlowsafeDurableAgent.approveToolCallGenerate, including its hand-written-signature caveat.

      Type Parameters

      • OUTPUT = undefined

      Parameters

      • _options: {} & Partial<ObservabilityContext> & (
            [NonNullable<OUTPUT>] extends [never] ? {} : OUTPUT extends {} ? {} : {}
        ) & { runId: string; toolCallId?: string }

      Returns Promise<never>

    • Refuse core's terminal snapshot cleanup. Its only call sites are the base executeWorkflow (overridden here), the blocked resume() and the blocked recover(), so nothing this class drives reaches it; blocking keeps the snapshot rows — which deployment-scoped retention purge owns — from being dropped out from under that owner by a future internal caller.

      Note what this override buys beyond that call-site audit: the member inventory in durable-agent-surface.test.ts sees a NEW member, never a new core call site on an EXISTING one. So the override is the standing guard — it converts core's best-effort cleanup into a throw the moment a future release calls it on a path FlowSafe drives. None does at 1.53.0.

      Parameters

      • _runId: string

      Returns Promise<never>

    • Drive the durable-agentic-loop through RunnerRuntime instead of the base createRun + run.start. stream()/generate() have already parked the non-serializables (model/tools/messageList) on the in-process run registry keyed by this runId, so the loop the runtime starts resolves them in-isolate while the runtime mints the per-leg grant context. The runId guard here is defense in depth — the public boundary (stream/generate) already enforced the host-owned run-ID rule; this catches any future internal caller.

      Parameters

      • runId: string
      • workflowInput: DurableAgenticWorkflowInput

      Returns Promise<void>

    • Refuse the AI SDK v4 legacy execution path. generateLegacy() forwards into AgentLegacyHandler, which converts and RUNS the agent's tools while bypassing RunnerRuntime entirely, mints its own run id when the caller omits one, and skips requireAgentExecutionFGA — the authorization gate every SUPPORTED entry point calls, so this would run the agent without it. (The network family skips that gate too; neither is unique in doing so.) It persists no workflow run state, which is why it is refused on those two grounds rather than as a re-drive.

      Signature caveat: overloaded and generic in OUTPUT on the base, so this signature is hand-derived and must be re-checked on every peer bump.

      Parameters

      • _messages: MessageListInput
      • Optional_args: AgentGenerateOptions<undefined, any> & { output?: undefined; experimental_output?: any; model?: DynamicArgument<MastraModelConfig> | undefined; }

      Returns Promise<never>

    • Refuse core's recovery discovery API. listActiveRuns() enumerates listWorkflowRuns({ workflowName: 'durable-agentic-loop', status: 'running' }) narrowed by agentId plus the optional threadId/resourceId filters the CALLER supplies, so it never consults the host topology's per-principal run-ownership checks (resourceAccess().owner('run', …)) and hands the caller run ids, thread ids and resource ids for runs it does not own. Host run listing is the topology's job, where ownership is checked.

      Parameters

      • Optional_options: DurableAgentListActiveRunsOptions

      Returns Promise<never>

    • Refuse the Agent-level analogue of FlowsafeDurableAgent.listActiveRuns. listSuspendedRuns() reads the workflows store directly — listWorkflowRuns({ workflowName: 'agentic-loop', status: 'suspended' }) — and narrows by agentId plus the optional threadId/resourceId filters the CALLER supplies, the same scoping listActiveRuns() applies. Same ground too: an unfiltered call returns run, thread and resource ids across every principal that shares the agent. It is the one direct data-returning discovery member the base Agent surface adds; the other additions funnel through this.resumeStream() and so fail closed on that override.

      Parameters

      • Optional_options: AgentListSuspendedRunsOptions

      Returns Promise<never>

    • Refuse the multi-agent network start. network() does not touch the durable-agentic-loop at all: it compiles a SEPARATE workflow and drives it with createRun + run.stream on the default engine, so the whole collaboration — every sub-agent leg and every tool call inside it — runs with no per-leg grant context, no snapshot provenance and no RunSummary. It also mints options.runId || mastra.generateId() || randomUUID(), the exact unowned fallback this runner forbids: the host mints every run id.

      Signature caveat: the base method is OVERLOADED and generic in OUTPUT, so Parameters<> sees only the LAST overload and is too narrow to satisfy the first. The options parameter is therefore widened to unknown — the one supertype that satisfies every overload at once. Re-check on every peer bump; nothing here fails if core changes the shape.

      Parameters

      • _messages: MessageListInput
      • Optional_options: unknown

      Returns Promise<never>

    • The same host-owned run-ID guard as FlowsafeDurableAgent.stream. prepare() is the third inherited minting entry point: it forwards options?.runId into core's prepareForDurableExecution (agent/durable/index.js:5980), which mints an unowned crypto.randomUUID() when it is absent (agent/durable/index.js:589) AND REGISTERS a run under that id (agent/durable/index.js:5984 — all three are 1.50.0-vintage offsets, since that file is a re-export shim from 1.53.0) — so a later resume(runId)/executeWorkflow sees a bare UUID PATH_SAFE_ID_PATTERN already accepts, past every downstream guard. Enforce the caller-minted ID here, while "absent" is still visible. A prepared id remains live until core cleans up the run, so later stream(), generate(), prepare(), and streamUntilPersisted() calls carrying that id are refused.

      Parameters

      • messages: MessageListInput
      • Optionaloptions: AgentExecutionOptions<TOutput>

      Returns Promise<{}>

    • Refuse core's single-run recovery. DurableAgent.recover() loads the persisted durable-agentic-loop snapshot, rebuilds model/memory/processors from it and re-drives the run with createRun + run.restart() — a second execution path that never enters executeWorkflow, so no leg of it is grant-derived, run-owned or snapshot-provenanced. Throw BEFORE the storage read, so a mistaken call cannot even enumerate a run.

      Parameters

      • _runId: string
      • Optional_options: DurableAgentRecoverOptions<TOutput>

      Returns Promise<never>

    • Refuse core's bulk recovery. recoverActiveRuns() is FlowsafeDurableAgent.listActiveRuns plus a recover() per row, and it is what Mastra.recoverAllDurableAgents() calls on every registered durable agent — so this is the one blocked entry point a host can reach without a FlowSafe call site, by opting into recovery: { durableAgents: 'auto' }. That loop isolates each agent in its own try/catch, so this refusal is logged there rather than failing boot. Refuse with an explicit runId too: a single target is still a re-drive off RunnerRuntime.

      Parameters

      • Optional_options: DurableAgentRecoverActiveRunsOptions

      Returns Promise<never>

    • Refuse core's durable resume. Until 1.53.0 this merely read the in-process run registry, which is why it was left inherited-but-unwired; now a registry MISS makes it load the persisted durable-agentic-loop snapshot, rehydrate through prepare() with the full application processor chain, and re-drive the run with createRun + run.resume — below executeWorkflow, so the leg carries no minted grant and no snapshot provenance. FlowsafeDurableAgent.resumeViaRuntime is the only resume path, and it is reached from the approval decision, never from a client.

      Parameters

      • _runId: string
      • _resumeData: unknown
      • Optional_options: DurableAgentResumeOptions<TOutput>

      Returns Promise<never>

    • Refuse the drain-to-completion resume. resumeGenerate() forwards straight to resume(), so it inherits the same below-the-seam re-drive.

      Parameters

      • _runId: string
      • _resumeData: unknown
      • Optional_options: DurableAgentResumeOptions<TOutput>

      Returns Promise<never>

    • Refuse the network resume — same loop and same ground as FlowsafeDurableAgent.network, plus one fact of its own: under autoResumeSuspendedTools it RECOVERS a suspended run id out of thread memory, so a caller need not even name the run it re-drives.

      Parameters

      • _resumeData: any
      • _options: Omit<MultiPrimitiveExecutionOptions, "runId"> & {}

      Returns Promise<never>

    • Refuse the base-Agent-shaped resume. Core overrides resumeStream() on DurableAgent precisely so an Agent-API caller lands on the durable resume(); blocking it here closes that same door from the other side.

      Parameters

      • _resumeData: any
      • Optional_streamOptions: any

      Returns Promise<never>

    • Rehydrate a suspended durable-agent run after isolate eviction, restore its active thread registration, then resume through RunnerRuntime so approval grant derivation and snapshot provenance remain authoritative. Hosts expose this only from their trusted approval-decision topology.

      Parameters

      • options: {
            memory?: AgentExecutionOptions<TOutput>["memory"];
            requestedBy: string;
            resumeData?: unknown;
            runId: string;
            step?: string | string[];
        }

      Returns Promise<RunSummary>

    • Refuse the thread-level tool approval. The name reads like a resume, but only its tail is one. Called with messages and approved, it routes to the thread runtime's continuation, which falls back to randomUUID() when the caller named no run id and then STARTS a run under it — an unowned id the host-owned run-id guard cannot distinguish from a real one, because it is path-safe. Called with no active thread run, it reaches the blocked suspended-run discovery instead. FlowSafe's own tool approval is a decided ApprovalRecord resumed through the approval-decision path, which mints the leg's grant; this mints nothing and owns nothing.

      Signature caveat: the base method is generic in OUTPUT, which Parameters<> instantiates to its undefined default and so types too narrowly to satisfy the base. The options parameter is widened to unknown — the one supertype that fits every instantiation. Re-check on every peer bump.

      Parameters

      • _options: unknown

      Returns Promise<never>

    • Enforce a caller-minted run ID before the inherited durable stream() runs: without this the optional options.runId would let core mint an unowned crypto.randomUUID() upstream. The private run-ID guard rejects a missing or non-path-safe value before delegating to core. A host mints an opaque path-safe id and passes it as options.runId.

      Parameters

      • messages: MessageListInput
      • Optionaloptions: DurableAgentStreamOptions<TOutput>

      Returns Promise<DurableAgentStreamResult<TOutput>>