Anchorage API reference
    Preparing search index...

    Interface FlowsafeWorkerConfig<Env>

    interface FlowsafeWorkerConfig<Env extends FlowsafeWorkerEnv> {
        artifactStore?: (env: Env) => RunArtifactPurger | undefined;
        backgroundTasks?: BackgroundTasksCleanupConfig;
        beforeResume?: (
            context: ActorContext,
            env: Env,
            workflowId: string,
            runId: string,
            body: unknown,
        ) => Promise<void>;
        beforeStart?: (
            context: ActorContext,
            env: Env,
            workflowId: string,
            inputData: unknown,
            requestContext: Record<string, unknown> | undefined,
        ) => Promise<void>;
        buildAgentRouter?: (
            resolve: ActorResolver,
            env: Env,
        ) => AgentRouter | undefined;
        buildObjectiveRouter?: (
            resolve: ActorResolver,
            env: Env,
        ) => ((request: Request) => Promise<Response | null>) | undefined;
        buildResumeRun?: (fallback: ResumeRunFn, env: Env) => ResumeRunFn;
        buildScheduleRouter?: (
            resolve: ActorResolver,
            env: Env,
        ) => ((request: Request) => Promise<Response | null>) | undefined;
        buildSignalRouter?: (
            resolve: ActorResolver,
            env: Env,
        ) => ((request: Request) => Promise<Response | null>) | undefined;
        buildVerifier: (env: Env) => TokenVerifier;
        extraPurgeDuties?: (env: Env) => Promise<Record<string, unknown>>;
        maintenance: {
            deadlineIntervalMs?: number;
            deadlineLimit?: number;
            notificationIntervalMs?: number;
            purgeIntervalMs: number;
            remoteStepRecoveryIntervalMs?: number;
            sweepIntervalMs: number;
            tickIntervalMs?: number;
        };
        mutationEpoch?: number
        | ((env: Env) => unknown);
        notificationTick?: (env: Env) => () => Promise<unknown>;
        notify?: (env: Env) => ApprovalNotificationSink | undefined;
        preRoutes?: (
            request: Request,
            env: Env,
            ctx: FlowsafeWorkerContext,
            kit: {
                authorizePrivateWorkflowDispatch: (
                    request: Request,
                ) => Promise<Response | undefined>;
                contextForStoredInvocation: (
                    journal: {
                        deploymentId: string;
                        get: (
                            invocationId: string,
                        ) => Promise<
                            | {
                                deploymentId: string;
                                invocationId: string;
                                principal: ExecutionPrincipal;
                                tablePrefix: string;
                            }
                            | undefined,
                        >;
                        tablePrefix: string;
                    },
                    invocationId: string,
                ) => Promise<ActorContext | undefined>;
                contextForStoredWorkflowInvocation: (
                    journal: {
                        deploymentId: string;
                        getWorkflow: (
                            invocationId: string,
                        ) => Promise<
                            | {
                                deploymentId: string;
                                invocationId: string;
                                principal: ExecutionPrincipal;
                                tablePrefix: string;
                            }
                            | undefined,
                        >;
                        tablePrefix: string;
                    },
                    invocationId: string,
                ) => Promise<ActorContext | undefined>;
                contextForStoredWorkflowStart: (
                    workflowId: string,
                    runId: string,
                ) => Promise<ActorContext | undefined>;
                resolve: ActorResolver;
                topology: DoRunRemoteStepTopology;
            },
        ) => Promise<Response | null>;
        remoteStepRecoveryTick?: (env: Env) => () => Promise<unknown>;
        scheduleTick?: (env: Env) => (() => Promise<unknown>) | undefined;
        storageTablePrefix?: string;
        systemPrincipalId: string;
        workflows: readonly WorkflowMeta[];
    }

    Type Parameters

    Hierarchy (View Summary)

    Index

    Properties

    artifactStore?: (env: Env) => RunArtifactPurger | undefined

    Builds the artifact purger from the current invocation's environment. When set, the retention purge deletes each expired run's R2 artifacts WITH its snapshot row. The snapshot row is the only enumerable record of a run's artifact keys, so a retention purge without this pairing strands artifacts until deployment teardown. Return the same R2-backed store used for runtime writes, or undefined for row-only purge. NOT via extraPurgeDuties: that hook runs after the rows are deleted, when the keys are already unenumerable.

    Opt-in background-task TTL cleanup. When present, the purge duty reaps terminal mastra_background_tasks rows past the TTL as its OWN failure-isolated duty — the storage-layer belt to a hosting DO's manager cleanup (which needs the DO alive). Absent => no duty, byte-identical (background tasks are opt-in). NOT via extraPurgeDuties: this needs its own try/catch and its own log fields, like every sibling purge duty.

    beforeResume?: (
        context: ActorContext,
        env: Env,
        workflowId: string,
        runId: string,
        body: unknown,
    ) => Promise<void>

    Host policy immediately before a validated raw resume reaches the run DO.

    beforeStart?: (
        context: ActorContext,
        env: Env,
        workflowId: string,
        inputData: unknown,
        requestContext: Record<string, unknown> | undefined,
    ) => Promise<void>

    Host policy immediately before a validated start reaches the run DO.

    buildAgentRouter?: (resolve: ActorResolver, env: Env) => AgentRouter | undefined

    Opt-in authenticated agent catalog/run router. Structurally typed so this module does not import the server-only agent-host subpath.

    buildObjectiveRouter?: (
        resolve: ActorResolver,
        env: Env,
    ) => ((request: Request) => Promise<Response | null>) | undefined

    Opt-in goal-objective stage. Mirrors buildSignalRouter: the host builds its createObjectiveRouter (which needs the thread-state store from its D1 domains, plus its audit/maxRuns config) and returns it here, closed over the request's ActorResolver; the composer mounts it after the signal stage. Both live under /api/threads/* but do not overlap — goals use the /goal segment, signals the channel segments. INJECTED rather than built here because createObjectiveRouter lives in goals/, which imports host-kit — host-kit importing it back would cycle. Absent (or returns undefined) ⇒ no goal stage, byte-identical.

    buildResumeRun?: (fallback: ResumeRunFn, env: Env) => ResumeRunFn

    Compose approval-driven resume handling, including agent-thread targets. fallback checks that the step is still at the record's suspension; a resume the composed function builds itself passes expectedSuspensionFor(record) for that check.

    buildScheduleRouter?: (
        resolve: ActorResolver,
        env: Env,
    ) => ((request: Request) => Promise<Response | null>) | undefined

    Opt-in schedule CRUD facade. Mirrors buildSignalRouter/ buildObjectiveRouter: the host builds its createScheduleRouter (which needs the schedules store from its D1 domains + its audit/cap config) and returns it here, closed over the request's ActorResolver; the composer mounts it after the goal stage. Its /api/schedules/* routes don't overlap the others. INJECTED (not built here, typed structurally) because createScheduleRouter lives in schedules/, which transitively imports host-kit — importing it back would cycle. Absent (or returns undefined) ⇒ no schedule surface, byte-identical.

    buildSignalRouter?: (
        resolve: ActorResolver,
        env: Env,
    ) => ((request: Request) => Promise<Response | null>) | undefined

    Opt-in signal-ingestion stage. The host builds its createSignalRouter (which needs its per-thread DO namespace via createThreadTopology, plus its audit/rate/allowlist config) and returns it here, closed over the request's ActorResolver; the composer mounts it after preRoutes, ahead of approvals/runs (its /api/threads/* routes don't overlap). INJECTED rather than built here because createSignalRouter lives in signals/, which imports host-kit — host-kit importing it back would cycle. Absent (or returns undefined) => no signal stage, byte-identical.

    buildVerifier: (env: Env) => TokenVerifier

    The identity seam: env -> TokenVerifier. Called once per fetch, so hosts keep their own per-isolate memoization — re-parsing a token map on every request is pure waste, but that is the host's trade to make.

    extraPurgeDuties?: (env: Env) => Promise<Record<string, unknown>>

    Extra purge duties. The returned fields fold into the ONE combined {type:'maintenance'} log line. A throw reports the purge attempt as failed while the worker still contains it, logs a maintenance-error, and emits the combined log.

    maintenance: {
        deadlineIntervalMs?: number;
        deadlineLimit?: number;
        notificationIntervalMs?: number;
        purgeIntervalMs: number;
        remoteStepRecoveryIntervalMs?: number;
        sweepIntervalMs: number;
        tickIntervalMs?: number;
    }

    Recurrence intervals for the singleton maintenance Durable Object. Every duty receives its own alarm invocation; tickIntervalMs is required when scheduleTick is configured and omitted otherwise, and notificationIntervalMs likewise with notificationTick, and remoteStepRecoveryIntervalMs with remoteStepRecoveryTick.

    Type Declaration

    • OptionaldeadlineIntervalMs?: number

      Deadline duty cadence. Defaults to sweepIntervalMs.

    • OptionaldeadlineLimit?: number

      Maximum runs per deadline pass. Default 100.

    • OptionalnotificationIntervalMs?: number
    • purgeIntervalMs: number
    • OptionalremoteStepRecoveryIntervalMs?: number
    • sweepIntervalMs: number
    • OptionaltickIntervalMs?: number
    mutationEpoch?: number | ((env: Env) => unknown)

    Trusted host epoch, captured before request authentication and storage waits. Callbacks return a number or undefined synchronously; client headers cannot supply it.

    notificationTick?: (env: Env) => () => Promise<unknown>

    Opt-in notification dispatch tick. The host builds its createNotificationDispatchTick and returns the closure here. The composer runs it as its OWN failure-isolated alarm duty (own try/catch, own notification-dispatch log line), so a schedule pass that throws or is terminated costs it nothing. The composer invokes THIS BUILDER outside that try, so a builder that throws is logged as maintenance-error with surface: 'notification-duty'. INJECTED (not built here, structurally typed as () => Promise<unknown>), like scheduleTick, because signals/ imports host-kit — host-kit importing it back would cycle. Requires maintenance.notificationIntervalMs; absent, the deployment runs no notification duty.

    notify?: (env: Env) => ApprovalNotificationSink | undefined

    Reviewer-facing notification transport used by the same service.

    preRoutes?: (
        request: Request,
        env: Env,
        ctx: FlowsafeWorkerContext,
        kit: {
            authorizePrivateWorkflowDispatch: (
                request: Request,
            ) => Promise<Response | undefined>;
            contextForStoredInvocation: (
                journal: {
                    deploymentId: string;
                    get: (
                        invocationId: string,
                    ) => Promise<
                        | {
                            deploymentId: string;
                            invocationId: string;
                            principal: ExecutionPrincipal;
                            tablePrefix: string;
                        }
                        | undefined,
                    >;
                    tablePrefix: string;
                },
                invocationId: string,
            ) => Promise<ActorContext | undefined>;
            contextForStoredWorkflowInvocation: (
                journal: {
                    deploymentId: string;
                    getWorkflow: (
                        invocationId: string,
                    ) => Promise<
                        | {
                            deploymentId: string;
                            invocationId: string;
                            principal: ExecutionPrincipal;
                            tablePrefix: string;
                        }
                        | undefined,
                    >;
                    tablePrefix: string;
                },
                invocationId: string,
            ) => Promise<ActorContext | undefined>;
            contextForStoredWorkflowStart: (
                workflowId: string,
                runId: string,
            ) => Promise<ActorContext | undefined>;
            resolve: ActorResolver;
            topology: DoRunRemoteStepTopology;
        },
    ) => Promise<Response | null>

    Deployment-specific routes tried AFTER /healthz and BEFORE the approval and run routers (the showcase mounts its demo sign-in here). kit hands over the request's already-built resolver and DO topology so a pre-route can share them. Return null to fall through.

    remoteStepRecoveryTick?: (env: Env) => () => Promise<unknown>
    scheduleTick?: (env: Env) => (() => Promise<unknown>) | undefined

    Opt-in schedule tick. The host builds its createScheduleTick (which needs the schedules store, its run-start seam — topology.start — and the run-cap + audit config) and returns the closure here. The composer runs it as its OWN failure-isolated alarm duty (own try/catch, own schedule-tick log line). The composer invokes THIS BUILDER outside that try, so a builder that throws is logged as maintenance-error with surface: 'tick-duty'; build a factory that can refuse at construction inside the returned closure. INJECTED (not built here, structurally typed as () => Promise<unknown>) because createScheduleTick lives in schedules/, which transitively imports host-kit — host-kit importing it back would cycle. Requires maintenance.tickIntervalMs; absent, the deployment runs no tick duty. A builder that returns undefined fails the duty with a config-error line on every pass.

    storageTablePrefix?: string

    Prefix used by the runner's existing Mastra snapshot table.

    systemPrincipalId: string

    System-principal id for bridge bookkeeping and alarm maintenance attribution. Requester kind is persisted separately, so ids may overlap across principal kinds.

    workflows: readonly WorkflowMeta[]

    The catalog createRunRouter serves and gates (hosts pass their metas).