feat(sdk-agents): add resume and structured output support#17580
Conversation
🦋 Changeset detectedLatest commit: f1a3b2d The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
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 |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (3)
WalkthroughThis 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 ChangesAgent SDK Enhancements
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
2a73634 to
65080f5
Compare
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.
c6b3795 to
559848c
Compare
PR triageLinked issue check skipped for core contributor @TheIsrael1. PR complexity score
Applied label: Changed test gateChanged tests passed against the base branch; they should fail before the PR code is applied. Label: |
There was a problem hiding this comment.
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 winSwap the hardcoded OpenAI model ID for a placeholder token.
gpt-5.1is 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 fromdocs/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 valueType assertion
as anyfor structuredOutput may hide type mismatches.The casts on lines 169 and 209 bypass TypeScript's type checking for the
structuredOutputoption. 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
📒 Files selected for processing (11)
.changeset/bright-readers-hunt.mdagent-sdks/claude/src/index.test.tsagent-sdks/claude/src/index.tsagent-sdks/claude/src/observability.test.tsagent-sdks/claude/src/utils.tsagent-sdks/cursor/src/index.test.tsagent-sdks/cursor/src/index.tsagent-sdks/cursor/src/utils.tsagent-sdks/openai/src/index.test.tsagent-sdks/openai/src/index.tsagent-sdks/openai/src/utils.ts
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:
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
resumeGenerateandresumeStreammethods that accept provider-specific resume data payloads:resumeDatato Claude's session-based resume options (usingresume: 'session-id'for generation andcontinue: truefor streaming continuation)CursorAgent.resume, then continues the conversation with provided messagesconversationId,previousResponseId, orsession)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:
result.objectSupporting 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
resumeGenerateandresumeStreammethods with resume data validationgenerateandstreamto pass structured output requests through to Claude SDK and extract resultsgetClaudeStructuredOutputhelper to centralize extraction of structured outputs from Claude messagesCursor Agent Updates
CursorAgentOptionsinto a union type that cleanly separates three creation modes (wrap existing agent, wrap agent factory, or create from options)resumeGenerateandresumeStreammethods supporting both agent reuse and agent lookup by IDassertStructuredOutputUnsupportedvalidation to fail early with clear messaging when structured output is requestedgenerateWithAgentandstreamWithAgenthelpersobjectfields through stream generationOpenAI Agent Updates
resumeGenerateandresumeStreammethods that validate resume data and merge identifiers into run optionscreateOpenAIRunOptionsgetAbortSignalhelper in favor of integrated signal handling increateOpenAIRunOptionsTesting Coverage
Comprehensive test coverage was added across all three providers:
TEST_CLAUDE_MODEL)resumeGenerateandresumeStreammapping and validate structured output extractionFiles Modified
.changeset/bright-readers-hunt.md: Release notes documenting all new featuresagent-sdks/claude/src/: Implementation and comprehensive test coverage for resume and structured outputagent-sdks/cursor/src/: Implementation with explicit structured output rejection and resume supportagent-sdks/openai/src/: Implementation with full structured output and resume supportutils.tsfiles: Shared utilities for structured output handling and stream generation