-
Fix model-level and runtime header support for LLM calls (#11275)
This fixes a bug where custom headers configured on models (like anthropic-beta) were not being passed through to the underlying AI SDK calls. The fix properly handles headers from multiple sources with correct priority:
Header Priority (low to high):
- Model config headers - Headers set in model configuration
- ModelSettings headers - Runtime headers that override model config
- Provider-level headers - Headers baked into AI SDK providers (not overridden)
Examples that now work:
// Model config headers
new Agent({
model: {
id: 'anthropic/claude-4-5-sonnet',
headers: { 'anthropic-beta': 'context-1m-2025-08-07' },
},
});
// Runtime headers override config
agent.generate('...', {
modelSettings: { headers: { 'x-custom': 'runtime-value' } },
});
// Provider-level headers preserved
const openai = createOpenAI({ headers: { 'openai-organization': 'org-123' } });
new Agent({ model: openai('gpt-4o-mini') });
-
Fixed AbortSignal not propagating from parent workflows to nested sub-workflows in the evented workflow engine. (#11142)
Previously, canceling a parent workflow did not stop nested sub-workflows, causing them to continue running and consuming resources after the parent was canceled.
Now, when you cancel a parent workflow, all nested sub-workflows are automatically canceled as well, ensuring clean termination of the entire workflow tree.
Example:
const parentWorkflow = createWorkflow({ id: 'parent-workflow' }).then(someStep).then(nestedChildWorkflow).commit();
const run = await parentWorkflow.createRun();
const resultPromise = run.start({ inputData: { value: 5 } });
// Cancel the parent workflow - nested workflows will also be canceled
await run.cancel();
// or use: run.abortController.abort();
const result = await resultPromise;
// result.status === 'canceled'
// All nested child workflows are also canceled
Related to #11063
-
Fix empty overrideScorers causing error instead of skipping scoring (#11257)
When overrideScorers was passed as an empty object {}, the agent would throw a "No scorers found" error. Now an empty object explicitly skips scoring, while undefined continues to use default scorers.
-
feat: Add field filtering and nested workflow control to workflow execution result endpoint (#11246)
Adds two optional query parameters to /api/workflows/:workflowId/runs/:runId/execution-result endpoint:
fields: Request only specific fields (e.g., status, result, error)
withNestedWorkflows: Control whether to fetch nested workflow data
This significantly reduces response payload size and improves response times for large workflows.
Server Endpoint Usage
# Get only status (minimal payload - fastest)
GET /api/workflows/:workflowId/runs/:runId/execution-result?fields=status
# Get status and result
GET /api/workflows/:workflowId/runs/:runId/execution-result?fields=status,result
# Get all fields but without nested workflow data (faster)
GET /api/workflows/:workflowId/runs/:runId/execution-result?withNestedWorkflows=false
# Get only specific fields without nested workflow data
GET /api/workflows/:workflowId/runs/:runId/execution-result?fields=status,steps&withNestedWorkflows=false
# Get full data (default behavior)
GET /api/workflows/:workflowId/runs/:runId/execution-result
Client SDK Usage
import { MastraClient } from '@mastra/client-js';
const client = new MastraClient({ baseUrl: 'http://localhost:4111' });
const workflow = client.getWorkflow('myWorkflow');
// Get only status (minimal payload - fastest)
const statusOnly = await workflow.runExecutionResult(runId, {
fields: ['status'],
});
console.log(statusOnly.status); // 'success' | 'failed' | 'running' | etc.
// Get status and result
const statusAndResult = await workflow.runExecutionResult(runId, {
fields: ['status', 'result'],
});
// Get all fields but without nested workflow data (faster)
const resultWithoutNested = await workflow.runExecutionResult(runId, {
withNestedWorkflows: false,
});
// Get specific fields without nested workflow data
const optimized = await workflow.runExecutionResult(runId, {
fields: ['status', 'steps'],
withNestedWorkflows: false,
});
// Get full execution result (default behavior)
const fullResult = await workflow.runExecutionResult(runId);
Core API Changes
The Workflow.getWorkflowRunExecutionResult method now accepts an options object:
await workflow.getWorkflowRunExecutionResult(runId, {
withNestedWorkflows: false, // default: true, set to false to skip nested workflow data
fields: ['status', 'result'], // optional field filtering
});
-
Removed a debug log that printed large Zod schemas, resulting in cleaner console output when using agents with memory enabled. (#11279)
-
Set externals: true as the default for mastra build and cloud-deployer to reduce bundle issues with native dependencies. (0dbf199)
Note: If you previously relied on the default bundling behavior (all dependencies bundled), you can explicitly set externals: false in your bundler configuration.
-
Fix delayed promises rejecting when stream suspends on tool-call-approval (#11278)
When a stream ends in suspended state (e.g., requiring tool approval), the delayed promises like toolResults, toolCalls, text, etc. now resolve with partial results instead of rejecting with an error. This allows consumers to access data that was produced before the suspension.
Also improves generic type inference for LLMStepResult and related types throughout the streaming infrastructure.