Commit 493a328
feat(core): run agentic loop on the evented workflow engine (#16796)
## Summary
- Migrates the agent's internal agentic loop onto the evented workflow
engine. Each LLM call and tool call now runs as a workflow step, sharing
suspend/resume and observability with the rest of the workflow system.
No user-visible behavior change yet — this is the structural
prerequisite for future durability and event-based observability
features.
- Fixes a nested-workflow bug where `resumeLabel` wasn't propagated up
through a parent's suspendedPaths, so resuming a nested workflow by
label silently failed.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
ELI5: This change moves the agent's internal loop to run as a series of
steps in the evented workflow engine so each model call and tool call is
tracked like a tiny workflow. That makes suspend/resume, observability,
and future durability much easier and also fixes a bug that broke
resuming nested workflows by label.
- What it does
- Migrates the agentic loop so each LLM and tool call executes as
evented workflow steps (uses createEventedWorkflow /
createEventedWorkflow factory).
- Agents can run without a user-provided Mastra by creating a
lazily-initialized ephemeral Mastra (InMemoryStore + EventEmitterPubSub)
and starting ephemeral workers on first use.
- Adds a per-run runScope (PrepareStreamRunScope) to thread
non-JSON-safe runtime state (MessageList, processorStates,
convertedTools, loopOptions) across prepare-stream workflow steps
instead of passing those objects through step inputs/outputs.
- Introduces runId-scoped internal workflow registration/unregistration
to avoid collisions for concurrent/nested runs.
- Bug fixes / behavioral corrections
- Fixes nested-workflow resume-by-label: resumeLabel is propagated
through parent suspendedPaths and nested suspend metadata so resuming a
nested workflow by label works reliably.
- Preserves and aggregates suspendPayloads (not just resumeLabels)
across suspended foreach iterations and when storage persistence is
skipped/absent.
- Ensures persisted snapshots are retained for pending/paused/suspended
states (not only suspended).
- Tightens internal workflow lookup to prefer runId-scoped internal
workflow instances, preventing wrong closure/registration resolution in
nested/concurrent cases.
- Implementation details / notable API surface changes
- New helper: createEventedWorkflow(...) exported from workflows
entrypoint (throws if evented factory not loaded).
- Mastra changes:
- Defaults to InMemoryStore when storage not provided (with warning) and
augments the store.
- Internal workflow registry supports runId-scoped keys; added
__unregisterInternalWorkflow and updated __registerInternalWorkflow /
__hasInternalWorkflow / __getInternalWorkflow signatures.
- Evented processor and execution engine:
- Nested workflow resolution now passes runId to getNestedWorkflow and
resolveWorkflow.
- Workflow event processor rebuilt resumeLabels and suspend payload
propagation; adjusted foreach aggregation and merge behavior when
storage updates are absent.
- In-memory workflow storage replaced JSON-serialize deep-copy with a
cycle-safe deep clone preserving Dates, Errors, Maps/Sets, prototypes,
typed arrays, etc.
- Tests / tooling
- Added suspend/resume test to validate resuming a suspended nested
workflow step by label and updated many tests to run against an evented
Mastra (InMemoryStore + EventEmitterPubSub) with worker lifecycle
management helpers (createTestMastra, start/stop workers).
- Multiple test updates to use real InMemoryStore + evented pubsub
instead of mocked storage or missing worker lifecycles.
- Minor / UX
- Updated background-task generated system prompt to clarify _background
behavior and placeholder result guidance.
- stream/loop runtime: distinguishes "pre-run" queued signals from
normal "pending" signals and exposes drainPendingSignals(runId, scope?)
with scope 'pending'|'pre-run'; stream lifecycle registers/unregisters
run-scoped internal workflows to prevent leakage on suspend.
- Risk / review notes
- Structural and high-impact refactor touching core agent loop, workflow
engine integration, storage cloning, and Mastra internals—review effort:
high in multiple areas (agent, workflows, mastra, storage, evented
processor).
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/mastra-ai/mastra/pull/16796?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Mastra Code (anthropic/claude-opus-4-6) <noreply@mastra.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Abhi Aiyer <abhi@mastra.ai>
Co-authored-by: Abhi Aiyer <abhiaiyer91@gmail.com>1 parent 6aa6168 commit 493a328
117 files changed
Lines changed: 7320 additions & 4761 deletions
File tree
- .changeset
- e2e-tests
- client-js/_test-utils/src
- monorepo
- integrations/brightdata/src
- __tests__
- mastracode/src
- observability/mastra/src/__snapshots__
- packages
- agent-builder/integration-tests
- core
- __recordings__/core-src-background-tasks-background-tasks.e2e
- src
- agent
- __tests__
- workflows/prepare-stream
- background-tasks
- evals
- run
- llm/model
- loop
- __snapshots__
- network
- test-utils
- workflows
- agentic-execution
- agentic-loop
- mastra
- processors
- processors
- storage
- domains/workflows
- stream/base
- tools
- workflows
- __tests__
- evented
- workflow-event-processor
- scheduler
- editor/src
- mcp/integration-tests
- memory/integration-tests
- server/src/server/handlers
- stores
- libsql/src/storage
- db
- domains/workflows
- pg/src/storage/domains/workflows
- workflows
- _test-utils/src
- domains
- inngest/src
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
104 | 104 | | |
105 | 105 | | |
106 | 106 | | |
107 | | - | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
108 | 114 | | |
109 | 115 | | |
110 | | - | |
| 116 | + | |
111 | 117 | | |
112 | 118 | | |
113 | 119 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
126 | 126 | | |
127 | 127 | | |
128 | 128 | | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
129 | 133 | | |
130 | 134 | | |
131 | 135 | | |
| |||
181 | 185 | | |
182 | 186 | | |
183 | 187 | | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
184 | 192 | | |
185 | 193 | | |
186 | 194 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
19 | | - | |
20 | | - | |
| 19 | + | |
21 | 20 | | |
22 | 21 | | |
23 | 22 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
61 | | - | |
62 | | - | |
63 | | - | |
| 61 | + | |
64 | 62 | | |
65 | 63 | | |
66 | 64 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
127 | 127 | | |
128 | 128 | | |
129 | 129 | | |
130 | | - | |
131 | | - | |
132 | | - | |
| 130 | + | |
133 | 131 | | |
134 | 132 | | |
135 | 133 | | |
136 | 134 | | |
137 | 135 | | |
138 | 136 | | |
139 | 137 | | |
140 | | - | |
141 | | - | |
142 | | - | |
| 138 | + | |
143 | 139 | | |
144 | 140 | | |
145 | 141 | | |
146 | 142 | | |
147 | 143 | | |
148 | | - | |
149 | | - | |
150 | | - | |
| 144 | + | |
151 | 145 | | |
152 | 146 | | |
153 | 147 | | |
154 | 148 | | |
155 | 149 | | |
156 | 150 | | |
157 | 151 | | |
158 | | - | |
159 | | - | |
160 | | - | |
| 152 | + | |
161 | 153 | | |
162 | 154 | | |
163 | 155 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
135 | 135 | | |
136 | 136 | | |
137 | 137 | | |
138 | | - | |
139 | | - | |
140 | | - | |
| 138 | + | |
141 | 139 | | |
142 | 140 | | |
143 | 141 | | |
| |||
152 | 150 | | |
153 | 151 | | |
154 | 152 | | |
155 | | - | |
156 | | - | |
157 | | - | |
| 153 | + | |
158 | 154 | | |
159 | 155 | | |
160 | 156 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
843 | 843 | | |
844 | 844 | | |
845 | 845 | | |
| 846 | + | |
| 847 | + | |
846 | 848 | | |
847 | 849 | | |
848 | 850 | | |
| |||
853 | 855 | | |
854 | 856 | | |
855 | 857 | | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
856 | 861 | | |
857 | 862 | | |
858 | 863 | | |
| |||
869 | 874 | | |
870 | 875 | | |
871 | 876 | | |
| 877 | + | |
| 878 | + | |
872 | 879 | | |
873 | 880 | | |
874 | 881 | | |
| |||
879 | 886 | | |
880 | 887 | | |
881 | 888 | | |
| 889 | + | |
| 890 | + | |
| 891 | + | |
882 | 892 | | |
883 | 893 | | |
884 | 894 | | |
| |||
0 commit comments