Skip to content

feat(sdk-agents): add resume and structured output support#17580

Merged
TheIsrael1 merged 8 commits into
mainfrom
research/sdk-agents-resume-structured-output
Jun 8, 2026
Merged

feat(sdk-agents): add resume and structured output support#17580
TheIsrael1 merged 8 commits into
mainfrom
research/sdk-agents-resume-structured-output

Conversation

@TheIsrael1

@TheIsrael1 TheIsrael1 commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Depends on #17525 and should merge after that PR.

This adds provider-native resume support for the Claude, Cursor, and OpenAI SDK agent wrappers without changing Mastra core APIs. The SDK agents now implement Mastra's existing resumeGenerate/resumeStream methods by accepting provider-specific resumeData with a message payload.

Example:

await claudeAgent.resumeStream({
  message: "Continue from here",
  sessionId: "claude-session-id",
});

Claude maps resumeData to Claude session resume/continue options. Cursor can reuse the wrapped SDK agent or resume a Cursor agent by id. OpenAI maps resumeData to previousResponseId, conversationId, or session.

Also keeps structured output coverage for Claude and OpenAI, while Cursor fails clearly when structuredOutput is requested because the Cursor SDK does not expose a native schema output API.

Validated with package-level tests, builds, lints, and git diff check.

ELI5

This PR teaches Mastra's AI agent wrappers for Claude, Cursor, and OpenAI how to remember conversations and pick up where they left off. It also lets them return structured data (like JSON objects) instead of just text. If you try to use structured output with Cursor, it tells you clearly that Cursor doesn't support that yet.


Overview

This PR extends the Claude, Cursor, and OpenAI SDK agent wrappers with two key capabilities: provider-native resume support and structured output handling. The implementation leverages each provider's native capabilities without changing Mastra's core APIs, maintaining backward compatibility while enabling advanced conversation and output handling patterns.

Provider-Native Resume Support

All three agent SDKs now implement resumeGenerate and resumeStream methods that accept provider-specific resume data payloads:

  • Claude: Maps resumeData to Claude's session-based resume options (using resume: 'session-id' for generation and continue: true for streaming continuation)
  • Cursor: Supports resuming either the previously wrapped agent or looking up an agent by ID via CursorAgent.resume, then continues the conversation with provided messages
  • OpenAI: Maps resume data to OpenAI's continuation identifiers (conversationId, previousResponseId, or session)

Each implementation validates resume input shapes to prevent misconfiguration and provides clear error messages when invalid resume data is passed.

Structured Output Support

Structured output support was implemented with provider-native handling:

  • Claude & OpenAI: Full support for returning validated JSON objects alongside text. Both providers configure their respective SDKs to output structured data using JSON schemas and extract the resulting objects for exposure via result.object
  • Cursor: Explicitly rejects structured output requests with a clear error message because the Cursor SDK does not expose a native schema output API

Supporting utilities were added to all three providers for schema validation, JSON parsing, and error handling with configurable strategies (fallback, warn, or throw).

Implementation Details

Claude Agent Updates

  • Refactored internal runners to accept wrapper run options and merge per-call SDK options
  • Added resumeGenerate and resumeStream methods with resume data validation
  • Updated generate and stream to pass structured output requests through to Claude SDK and extract results
  • Added getClaudeStructuredOutput helper to centralize extraction of structured outputs from Claude messages
  • Extended utilities with structured output helpers for schema validation and JSON parsing

Cursor Agent Updates

  • Restructured CursorAgentOptions into a union type that cleanly separates three creation modes (wrap existing agent, wrap agent factory, or create from options)
  • Added resumeGenerate and resumeStream methods supporting both agent reuse and agent lookup by ID
  • Added assertStructuredOutputUnsupported validation to fail early with clear messaging when structured output is requested
  • Updated internal routing through generateWithAgent and streamWithAgent helpers
  • Extended utilities to propagate optional object fields through stream generation

OpenAI Agent Updates

  • Added resumeGenerate and resumeStream methods that validate resume data and merge identifiers into run options
  • Refactored agent execution to centralize run options creation via createOpenAIRunOptions
  • Updated structured output handling to clone/configure the agent with schema information and extract validated objects from results
  • Removed the prior getAbortSignal helper in favor of integrated signal handling in createOpenAIRunOptions
  • Extended utilities with structured output schema and validation helpers

Testing Coverage

Comprehensive test coverage was added across all three providers:

  • Test constants standardize model usage (e.g., TEST_CLAUDE_MODEL)
  • Claude tests verify resumeGenerate and resumeStream mapping and validate structured output extraction
  • Cursor tests verify resume with agent reuse and agent lookup, plus structured output rejection
  • OpenAI tests verify resume data mapping to continuation options and structured output handling
  • Validation tests confirm mixed/invalid resume inputs are rejected appropriately

Files Modified

  • .changeset/bright-readers-hunt.md: Release notes documenting all new features
  • agent-sdks/claude/src/: Implementation and comprehensive test coverage for resume and structured output
  • agent-sdks/cursor/src/: Implementation with explicit structured output rejection and resume support
  • agent-sdks/openai/src/: Implementation with full structured output and resume support
  • Corresponding utils.ts files: Shared utilities for structured output handling and stream generation

@changeset-bot

changeset-bot Bot commented Jun 4, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f1a3b2d

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

This PR includes changesets to release 3 packages
Name Type
@mastra/claude Minor
@mastra/cursor Minor
@mastra/openai Minor

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 4, 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 8, 2026 11:00am
mastra-playground-ui Ready Ready Preview, Comment Jun 8, 2026 11:00am

Request Review

@coderabbitai

coderabbitai Bot commented Jun 4, 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: 24d62ade-4886-4aa4-9178-14ee9cadea1f

📥 Commits

Reviewing files that changed from the base of the PR and between f43700e and f1a3b2d.

📒 Files selected for processing (4)
  • .changeset/bright-readers-hunt.md
  • agent-sdks/claude/src/index.test.ts
  • agent-sdks/claude/src/index.ts
  • agent-sdks/openai/src/index.ts
✅ Files skipped from review due to trivial changes (1)
  • .changeset/bright-readers-hunt.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • agent-sdks/claude/src/index.test.ts
  • agent-sdks/openai/src/index.ts
  • agent-sdks/claude/src/index.ts

Walkthrough

This PR adds provider-native structured output support to Claude and OpenAI SDK agents, introduces resume capabilities across all three agent SDKs, and enforces that Cursor SDK agents reject structured output requests. Release notes document these changes with TypeScript examples showing the new resumeGenerate/resumeStream and structuredOutput APIs.

Changes

Agent SDK Enhancements

Layer / File(s) Summary
Release Notes and Documentation
.changeset/bright-readers-hunt.md
Changeset marks @mastra/claude, @mastra/cursor, and @mastra/openai as minor and documents structured output support for Claude/OpenAI, resume APIs for all three agents, Cursor's structured output rejection, and includes TypeScript examples demonstrating the new functionality.
Claude SDK: Structured Output & Resume Support
agent-sdks/claude/src/index.ts, agent-sdks/claude/src/utils.ts, agent-sdks/claude/src/index.test.ts, agent-sdks/claude/src/observability.test.ts
Claude wrapper adds structuredOutput configuration via ClaudeSDKAgentRunOptions, re-exports ClaudeSDKOptions, and introduces resumeGenerate/resumeStream methods that map resume data into Claude SDK session/continue options. Both generate and stream paths extract structured_output from Claude results and compute final object payloads. Utils add structured output helpers for schema extraction, prompt injection, and JSON validation. Tests verify structured output mapping via outputFormat, resume session/continue flows, and invalid resume data rejection; observability tests standardize model references.
Cursor SDK: Resume with Structured Output Rejection
agent-sdks/cursor/src/index.ts, agent-sdks/cursor/src/utils.ts, agent-sdks/cursor/src/index.test.ts
Cursor wrapper introduces CursorSDKAgentResumeData type, refactors CursorAgentOptions into a discriminated union constraining creation modes, adds resumeGenerate/resumeStream methods that validate resume data and resolve agents via CursorAgent.resume, and asserts structured output unsupported before generate/stream execution. Utils thread optional object payload through stream finalization. Tests verify agent reuse when agentId is omitted, resume lookup when provided, and structured output rejection with clear error messaging.
OpenAI SDK: Structured Output & Resume Support
agent-sdks/openai/src/index.ts, agent-sdks/openai/src/utils.ts, agent-sdks/openai/src/index.test.ts
OpenAI wrapper introduces OpenAISDKAgentResumeData type with resume identifiers (previousResponseId, conversationId, session), adds resumeGenerate/resumeStream methods that merge resume data into run options, and clones agents with json_schema output type when structured output is requested. Both paths extract finalOutput and compute object via validation. Centralized createOpenAIRunOptions builds run configuration including abort signal and resume identifiers. Utils add structured output schema handling and validation. Tests verify agent cloning with output type, json_schema schema passing, continuation identifier propagation, and resume/stream behavior.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • mastra-ai/mastra#17525: Extends existing OpenAI SDK agent wrapper with structured output and resume capabilities.
  • mastra-ai/mastra#16906: Introduces the Claude and Cursor SDK agent wrappers that this PR extends with structured output and resume support.

Suggested reviewers

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

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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 'feat(sdk-agents): add resume and structured output support' is concise (58 chars), uses imperative mood, proper capitalization, and clearly describes the main feature additions to the SDK agents module.
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 research/sdk-agents-resume-structured-output

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@TheIsrael1 TheIsrael1 force-pushed the research/sdk-agents-resume-structured-output branch from 2a73634 to 65080f5 Compare June 4, 2026 17:11
@TheIsrael1 TheIsrael1 changed the title feat(sdk-agents): add provider-native resume feat(sdk-agents): add resume and structured output support Jun 4, 2026
@vercel vercel Bot temporarily deployed to Preview – mastra-docs-1.x June 4, 2026 17:34 Inactive
@vercel vercel Bot temporarily deployed to Preview – mastra-playground-ui June 4, 2026 17:34 Inactive
Base automatically changed from research/codex-sdk-agent to main June 5, 2026 14:43
Ehindero Israel added 2 commits June 5, 2026 16:22
Add provider-native resume support behind the existing resumeGenerate and resumeStream methods for Claude, Cursor, and OpenAI SDK agents.\n\nAlso add provider-native structured output support for Claude and OpenAI, and keep Cursor structured output unsupported with a clear error because the Cursor SDK has no native schema output API.
@vercel vercel Bot temporarily deployed to Preview – mastra-playground-ui June 5, 2026 15:31 Inactive
@vercel vercel Bot temporarily deployed to Preview – mastra-docs-1.x June 5, 2026 15:31 Inactive
@dane-ai-mastra

dane-ai-mastra Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

PR triage

Linked issue check skipped for core contributor @TheIsrael1.


PR complexity score

Factor Value Score impact
Files changed 11 +22
Lines changed 1129 +60
Author merged PRs 566 -20
Test files changed Yes -10
Final score 52

Applied label: complexity: high


Changed test gate

Changed tests passed against the base branch; they should fail before the PR code is applied.

Label: tests: failing ❌

@dane-ai-mastra dane-ai-mastra Bot added the tests: failing ❌ Changed tests passed against base label Jun 5, 2026

@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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
agent-sdks/openai/src/index.test.ts (1)

8-8: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Swap the hardcoded OpenAI model ID for a placeholder token.

gpt-5.1 is a literal model ID in a test constant; use a token from the docs model-token registry instead.

[potential_issue]

As per coding guidelines: for **/*.{ts,tsx,md,mdx,json}, model names/IDs in tests must use placeholder tokens from docs/src/plugins/remark-model-tokens/models.ts.

🤖 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 `@agent-sdks/openai/src/index.test.ts` at line 8, The test constant
TEST_OPENAI_MODEL currently contains a hardcoded model ID; update the value of
TEST_OPENAI_MODEL in index.test.ts to use the placeholder token defined in
docs/src/plugins/remark-model-tokens/models.ts (replace the literal 'gpt-5.1'
with the appropriate exported model token name from that registry) so tests
follow the model-token convention; keep the constant name TEST_OPENAI_MODEL and
import or reference the documented token instead of the literal string.
🧹 Nitpick comments (1)
agent-sdks/openai/src/index.ts (1)

169-169: 💤 Low value

Type assertion as any for structuredOutput may hide type mismatches.

The casts on lines 169 and 209 bypass TypeScript's type checking for the structuredOutput option. Consider defining proper type compatibility or using a more specific assertion.

Also applies to: 209-209

🤖 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 `@agent-sdks/openai/src/index.ts` at line 169, The code is using a blanket `as
any` cast for the structuredOutput option (seen where options: {
...telemetry.outputOptions(), structuredOutput: options?.structuredOutput as any
}) which hides type mismatches; replace the `as any` by aligning types properly:
introduce or import the correct StructuredOutput type/interface (or make the
surrounding options generic) and cast to that specific type instead of any,
update the call site that merges telemetry.outputOptions() to accept/return the
matching structuredOutput type, and apply the same fix at the other occurrence
around the second structuredOutput usage (line with the other cast) so both use
a specific interface or generic rather than `any`.
🤖 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.

Inline comments:
In @.changeset/bright-readers-hunt.md:
- Line 7: Add a short public API usage example to the changeset describing the
new features: include a minimal snippet showing how to call resumeGenerate and
resumeStream with provider-specific resumeData (showing a message payload shape)
and an example call that requests structuredOutput (including the
structuredOutput option and expected response shape) so consumers know the call
shape for SDK agents and the cursor SDK failure case. Reference the symbols
resumeGenerate, resumeStream, structuredOutput and indicate that the example
covers both provider-native resumeData message payloads and the structuredOutput
call shape for OpenAI/Claude SDK agents.

In `@agent-sdks/claude/src/index.ts`:
- Around line 242-245: validateClaudeResumeData currently accepts payloads where
a non-string sessionId coexists with continue: true because the OR check lets
the continue branch pass; update validation to enforce mutually exclusive
shapes: if 'sessionId' is present, require typeof resumeData.sessionId ===
'string' and reject any payload that also contains 'continue'; otherwise if
'continue' is present require resumeData.continue === true and reject any
payload that also contains 'sessionId'. Update both validateClaudeResumeData and
createClaudeResumeRunOptions logic (referencing resumeData, sessionId, and
continue) so a mixed/invalid shape is rejected rather than forwarded into
sdkOptions.resume.

---

Outside diff comments:
In `@agent-sdks/openai/src/index.test.ts`:
- Line 8: The test constant TEST_OPENAI_MODEL currently contains a hardcoded
model ID; update the value of TEST_OPENAI_MODEL in index.test.ts to use the
placeholder token defined in docs/src/plugins/remark-model-tokens/models.ts
(replace the literal 'gpt-5.1' with the appropriate exported model token name
from that registry) so tests follow the model-token convention; keep the
constant name TEST_OPENAI_MODEL and import or reference the documented token
instead of the literal string.

---

Nitpick comments:
In `@agent-sdks/openai/src/index.ts`:
- Line 169: The code is using a blanket `as any` cast for the structuredOutput
option (seen where options: { ...telemetry.outputOptions(), structuredOutput:
options?.structuredOutput as any }) which hides type mismatches; replace the `as
any` by aligning types properly: introduce or import the correct
StructuredOutput type/interface (or make the surrounding options generic) and
cast to that specific type instead of any, update the call site that merges
telemetry.outputOptions() to accept/return the matching structuredOutput type,
and apply the same fix at the other occurrence around the second
structuredOutput usage (line with the other cast) so both use a specific
interface or generic rather than `any`.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1cef1f9e-a734-4370-9b1c-04d080785e60

📥 Commits

Reviewing files that changed from the base of the PR and between 65799d4 and b8043f2.

📒 Files selected for processing (11)
  • .changeset/bright-readers-hunt.md
  • agent-sdks/claude/src/index.test.ts
  • agent-sdks/claude/src/index.ts
  • agent-sdks/claude/src/observability.test.ts
  • agent-sdks/claude/src/utils.ts
  • agent-sdks/cursor/src/index.test.ts
  • agent-sdks/cursor/src/index.ts
  • agent-sdks/cursor/src/utils.ts
  • agent-sdks/openai/src/index.test.ts
  • agent-sdks/openai/src/index.ts
  • agent-sdks/openai/src/utils.ts

Comment thread .changeset/bright-readers-hunt.md
Comment thread agent-sdks/claude/src/index.ts Outdated
@TheIsrael1 TheIsrael1 merged commit 1c541a3 into main Jun 8, 2026
73 checks passed
@TheIsrael1 TheIsrael1 deleted the research/sdk-agents-resume-structured-output branch June 8, 2026 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

complexity: high High-complexity PR tests: green ✅ Changed tests failed against base as expected

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants