Skip to content

feat(core): migrate Durable Agent to evented workflow engine#17716

Open
taofeeq-deru wants to merge 89 commits into
mainfrom
durable-agent-evented-workflows
Open

feat(core): migrate Durable Agent to evented workflow engine#17716
taofeeq-deru wants to merge 89 commits into
mainfrom
durable-agent-evented-workflows

Conversation

@taofeeq-deru

@taofeeq-deru taofeeq-deru commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Migrates the Durable Agent's internal workflow engine from the synchronous createWorkflow() to the evented createEventedWorkflow() engine. This brings durability and observability improvements to durable agent runs by leveraging the same event-driven architecture used by standard workflows.

What changed

  • createDurableAgenticWorkflow now uses createEventedWorkflow() instead of createWorkflow()
  • DurableAgent lifecycle methods (stream, generate, resume) updated to work with the evented engine, including mastra.startWorkers() and internal workflow registration
  • Nested workflow initial snapshots now include the input key from the parent step's result in the persisted context, preventing data loss during step execution
  • Ephemeral Mastra fallback ensures durable agents without an explicit Mastra instance still get proper pubsub and storage for the evented engine

Transparency

This change is fully transparent — existing Durable Agent usage continues to work without any API changes. The shouldPersistSnapshot option on the durable agentic workflow controls which statuses are persisted (pending, paused, suspended), matching the previous behavior.

Test plan

  • All 324 durable agent tests pass (23 files)
  • All 510 core test files pass (9,278 tests, 0 failures)
  • All 267 Playground E2E tests pass
  • TypeScript compiles cleanly (tsc --noEmit)

ELI5

This PR swaps the Durable Agent’s internal engine for an event-based one so long-running agent runs are more durable and observable; it happens behind the scenes with no API changes.

Summary

The Durable Agent’s internal workflow engine was migrated from synchronous createWorkflow() to the event-driven createEventedWorkflow(), improving durability, observability, and recovery while remaining backward-compatible.

Core Changes

  • Workflow Engine Migration: createDurableAgenticWorkflow now uses createEventedWorkflow() for single-iteration execution and the agentic loop, and persisted snapshots are created for pending, paused, and suspended statuses.
  • Dynamic Evented Module Loading: evented workflow code is loaded on-demand via await import(...) to avoid ESM import-order cycles.
  • Mastra Resolution & Ephemeral Fallback: DurableAgent resolves an “effective” Mastra for runs; if none is registered, it lazily creates a short-lived Mastra (pubsub wired to the agent, storage defaulting to in-memory) so the evented engine has pubsub/storage.
  • Nested Workflow Snapshot Fix: initial nested workflow snapshots now include { input: prevResult.output } when the parent step succeeded, preventing input loss during nested step execution.
  • Lifecycle & Cleanup: internal run-scoped workflow registration/unregistration is handled for execution/resume; stream(), resume(), and observe() cleanup logic best-effort unregisters internal workflows. Ephemeral Mastra instances are stopped/cleared if a real Mastra is later registered.
  • Evented Execution Path: EventedAgent now fire-and-forgets runs by creating run objects and calling startAsync; durable execution wiring was updated accordingly.

Observability & Serialization

  • Tracing is propagated for evented runs (WORKFLOW_RUN / WORKFLOW_STEP spans).
  • Serialization boundaries introduced by the event bus are addressed for tool errors, suspend contexts, signal echoes, and function-based tool approval policies.

Test & Infrastructure Changes

  • Tests updated to deterministically drain async streams and await cached events instead of using fixed sleeps.
  • Test cleanup clears both background tasks and persisted workflow state between tests.
  • Test Mastra instances include pubsub and stable storage (file-backed LibSQL or similar) instead of :memory: where applicable.
  • 324 durable agent tests (23 files), 510 core test files (9,278 tests) passed; 267 Playground E2E tests passed. TypeScript compiles cleanly.

Compatibility

  • No public API changes. shouldPersistSnapshot behavior remains: snapshot persistence continues to be controlled for pending/paused/suspended as noted. The migration is transparent to existing Durable Agent usage.

taofeeq-deru and others added 30 commits May 18, 2026 17:16
The agentic-loop modules no longer statically import `workflows/evented`
(that formed an ESM init-time cycle with the base `Workflow` class). They
build evented workflows via the `createEventedWorkflow` registry instead,
so the evented module must be loaded before those factories run. Load it
with a dynamic import on the agent execute path and the loop stream path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The agentic loop now runs on the evented workflow engine, which requires a
Mastra with pubsub and running workers. The e2e test used MastraLLMVNext
standalone with no Mastra, so every case failed with "Mastra instance with
pubsub is required". Provide one in beforeAll and register it on the model.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The agentic loop runs on the evented workflow engine, which needs a
pubsub-equipped Mastra with running workers and an atomic-capable storage
adapter. Two tests used mocks too thin to satisfy it:

- agent-fga "no FGA provider configured" registered a hand-rolled Mastra
  mock with no startWorkers; drop it so the agent uses its ephemeral Mastra.
- runEvals "save scores to storage" used a partial storage mock whose
  workflows store lacks atomic operations; use a real InMemoryStore and spy
  on the real scores store.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… loop

A signal sent to an already-running agent could be folded into the run's
first model request instead of getting its own turn. The evented engine
registers a run as "active" before its first model request, so
`llm-execution-step`'s pre-first-request drain would grab a follow-up signal
that arrived in that window — collapsing two turns into one.

Split the queue in two: signals sent to a reserved (not-yet-started) run stay
folded into the first request, while signals sent to an active run are drained
as separate turns by `signalDrainStep`. `sendSignal` already distinguishes the
cases — route them to `preRunSignalsByThread` vs `pendingSignalsByThread`, and
have `drainPendingSignals` take a `scope` to read the right one.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Evented workflow runs dropped the observability context: `EventedRun.start`
ignored it, so the event processor never built a `tracingContext` and every
step's `params.tracingContext` was undefined. Spans created inside an evented
workflow — the model, tool, and processor spans of an agent run — were
orphaned and never exported, truncating the trace at `agent_run`.

`currentSpan` is a non-serializable AISpan, so it cannot ride the engine's
pubsub events. Hold the run's tracing context on Mastra keyed by runId
(`__registerRunTracingContext`): `EventedRun.start` records it, and the event
processor reads it when dispatching each step — walking the parent-run chain
so nested workflow runs inherit their parent's span.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… engine

The evented workflow engine never created its own workflow/step spans the
way the default engine does, so agent traces viewed with internal spans
shown were missing the `execution-workflow` / `agentic-loop` run spans and
the per-step spans.

`EventedRun.start` now creates a WORKFLOW_RUN span and registers it as the
run's tracing context, so steps nest under it. The step executor creates a
WORKFLOW_STEP span per step. Both honor the workflow's `tracingPolicy`, so
internal workflows stay hidden unless internal spans are explicitly shown.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
taofeeq-deru and others added 7 commits June 4, 2026 09:35
…ontext

When a nested workflow's initial snapshot is persisted, include the
parent step's prevResult output as the input key in the context. This
prevents updateWorkflowResults from later overwriting the event's
stepResults (which contains input) with storage's empty context.

Co-Authored-By: Mastra Code (anthropic/claude-opus-4-6) <noreply@mastra.ai>
Co-Authored-By: Mastra Code (anthropic/claude-opus-4-6) <noreply@mastra.ai>
@changeset-bot

changeset-bot Bot commented Jun 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 4dcabd2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 20 packages
Name Type
@mastra/core Minor
mastracode Patch
@mastra/mcp-docs-server Patch
@internal/playground Patch
@mastra/client-js Patch
@mastra/opencode Patch
@mastra/longmemeval Patch
mastra Patch
@mastra/deployer-cloud Minor
@mastra/react Patch
@mastra/playground-ui Patch
@mastra/server Minor
@mastra/deployer Minor
create-mastra Patch
@mastra/express Patch
@mastra/fastify Patch
@mastra/hono Patch
@mastra/koa Patch
@mastra/nestjs Patch
@mastra/temporal Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
mastra-docs-1.x Ready Ready Preview, Comment Jun 9, 2026 6:21pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
mastra-playground-ui Skipped Skipped Jun 9, 2026 6:21pm

Request Review

@dane-ai-mastra dane-ai-mastra Bot added the complexity: critical Critical-complexity PR label Jun 9, 2026
@dane-ai-mastra

dane-ai-mastra Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

PR triage

Linked issue check skipped for core contributor @taofeeq-deru.


PR complexity score

Factor Value Score impact
Files changed 17 +34
Lines changed 3002 +60
Author merged PRs 474 -20
Test files changed Yes -10
Final score 64

Applied label: complexity: critical


Changed test gate

Changed tests failed against the base branch as expected.

Label: tests: green ✅

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b1756d41-76da-4ff4-a0f5-64335eaf2ec8

📥 Commits

Reviewing files that changed from the base of the PR and between e209349 and 3464019.

📒 Files selected for processing (3)
  • packages/core/src/agent/durable/workflows/create-durable-agentic-workflow.ts
  • packages/core/src/agent/durable/workflows/steps/llm-execution.ts
  • packages/core/src/agent/durable/workflows/steps/llm-mapping.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/core/src/agent/durable/workflows/steps/llm-execution.ts
  • packages/core/src/agent/durable/workflows/steps/llm-mapping.ts
  • packages/core/src/agent/durable/workflows/create-durable-agentic-workflow.ts

Walkthrough

This PR migrates Durable Agent's internal workflow engine from synchronous to evented execution by adding runtime evented module loading, ephemeral Mastra instance resolution, internal workflow registration and teardown, switching agentic workflows to the evented engine, and updating tests to deterministically drain streams. No public API changes.

Changes

Durable Agent Evented Workflow Migration

Layer / File(s) Summary
Release documentation
.changeset/thick-signs-decide.md
Minor version bump for @mastra/core documenting workflow engine migration from synchronous to evented with no API changes.
Runtime evented workflow module loading
packages/core/src/agent/agent.ts, packages/core/src/loop/workflows/stream.ts
Agent and loop workflows dynamically import the evented module at runtime to ensure factory registration when needed and avoid import-time cycles.
DurableAgent evented execution infrastructure
packages/core/src/agent/durable/durable-agent.ts
Introduces ephemeral Mastra instances, effective Mastra resolution, internal workflow registration with worker lifecycle, and extended cleanup for stream/resume/observe methods with best-effort run teardown.
EventedAgent runWorkflow override
packages/core/src/agent/durable/evented-agent.ts
Refactors execution from executeWorkflow to runWorkflow override, creating runs without pubsub parameter and starting async (fire-and-forget), with lifecycle/cleanup delegated to parent DurableAgent infrastructure.
Durable agentic workflow creation
packages/core/src/agent/durable/workflows/create-durable-agentic-workflow.ts
Switches workflow construction from createWorkflow to createEventedWorkflow for both single-iteration and loop steps; extends snapshot persistence to include pending/paused statuses; adds module load order documentation.
Workflow step import path alignment
packages/core/src/agent/durable/workflows/steps/background-task-check.ts, llm-execution.ts, llm-mapping.ts, scorer-execution.ts, tool-call.ts
Multiple workflow step files update createStep import source from workflows barrel export to direct workflow module path and align PUBSUB_SYMBOL imports.
Nested workflow snapshot context initialization
packages/core/src/workflows/evented/workflow-event-processor/index.ts
Nested workflow snapshot context now includes parent step output as input when the triggering parent succeeded.
Test stream cleanup and draining
packages/core/src/agent/durable/__tests__/durable-agent-background-tasks.test.ts, durable-agent-request-context.test.ts, durable-agent-stopwhen.test.ts, resume-api.test.ts
Test files updated to await stream consumption via consumeStream or draining fullStream before cleanup; resume tests poll cached events deterministically instead of using fixed sleeps.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • mastra-ai/mastra#16796: Both PRs touch the evented-workflow runtime wiring for the agentic loop—specifically dynamic await import(...) loading of workflows/evented/workflow in the loop stream/workflow execution path—so the changes are directly connected at the module-import/run-setup level.
  • mastra-ai/mastra#16637: Both PRs address evented workflow registration/import ordering: the retrieved PR restores evented factory side-effect registration via packages/core/src/workflows/index.ts, while this PR ensures evented workflow modules are dynamically imported at runtime so durable/scheduled execution initializes correctly.
  • mastra-ai/mastra#16631: Both PRs modify create-durable-agentic-workflow.ts-adjacent code: this PR switches to the evented engine and adjusts snapshot persistence while the related PR adjusts tracing for internal workflow spans.

Suggested reviewers

  • abhiaiyer91
  • rase-
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: migrating Durable Agent to the evented workflow engine, which is the core objective of this PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch durable-agent-evented-workflows

Warning

Review ran into problems

🔥 Problems

Stopped waiting for pipeline failures after 30000ms. One of your pipelines takes longer than our 30000ms fetch window to run, so review may not consider pipeline-failure results for inline comments if any failures occurred after the fetch window. Increase the timeout if you want to wait longer or run a @coderabbit review after the pipeline has finished.


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (5)
packages/core/src/agent/durable/__tests__/resume-api.test.ts (1)

260-266: ⚡ Quick win

Consider adding explicit timeout or assertion to the polling loop.

The polling loop waits for cached events but breaks silently after 100 iterations if no events arrive. If the evented engine fails to cache events, the test continues and only fails later at line 274 (or 308) when asserting cachedEvents.length > 0, making the root cause harder to diagnose.

Consider adding an assertion or throwing an error if the loop completes without finding events:

 for (let i = 0; i < 100; i++) {
   await new Promise(resolve => setTimeout(resolve, 50));
   const events = await cachingPubsub.getHistory(topic);
   if (events.length > 0) break;
 }
+const cachedAfterWait = await cachingPubsub.getHistory(topic);
+expect(cachedAfterWait.length).toBeGreaterThan(0);

This provides clearer failure messages and catches issues at the polling site.

Also applies to: 296-302

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/agent/durable/__tests__/resume-api.test.ts` around lines
260 - 266, The polling loop that waits for cached events (using the topic
variable `const topic = \`agent.stream.${runId}\`` and
`cachingPubsub.getHistory(topic)`) may exit silently after 100 iterations;
modify the loop to fail fast by adding an explicit timeout/maximum-wait
assertion: after the loop completes without finding events, throw an Error or
call an assertion like `assert.fail` with a clear message that no cached events
arrived for the topic and include the runId/topic in the message; apply the same
change to the second polling block that uses `cachingPubsub.getHistory` at the
296-302 site so tests report the polling timeout immediately.
packages/core/src/agent/durable/__tests__/durable-agent-background-tasks.test.ts (1)

169-181: ⚡ Quick win

Inconsistent stream cleanup pattern across background-tasks tests.

This test (and several others at lines 209-223, 260-288, 323-341, 392-421, 496-511) uses a fixed setTimeout followed by immediate cleanup(), whereas the request-context and stopwhen test files in this PR consistently drain streams before cleanup via await drain(result.fullStream) or await output.consumeStream().

Since the evented engine is async, fixed timeouts are non-deterministic and may not guarantee the stream has finished processing. Consider updating these tests to explicitly drain the stream before calling cleanup() for consistency and determinism.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/core/src/agent/durable/__tests__/durable-agent-background-tasks.test.ts`
around lines 169 - 181, The test uses a fixed setTimeout before calling cleanup
on the stream returned by durableAgent.stream, which is non-deterministic;
replace the timeout-based wait with an explicit stream drain/consume step: after
calling durableAgent.stream('Research quantum', {...}) capture the returned
stream (or result.fullStream / result) and await a drain utility (e.g., await
drain(result.fullStream) or await output.consumeStream()) to ensure all events
are processed before calling cleanup(); apply the same change to the other
background-tasks tests referenced (the blocks around lines 209-223, 260-288,
323-341, 392-421, 496-511) so they all use deterministic stream draining instead
of setTimeout.
packages/core/src/agent/durable/durable-agent.ts (2)

469-471: 💤 Low value

Redundant startWorkers() call.

#getEffectiveMastra() already calls await ephemeral.startWorkers() at line 341 when creating the ephemeral instance. The second call here is redundant for the ephemeral case, and for the user's Mastra (returned directly from line 327), workers should already be started. Consider removing the duplicate call.

♻️ Suggested fix
     const effectiveMastra = await this.#getEffectiveMastra();
-    await effectiveMastra.startWorkers();
     effectiveMastra.__registerInternalWorkflow(workflow as any, runId);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/agent/durable/durable-agent.ts` around lines 469 - 471,
Remove the redundant await effectiveMastra.startWorkers() call here and rely on
`#getEffectiveMastra`() to ensure workers are started for both ephemeral and user
Mastra instances; keep the subsequent
effectiveMastra.__registerInternalWorkflow(workflow as any, runId) invocation
unchanged. Locate the code around `#getEffectiveMastra`, startWorkers,
effectiveMastra and remove the extra startWorkers invocation so workers are not
started twice.

724-726: 💤 Low value

Same redundant startWorkers() call in resume path.

Similar to executeWorkflow(), #getEffectiveMastra() already starts workers when creating the ephemeral instance.

♻️ Suggested fix
         const effectiveMastra = await this.#getEffectiveMastra();
-        await effectiveMastra.startWorkers();
         effectiveMastra.__registerInternalWorkflow(workflow as any, runId);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/agent/durable/durable-agent.ts` around lines 724 - 726, The
resume path is calling effectiveMastra.startWorkers() redundantly because
`#getEffectiveMastra`() already starts workers when creating the ephemeral Mastra;
remove the await effectiveMastra.startWorkers() call and keep the subsequent
effectiveMastra.__registerInternalWorkflow(workflow as any, runId) registration
so the code uses the already-initialized worker state from
`#getEffectiveMastra`().
packages/core/src/agent/durable/workflows/create-durable-agentic-workflow.ts (1)

114-136: 💤 Low value

Consider extracting the duplicated shouldPersistSnapshot predicate.

The same persistence logic appears in both singleIterationWorkflow (lines 119-129) and the main agentic loop workflow (lines 222-232). Extracting to a shared constant would reduce maintenance burden if the persistence rules change.

const shouldPersistSnapshot: typeof params => boolean = params =>
  params.workflowStatus === 'pending' ||
  params.workflowStatus === 'paused' ||
  params.workflowStatus === 'suspended';

Also applies to: 217-238

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/agent/durable/workflows/create-durable-agentic-workflow.ts`
around lines 114 - 136, Extract the duplicated predicate into a single exported
constant (e.g., shouldPersistSnapshot) and use it in both createEventedWorkflow
calls (the one with id DurableStepIds.AGENTIC_EXECUTION /
singleIterationWorkflow and the main agentic loop workflow) instead of
duplicating the inline function; implement the constant with the same logic
(return true when params.workflowStatus is 'pending' || 'paused' || 'suspended')
and update the options.shouldPersistSnapshot references to call that shared
constant so maintenance of persistence rules is centralized.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@packages/core/src/agent/durable/__tests__/durable-agent-background-tasks.test.ts`:
- Around line 169-181: The test uses a fixed setTimeout before calling cleanup
on the stream returned by durableAgent.stream, which is non-deterministic;
replace the timeout-based wait with an explicit stream drain/consume step: after
calling durableAgent.stream('Research quantum', {...}) capture the returned
stream (or result.fullStream / result) and await a drain utility (e.g., await
drain(result.fullStream) or await output.consumeStream()) to ensure all events
are processed before calling cleanup(); apply the same change to the other
background-tasks tests referenced (the blocks around lines 209-223, 260-288,
323-341, 392-421, 496-511) so they all use deterministic stream draining instead
of setTimeout.

In `@packages/core/src/agent/durable/__tests__/resume-api.test.ts`:
- Around line 260-266: The polling loop that waits for cached events (using the
topic variable `const topic = \`agent.stream.${runId}\`` and
`cachingPubsub.getHistory(topic)`) may exit silently after 100 iterations;
modify the loop to fail fast by adding an explicit timeout/maximum-wait
assertion: after the loop completes without finding events, throw an Error or
call an assertion like `assert.fail` with a clear message that no cached events
arrived for the topic and include the runId/topic in the message; apply the same
change to the second polling block that uses `cachingPubsub.getHistory` at the
296-302 site so tests report the polling timeout immediately.

In `@packages/core/src/agent/durable/durable-agent.ts`:
- Around line 469-471: Remove the redundant await effectiveMastra.startWorkers()
call here and rely on `#getEffectiveMastra`() to ensure workers are started for
both ephemeral and user Mastra instances; keep the subsequent
effectiveMastra.__registerInternalWorkflow(workflow as any, runId) invocation
unchanged. Locate the code around `#getEffectiveMastra`, startWorkers,
effectiveMastra and remove the extra startWorkers invocation so workers are not
started twice.
- Around line 724-726: The resume path is calling effectiveMastra.startWorkers()
redundantly because `#getEffectiveMastra`() already starts workers when creating
the ephemeral Mastra; remove the await effectiveMastra.startWorkers() call and
keep the subsequent effectiveMastra.__registerInternalWorkflow(workflow as any,
runId) registration so the code uses the already-initialized worker state from
`#getEffectiveMastra`().

In
`@packages/core/src/agent/durable/workflows/create-durable-agentic-workflow.ts`:
- Around line 114-136: Extract the duplicated predicate into a single exported
constant (e.g., shouldPersistSnapshot) and use it in both createEventedWorkflow
calls (the one with id DurableStepIds.AGENTIC_EXECUTION /
singleIterationWorkflow and the main agentic loop workflow) instead of
duplicating the inline function; implement the constant with the same logic
(return true when params.workflowStatus is 'pending' || 'paused' || 'suspended')
and update the options.shouldPersistSnapshot references to call that shared
constant so maintenance of persistence rules is centralized.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d69fd6bf-cd0f-4890-b30b-0c99f85cde40

📥 Commits

Reviewing files that changed from the base of the PR and between 48a1aae and e209349.

⛔ Files ignored due to path filters (1)
  • packages/mcp/integration-tests/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (16)
  • .changeset/thick-signs-decide.md
  • packages/core/src/agent/agent.ts
  • packages/core/src/agent/durable/__tests__/durable-agent-background-tasks.test.ts
  • packages/core/src/agent/durable/__tests__/durable-agent-request-context.test.ts
  • packages/core/src/agent/durable/__tests__/durable-agent-stopwhen.test.ts
  • packages/core/src/agent/durable/__tests__/resume-api.test.ts
  • packages/core/src/agent/durable/durable-agent.ts
  • packages/core/src/agent/durable/evented-agent.ts
  • packages/core/src/agent/durable/workflows/create-durable-agentic-workflow.ts
  • packages/core/src/agent/durable/workflows/steps/background-task-check.ts
  • packages/core/src/agent/durable/workflows/steps/llm-execution.ts
  • packages/core/src/agent/durable/workflows/steps/llm-mapping.ts
  • packages/core/src/agent/durable/workflows/steps/scorer-execution.ts
  • packages/core/src/agent/durable/workflows/steps/tool-call.ts
  • packages/core/src/loop/workflows/stream.ts
  • packages/core/src/workflows/evented/workflow-event-processor/index.ts

@dane-ai-mastra dane-ai-mastra Bot added the tests: green ✅ Changed tests failed against base as expected label Jun 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

complexity: critical Critical-complexity PR tests: green ✅ Changed tests failed against base as expected

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant