') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); Add allowReservedAttributes option to start() by pranaygp · Pull Request #2385 · vercel/workflow · GitHub
Skip to content

Add allowReservedAttributes option to start() - #2385

Merged
pranaygp merged 2 commits into
mainfrom
start-allow-reserved-attributes
Jun 12, 2026
Merged

Add allowReservedAttributes option to start()#2385
pranaygp merged 2 commits into
mainfrom
start-allow-reserved-attributes

Conversation

@pranaygp

@pranaygppranaygp commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary

#2226 added start(..., { attributes }) to seed plaintext attributes at run creation, but always validates them with the reserved $ prefix disallowed and exposes no opt-out. That leaves a gap relative to the rest of the attributes surface: experimental_setAttributes accepts { allowReservedAttributes: true } for framework-level callers, and the run_created / run_started event schemas plus the local and Postgres worlds already accept and validate the flag — so the wire format supports seeding reserved attributes at creation, just not through the public start() API.

This closes that gap by threading the same option through start():

  • StartOptions.allowReservedAttributes (same semantics and guidance as the experimental_setAttributes option) is passed to client-side validation and forwarded on the run_created eventData.
  • The flag rides along in the queue runInput (new optional field on RunInputSchema) and is forwarded into the run_started eventData, so the resilient-start path (run bootstrapped from the queue message when run_created was missed) validates the seeded attributes identically to the original attempt.

No world changes needed — world-local and world-postgres already honor allowReservedAttributes on both the run_created and run_started creation paths.

This unblocks framework-level use cases like cross-run lineage (#2153, $rootRunId / $parentRunId) that need reserved keys present from creation time.

Testing

  • pnpm --filter @workflow/core test
  • pnpm exec turbo run typecheck test --filter=@workflow/world --filter=@workflow/core --filter=@workflow/world-local
  • New unit tests: reserved keys + flag accepted and forwarded on both run_created and the queue runInput; flag absent from both payloads when not requested; size/cap validation still enforced with the flag set; reserved keys still rejected without the flag (existing test).
  • New e2e test (run locally against the nextjs-turbopack dev server): start() with a $-prefixed key + allowReservedAttributes: true completes, the reserved key is persisted on the run, and it survives the workflow's own attr_set writes.
  • workflow-server already validates and honors the flag on initial run attributes (InitialRunAttributesSchema) and forwards it on its own resilient path, so no server change is needed.

Docs Preview

Pagev5
start() API reference/v5/docs/api-reference/workflow-api/start

🤖 Generated with Claude Code

experimental_setAttributes already exposes allowReservedAttributes for
framework-level callers that own a $-prefixed sub-namespace, and the
run_created / run_started event schemas plus the local and Postgres
worlds already accept and validate the flag. start() was the one gap:
it always validated initial attributes with the reserved prefix
disallowed and had no way to opt out, so framework code could not seed
reserved attributes at run creation.
Thread the option through start():
- StartOptions.allowReservedAttributes, passed to client-side
validation and forwarded on the run_created eventData
- carried in the queue runInput (new RunInputSchema field) and
forwarded to run_started so the resilient/lazy run creation path
validates identically
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@pranaygp
pranaygp requested a review from a team as a code ownerJune 12, 2026 19:55
CopilotAI review requested due to automatic review settings June 12, 2026 19:55
@vercel

vercelBot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

@changeset-bot

changeset-botBot commented Jun 12, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 0698fa2

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

This PR includes changesets to release 21 packages
NameType
workflowMinor
@workflow/coreMinor
@workflow/worldMinor
@workflow/aiMajor
@workflow/world-testingPatch
@workflow/buildersPatch
@workflow/cliPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/vitestPatch
@workflow/web-sharedPatch
@workflow/webPatch
@workflow/world-localPatch
@workflow/world-postgresPatch
@workflow/world-vercelPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

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

@github-actions

github-actionsBot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express0.043s (+59.0% 🔺)1.007s (~)0.964s101.00x
💻 LocalNitro0.046s (+13.9% 🔺)1.006s (~)0.961s101.06x
💻 LocalNext.js (Turbopack)0.064s (+5.0%)1.006s (~)0.942s101.47x
🐘 PostgresNitro0.064s (-4.8%)1.012s (~)0.948s101.47x
🐘 PostgresExpress0.066s (+17.1% 🔺)1.012s (~)0.946s101.52x
🐘 PostgresNext.js (Turbopack)0.072s (+5.4% 🔺)1.013s (~)0.941s101.65x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro0.321s (+10.6% 🔺)2.250s (+0.6%)1.929s101.00x
▲ VercelNext.js (Turbopack)0.322s (+16.4% 🔺)2.625s (-9.4% 🟢)2.304s101.00x
▲ VercelExpress0.372s (+25.1% 🔺)2.268s (-7.6% 🟢)1.896s101.16x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

workflow with 1 step

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.093s (+2.9%)2.007s (~)0.914s101.00x
💻 LocalNitro1.098s (+0.5%)2.007s (~)0.909s101.00x
🐘 PostgresNitro1.116s (+0.8%)2.010s (~)0.894s101.02x
🐘 PostgresExpress1.117s (+0.6%)2.011s (~)0.894s101.02x
💻 LocalNext.js (Turbopack)1.140s (+0.6%)2.007s (~)0.867s101.04x
🐘 PostgresNext.js (Turbopack)1.152s (+1.4%)2.010s (~)0.857s101.05x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)1.589s (-1.0%)3.741s (-1.3%)2.151s101.00x
▲ VercelNitro1.656s (+2.8%)3.769s (+12.0% 🔺)2.113s101.04x
▲ VercelExpress1.662s (+2.8%)3.328s (-10.6% 🟢)1.666s101.05x

🔍 Observability: Next.js (Turbopack) | Nitro | Express

workflow with 10 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express10.521s (+1.3%)11.023s (~)0.502s31.00x
💻 LocalNitro10.551s (~)11.024s (~)0.473s31.00x
🐘 PostgresNitro10.575s (~)11.021s (~)0.446s31.01x
🐘 PostgresExpress10.578s (~)11.023s (~)0.445s31.01x
💻 LocalNext.js (Turbopack)10.763s (~)11.023s (~)0.260s31.02x
🐘 PostgresNext.js (Turbopack)10.836s (~)11.017s (~)0.181s31.03x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express13.317s (-2.5%)14.958s (-3.4%)1.642s31.00x
▲ VercelNext.js (Turbopack)13.887s (-2.3%)15.974s (-3.7%)2.087s21.04x
▲ VercelNitro14.350s (+6.5% 🔺)16.283s (+7.6% 🔺)1.933s21.08x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 25 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express13.761s (+2.9%)14.027s (~)0.266s51.00x
🐘 PostgresNitro13.794s (~)14.019s (~)0.225s51.00x
💻 LocalNitro13.827s (+0.5%)14.026s (~)0.199s51.00x
🐘 PostgresExpress13.876s (+0.5%)14.022s (~)0.146s51.01x
💻 LocalNext.js (Turbopack)14.324s (-0.6%)15.031s (~)0.707s41.04x
🐘 PostgresNext.js (Turbopack)14.500s (~)15.018s (~)0.518s41.05x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express20.596s (-2.0%)21.996s (-4.6%)1.400s31.00x
▲ VercelNext.js (Turbopack)21.466s (-2.6%)23.735s (-2.8%)2.269s31.04x
▲ VercelNitro21.679s (+6.2% 🔺)23.906s (+6.3% 🔺)2.227s31.05x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 50 sequential steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express12.497s (+6.8% 🔺)13.025s (+8.3% 🔺)0.528s71.00x
🐘 PostgresNitro12.596s (~)13.019s (~)0.423s71.01x
🐘 PostgresExpress12.632s (-2.3%)13.021s (-2.1%)0.389s71.01x
💻 LocalNitro12.642s (+2.0%)13.026s (~)0.384s71.01x
💻 LocalNext.js (Turbopack)13.593s (-0.7%)14.026s (~)0.433s71.09x
🐘 PostgresNext.js (Turbopack)13.761s (~)14.016s (~)0.255s71.10x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express27.486s (-14.3% 🟢)30.004s (-13.4% 🟢)2.519s31.00x
▲ VercelNitro28.733s (-9.7% 🟢)31.361s (-6.8% 🟢)2.628s31.05x
▲ VercelNext.js (Turbopack)29.520s (-16.5% 🟢)32.267s (-13.4% 🟢)2.747s31.07x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Nitro1.198s (-5.5% 🟢)2.007s (~)0.809s151.00x
🐘 PostgresNitro1.209s (-3.4%)2.008s (~)0.799s151.01x
🐘 PostgresExpress1.225s (+1.7%)2.008s (~)0.784s151.02x
💻 LocalExpress1.230s (+7.8% 🔺)2.006s (~)0.777s151.03x
🐘 PostgresNext.js (Turbopack)1.300s (+1.8%)2.007s (~)0.707s151.09x
💻 LocalNext.js (Turbopack)1.308s (-1.2%)2.006s (~)0.698s151.09x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.160s (-35.3% 🟢)3.447s (-33.0% 🟢)1.287s91.00x
▲ VercelNitro2.400s (-15.7% 🟢)3.896s (-15.6% 🟢)1.496s81.11x
▲ VercelNext.js (Turbopack)3.341s (-27.5% 🟢)5.290s (-20.2% 🟢)1.949s61.55x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.338s (-5.1% 🟢)2.509s (+4.8%)1.171s121.00x
🐘 PostgresExpress1.390s (+2.9%)2.592s (+8.3% 🔺)1.202s121.04x
🐘 PostgresNext.js (Turbopack)1.601s (~)2.224s (~)0.622s141.20x
💻 LocalExpress1.761s (+20.2% 🔺)2.005s (~)0.244s151.32x
💻 LocalNext.js (Turbopack)1.848s (+12.8% 🔺)2.073s (~)0.225s151.38x
💻 LocalNitro1.961s (+13.3% 🔺)2.317s (+15.5% 🔺)0.357s131.47x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.754s (+2.4%)5.659s (+12.1% 🔺)1.905s61.00x
▲ VercelNext.js (Turbopack)5.198s (+46.4% 🔺)10.210s (+84.4% 🔺)5.012s41.38x
▲ VercelExpress5.319s (+70.7% 🔺)7.562s (+60.6% 🔺)2.244s41.42x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Promise.all with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.568s (-3.2%)4.011s (-3.0%)2.443s81.00x
🐘 PostgresNitro1.653s (+4.8%)4.140s (+6.5% 🔺)2.487s81.05x
🐘 PostgresNext.js (Turbopack)3.345s (+5.7% 🔺)4.013s (-3.1%)0.668s82.13x
💻 LocalExpress4.879s (+79.6% 🔺)5.513s (+64.9% 🔺)0.634s63.11x
💻 LocalNext.js (Turbopack)5.100s (+6.3% 🔺)5.512s (+6.4% 🔺)0.412s63.25x
💻 LocalNitro5.792s (+22.7% 🔺)6.415s (+21.1% 🔺)0.623s53.69x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro3.797s (-27.3% 🟢)5.971s (-6.0% 🟢)2.174s61.00x
▲ VercelNext.js (Turbopack)4.600s (-4.8%)6.613s (~)2.013s51.21x
▲ VercelExpress4.946s (~)6.705s (-2.5%)1.759s51.30x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Promise.race with 10 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.208s (~)2.007s (~)0.799s151.00x
🐘 PostgresNext.js (Turbopack)1.286s (~)2.008s (~)0.722s151.06x
🐘 PostgresNitro1.296s (+8.0% 🔺)2.149s (+7.1% 🔺)0.853s141.07x
💻 LocalNext.js (Turbopack)1.442s (+3.6%)2.006s (~)0.565s151.19x
💻 LocalNitro1.577s (+4.8%)2.007s (~)0.430s151.31x
💻 LocalExpress1.594s (+27.0% 🔺)2.006s (~)0.413s151.32x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)2.484s (+1.9%)4.065s (~)1.581s81.00x
▲ VercelNitro2.564s (+5.2% 🔺)4.349s (+24.1% 🔺)1.784s81.03x
▲ VercelExpress2.882s (~)4.392s (-4.7%)1.510s71.16x

🔍 Observability: Next.js (Turbopack) | Nitro | Express

Promise.race with 25 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.353s (-0.9%)2.393s (~)1.040s131.00x
🐘 PostgresExpress1.429s (+2.8%)2.393s (+11.2% 🔺)0.964s131.06x
🐘 PostgresNext.js (Turbopack)1.602s (+7.7% 🔺)2.393s (+19.2% 🔺)0.791s131.18x
💻 LocalNext.js (Turbopack)1.960s (-4.3%)2.508s (~)0.548s121.45x
💻 LocalExpress2.050s (+29.0% 🔺)2.592s (+29.2% 🔺)0.541s121.52x
💻 LocalNitro2.183s (+5.0% 🔺)2.677s (+8.4% 🔺)0.494s121.61x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Next.js (Turbopack)2.868s (-14.1% 🟢)4.656s (-18.9% 🟢)1.788s71.00x
▲ VercelExpress2.880s (-18.8% 🟢)4.501s (-17.2% 🟢)1.621s71.00x
▲ VercelNitro2.906s (-44.5% 🟢)4.695s (-30.0% 🟢)1.790s71.01x

🔍 Observability: Next.js (Turbopack) | Express | Nitro

Promise.race with 50 concurrent steps

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express1.581s (-6.5% 🟢)4.011s (~)2.430s81.00x
🐘 PostgresNitro1.597s (-16.0% 🟢)4.297s (~)2.700s71.01x
🐘 PostgresNext.js (Turbopack)3.562s (-14.4% 🟢)4.442s (-8.8% 🟢)0.879s72.25x
💻 LocalNext.js (Turbopack)5.450s (+1.2%)6.015s (+2.8%)0.564s53.45x
💻 LocalExpress6.074s (+56.3% 🔺)6.619s (+55.4% 🔺)0.545s53.84x
💻 LocalNitro6.280s (+8.1% 🔺)6.619s (~)0.339s53.97x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express3.787s (-15.2% 🟢)5.586s (-13.7% 🟢)1.799s61.00x
▲ VercelNitro3.940s (+1.5%)6.138s (+12.3% 🔺)2.198s51.04x
▲ VercelNext.js (Turbopack)4.264s (-14.4% 🟢)6.468s (-5.6% 🟢)2.204s51.13x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.587s (+2.0%)1.006s (-1.7%)0.419s601.00x
🐘 PostgresNitro0.598s (+3.3%)1.040s (+1.7%)0.442s581.02x
💻 LocalExpress0.625s (+27.9% 🔺)1.022s (+1.5%)0.397s591.06x
💻 LocalNitro0.630s (+3.2%)1.005s (~)0.375s601.07x
💻 LocalNext.js (Turbopack)0.861s (-5.1% 🟢)1.021s (-5.1% 🟢)0.160s591.47x
🐘 PostgresNext.js (Turbopack)0.877s (+6.6% 🔺)1.024s (+1.8%)0.146s591.49x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro5.705s (-10.9% 🟢)7.581s (-4.1%)1.876s81.00x
▲ VercelNext.js (Turbopack)6.014s (+9.7% 🔺)7.626s (+2.9%)1.612s81.05x
▲ VercelExpress6.188s (+20.3% 🔺)7.605s (+11.3% 🔺)1.417s81.08x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.402s (+3.9%)2.029s (+1.1%)0.628s451.00x
🐘 PostgresExpress1.402s (+3.2%)2.007s (~)0.606s451.00x
💻 LocalNitro1.571s (+4.7%)2.007s (~)0.436s451.12x
💻 LocalExpress1.578s (+22.6% 🔺)2.006s (+1.2%)0.428s451.13x
🐘 PostgresNext.js (Turbopack)2.020s (+5.2% 🔺)2.442s (+16.3% 🔺)0.422s371.44x
💻 LocalNext.js (Turbopack)2.107s (-0.8%)2.976s (-1.1%)0.869s311.50x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express13.351s (-10.8% 🟢)15.025s (-11.5% 🟢)1.675s61.00x
▲ VercelNitro14.232s (~)16.647s (+6.9% 🔺)2.415s61.07x
▲ VercelNext.js (Turbopack)15.012s (-3.2%)17.433s (-1.0%)2.422s61.12x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro2.729s (+1.4%)3.111s (+1.7%)0.382s391.00x
🐘 PostgresExpress2.790s (~)3.163s (~)0.373s391.02x
💻 LocalExpress3.338s (+27.3% 🔺)4.043s (+30.0% 🔺)0.706s301.22x
💻 LocalNitro3.379s (+4.2%)4.009s (~)0.630s301.24x
🐘 PostgresNext.js (Turbopack)4.030s (+4.3%)4.626s (+11.6% 🔺)0.596s261.48x
💻 LocalNext.js (Turbopack)4.301s (-1.3%)5.011s (~)0.709s241.58x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express27.259s (~)29.765s (+2.2%)2.505s51.00x
▲ VercelNitro28.690s (+10.6% 🔺)31.821s (+15.1% 🔺)3.131s41.05x
▲ VercelNext.js (Turbopack)29.816s (~)32.522s (+2.4%)2.706s41.09x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.250s (~)1.006s (~)0.756s601.00x
🐘 PostgresExpress0.259s (+1.6%)1.006s (~)0.747s601.04x
🐘 PostgresNext.js (Turbopack)0.314s (+7.2% 🔺)1.006s (~)0.693s601.25x
💻 LocalExpress0.425s (+22.9% 🔺)1.004s (~)0.579s601.70x
💻 LocalNitro0.427s (-7.1% 🟢)1.005s (-1.6%)0.578s601.71x
💻 LocalNext.js (Turbopack)0.581s (+3.0%)1.022s (+1.7%)0.441s592.32x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Nitro2.103s (-14.4% 🟢)3.876s (-3.2%)1.773s161.00x
▲ VercelNext.js (Turbopack)2.326s (+1.0%)4.251s (+4.3%)1.926s151.11x
▲ VercelExpress2.535s (~)4.208s (-1.9%)1.673s151.21x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.423s (+6.6% 🔺)1.041s (+3.4%)0.618s871.00x
🐘 PostgresExpress0.425s (+3.8%)1.029s (-1.1%)0.604s881.00x
🐘 PostgresNext.js (Turbopack)0.631s (+9.5% 🔺)1.312s (+18.8% 🔺)0.681s691.49x
💻 LocalNitro2.134s (-5.0% 🟢)2.797s (+2.2%)0.663s335.05x
💻 LocalExpress2.210s (+46.2% 🔺)2.768s (+33.4% 🔺)0.558s335.23x
💻 LocalNext.js (Turbopack)2.521s (+5.8% 🔺)3.225s (+4.8%)0.705s285.96x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.870s (-24.5% 🟢)4.322s (-20.9% 🟢)1.452s211.00x
▲ VercelNitro3.105s (-17.9% 🟢)4.800s (-9.5% 🟢)1.695s191.08x
▲ VercelNext.js (Turbopack)3.283s (-13.5% 🟢)5.155s (-11.3% 🟢)1.872s181.14x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro0.817s (+2.3%)1.414s (+5.5% 🔺)0.597s861.00x
🐘 PostgresExpress0.840s (+3.2%)1.508s (+11.2% 🔺)0.668s801.03x
🐘 PostgresNext.js (Turbopack)3.067s (+15.8% 🔺)3.951s (+8.3% 🔺)0.884s313.75x
💻 LocalExpress9.917s (+45.1% 🔺)10.279s (+36.7% 🔺)0.362s1212.14x
💻 LocalNitro9.975s (+5.1% 🔺)10.530s (+4.1%)0.555s1212.21x
💻 LocalNext.js (Turbopack)10.500s (-4.5%)11.210s (-6.8% 🟢)0.710s1112.85x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express6.111s (-27.1% 🟢)7.777s (-23.1% 🟢)1.666s161.00x
▲ VercelNitro6.238s (-10.2% 🟢)7.969s (-5.9% 🟢)1.731s161.02x
▲ VercelNext.js (Turbopack)7.558s (-7.6% 🟢)9.489s (-6.2% 🟢)1.931s131.24x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Stream Benchmarks(includes TTFB metrics)
workflow with stream

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.167s (+4.8%)2.005s (~)0.010s (+83.9% 🔺)2.018s (~)0.851s101.00x
💻 LocalNitro1.171s (~)2.005s (~)0.013s (+21.2% 🔺)2.020s (~)0.849s101.00x
🐘 PostgresExpress1.171s (-0.8%)1.995s (~)0.001s (-15.4% 🟢)2.010s (~)0.839s101.00x
🐘 PostgresNitro1.177s (~)1.996s (~)0.001s (-7.7% 🟢)2.011s (~)0.834s101.01x
💻 LocalNext.js (Turbopack)1.204s (~)2.003s (~)0.012s (+19.8% 🔺)2.019s (~)0.815s101.03x
🐘 PostgresNext.js (Turbopack)1.246s (-0.9%)2.001s (~)0.001s (~)2.011s (~)0.765s101.07x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.305s (+4.2%)3.308s (~)1.345s (+11.0% 🔺)5.032s (~)2.727s101.00x
▲ VercelNitro2.443s (+10.2% 🔺)3.573s (+2.1%)0.769s (-30.3% 🟢)4.953s (-1.4%)2.510s101.06x
▲ VercelNext.js (Turbopack)2.621s (+18.8% 🔺)4.026s (+9.8% 🔺)0.803s (-20.7% 🟢)5.277s (+1.5%)2.655s101.14x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

stream pipeline with 5 transform steps (1MB)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
💻 Local🥇 Express1.583s (+12.3% 🔺)2.011s (~)0.013s (+36.9% 🔺)2.025s (~)0.442s301.00x
🐘 PostgresNitro1.586s (~)2.003s (~)0.005s (+2.0%)2.025s (~)0.440s301.00x
🐘 PostgresExpress1.595s (-0.7%)2.007s (~)0.005s (-5.0% 🟢)2.027s (~)0.432s301.01x
💻 LocalNitro1.624s (+2.4%)2.010s (~)0.013s (+1.8%)2.025s (~)0.401s301.03x
💻 LocalNext.js (Turbopack)1.724s (~)2.010s (~)0.014s (+20.1% 🔺)2.026s (~)0.303s301.09x
🐘 PostgresNext.js (Turbopack)1.848s (+4.4%)2.012s (~)0.005s (+42.3% 🔺)2.028s (~)0.180s301.17x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express5.946s (-11.4% 🟢)7.004s (-14.1% 🟢)0.203s (+4.2%)7.620s (-13.7% 🟢)1.674s81.00x
▲ VercelNitro5.966s (-1.2%)7.173s (+2.4%)0.327s (+64.8% 🔺)7.967s (+4.5%)2.001s81.00x
▲ VercelNext.js (Turbopack)6.121s (-3.7%)7.688s (-4.8%)0.251s (-21.7% 🟢)8.444s (-5.3% 🟢)2.323s81.03x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

10 parallel streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Express0.781s (-3.4%)1.028s (-2.8%)0.000s (-50.9% 🟢)1.065s (-1.4%)0.284s571.00x
🐘 PostgresNitro0.794s (-2.3%)1.062s (+1.3%)0.000s (-50.0% 🟢)1.078s (~)0.285s561.02x
🐘 PostgresNext.js (Turbopack)1.076s (+10.5% 🔺)1.538s (+10.9% 🔺)0.000s (+12.8% 🔺)1.548s (+11.1% 🔺)0.472s391.38x
💻 LocalNitro1.414s (-2.1%)2.014s (~)0.000s (+50.0% 🔺)2.016s (~)0.602s301.81x
💻 LocalExpress1.424s (+34.0% 🔺)2.014s (+14.8% 🔺)0.000s (-33.3% 🟢)2.016s (+14.8% 🔺)0.592s301.82x
💻 LocalNext.js (Turbopack)1.447s (-4.8%)2.013s (~)0.000s (+42.9% 🔺)2.016s (~)0.569s301.85x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express2.672s (-17.7% 🟢)3.912s (-13.6% 🟢)0.000s (NaN%)4.308s (-13.8% 🟢)1.636s141.00x
▲ VercelNitro2.864s (+3.1%)4.305s (+7.4% 🔺)0.000s (-100.0% 🟢)4.796s (+9.6% 🔺)1.933s131.07x
▲ VercelNext.js (Turbopack)2.975s (-5.6% 🟢)4.561s (-3.1%)0.000s (-100.0% 🟢)5.056s (-2.7%)2.081s121.11x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

fan-out fan-in 10 streams (1MB each)

💻 Local Development

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
🐘 Postgres🥇 Nitro1.595s (-0.6%)2.133s (~)0.000s (-100.0% 🟢)2.161s (-0.5%)0.567s291.00x
🐘 PostgresExpress1.634s (+1.2%)2.219s (+3.7%)0.000s (NaN%)2.236s (+3.8%)0.602s271.02x
🐘 PostgresNext.js (Turbopack)2.349s (+6.1% 🔺)2.857s (+4.6%)0.000s (NaN%)2.869s (+4.2%)0.521s211.47x
💻 LocalNext.js (Turbopack)2.843s (-7.2% 🟢)3.470s (-2.2%)0.001s (+11.6% 🔺)3.474s (-2.3%)0.630s181.78x
💻 LocalExpress3.088s (+46.0% 🔺)3.732s (+45.8% 🔺)0.001s (+111.8% 🔺)3.735s (+45.6% 🔺)0.647s171.94x
💻 LocalNitro3.270s (+1.8%)3.831s (-1.9%)0.001s (-46.7% 🟢)3.845s (-1.6%)0.575s162.05x

▲ Production (Vercel)

WorldFrameworkWorkflow TimeTTFBSlurpWall TimeOverheadSamplesvs Fastest
▲ Vercel🥇 Express4.481s (-1.5%)5.607s (-7.7% 🟢)0.000s (+Infinity% 🔺)6.021s (-7.8% 🟢)1.540s101.00x
▲ VercelNext.js (Turbopack)4.530s (-8.1% 🟢)5.888s (-7.2% 🟢)0.000s (NaN%)6.366s (-6.7% 🟢)1.836s101.01x
▲ VercelNitro4.664s (~)5.904s (+4.2%)0.000s (-100.0% 🟢)6.388s (+5.1% 🔺)1.724s101.04x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World🥇 Fastest FrameworkWins
💻 LocalExpress13/21
🐘 PostgresNitro15/21
▲ VercelExpress13/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework🥇 Fastest WorldWins
Express🐘 Postgres14/21
Next.js (Turbopack)🐘 Postgres13/21
Nitro🐘 Postgres16/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Redis + BullMQ: Community world (local development)
  • 🌐 Cloudflare: Community world (local development)
  • 🌐 MySQL: Community world (local development)
  • 🌐 Azure: Community world (local development)
  • 🌐 NATS JetStream: Community world (local development)
  • 🌐 Upstash: Community world (local development)

📋 View full workflow run

@github-actions

github-actionsBot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

🧪 E2E Test Results

All tests passed

Summary

PassedFailedSkippedTotal
✅ ▲ Vercel Production138702191606
✅ 💻 Local Development182502192044
✅ 📦 Local Production182502192044
✅ 🐘 Local Postgres181102332044
✅ 🪟 Windows14600146
✅ 📋 Other84401781022
Total7838010688906

Details by Category

✅ ▲ Vercel Production
AppPassedFailedSkipped
✅ astro120026
✅ example120026
✅ express120026
✅ fastify120026
✅ hono120026
✅ nextjs-turbopack14402
✅ nextjs-webpack14402
✅ nitro120026
✅ nuxt120026
✅ sveltekit13907
✅ vite120026
✅ 💻 Local Development
AppPassedFailedSkipped
✅ astro-stable121025
✅ express-stable121025
✅ fastify-stable121025
✅ hono-stable121025
✅ nextjs-turbopack-canary127019
✅ nextjs-turbopack-stable-lazy-discovery-disabled14600
✅ nextjs-turbopack-stable-lazy-discovery-enabled14600
✅ nextjs-webpack-canary127019
✅ nextjs-webpack-stable-lazy-discovery-disabled14600
✅ nextjs-webpack-stable-lazy-discovery-enabled14600
✅ nitro-stable121025
✅ nuxt-stable121025
✅ sveltekit-stable14006
✅ vite-stable121025
✅ 📦 Local Production
AppPassedFailedSkipped
✅ astro-stable121025
✅ express-stable121025
✅ fastify-stable121025
✅ hono-stable121025
✅ nextjs-turbopack-canary127019
✅ nextjs-turbopack-stable-lazy-discovery-disabled14600
✅ nextjs-turbopack-stable-lazy-discovery-enabled14600
✅ nextjs-webpack-canary127019
✅ nextjs-webpack-stable-lazy-discovery-disabled14600
✅ nextjs-webpack-stable-lazy-discovery-enabled14600
✅ nitro-stable121025
✅ nuxt-stable121025
✅ sveltekit-stable14006
✅ vite-stable121025
✅ 🐘 Local Postgres
AppPassedFailedSkipped
✅ astro-stable120026
✅ express-stable120026
✅ fastify-stable120026
✅ hono-stable120026
✅ nextjs-turbopack-canary126020
✅ nextjs-turbopack-stable-lazy-discovery-disabled14501
✅ nextjs-turbopack-stable-lazy-discovery-enabled14501
✅ nextjs-webpack-canary126020
✅ nextjs-webpack-stable-lazy-discovery-disabled14501
✅ nextjs-webpack-stable-lazy-discovery-enabled14501
✅ nitro-stable120026
✅ nuxt-stable120026
✅ sveltekit-stable13907
✅ vite-stable120026
✅ 🪟 Windows
AppPassedFailedSkipped
✅ nextjs-turbopack14600
✅ 📋 Other
AppPassedFailedSkipped
✅ e2e-local-dev-nest-stable121025
✅ e2e-local-dev-tanstack-start-121025
✅ e2e-local-postgres-nest-stable120026
✅ e2e-local-postgres-tanstack-start-120026
✅ e2e-local-prod-nest-stable121025
✅ e2e-local-prod-tanstack-start-121025
✅ e2e-vercel-prod-tanstack-start120026

📋 View full workflow run

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

Pull request overview

This PR extends the start() API to optionally permit reserved $-prefixed attribute keys at run creation time (for framework/library callers), and ensures the same behavior is preserved for the resilient-start (queue → run_started) creation path.

Changes:

  • Add StartOptions.allowReservedAttributes and thread it through client-side attribute validation in start().
  • Carry allowReservedAttributes through the queue runInput and into run_started eventData for resilient run creation.
  • Add unit tests and update v5 start() documentation and package changesets.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
packages/world/src/queue.tsExtends RunInputSchema to optionally carry allowReservedAttributes (as true) alongside seeded attributes.
packages/core/src/runtime/start.tsAdds allowReservedAttributes option, uses it during normalization/validation, and forwards it on run_created + queue runInput.
packages/core/src/runtime/start.test.tsAdds coverage verifying flag presence/absence and that non-reserved validation still applies when the flag is enabled.
packages/core/src/runtime.tsForwards runInput.allowReservedAttributes into run_started eventData for resilient run creation.
docs/content/docs/v5/api-reference/workflow-api/start.mdxDocuments reserved $ keys and the allowReservedAttributes escape hatch for framework-level callers.
.changeset/start-allow-reserved-attributes.mdDeclares a minor bump for the relevant packages to ship the new option and schema support.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…ributes
Verified locally against the nextjs-turbopack dev server: the reserved
key passes client and server validation, lands on the run at creation,
and survives the workflow's own attr_set writes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@TooTallNateTooTallNate left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Approve — minimal, correct gap-closure; every claimed precondition verified

This is the right shape for this change: the wire format and storage layers already supported seeding reserved attributes at creation — only the public start() API lacked the escape hatch. I verified each "already supported" claim in the PR description against the code:

  • normalizeAttributeChanges(attrs, { allowReservedAttributes }) — the options parameter and semantics already exist (added with the attributes MVP), so client-side validation is byte-identical to the experimental_setAttributes path ✓
  • run_created, run_started, and attr_set event schemas all already carry allowReservedAttributes: z.literal(true).optional()
  • world-local honors the flag on both creation paths (events-storage.ts handles it for run_created and the resilient run_started bootstrap) ✓

So this PR is genuinely just threading: StartOptions → client validation → run_created eventData → queue runInput → resilient run_started eventData.

What I particularly like

  • The resilient-start path is handled, not forgotten. The subtle failure mode here would be: run_created is lost, the run bootstraps from the queue message via run_started, and the server-side validation rejects the reserved keys because the flag didn't ride along — making resilient starts behave differently from normal ones for exactly the callers using this option. The shared attributeSeed object + the RunInputSchema field + the runtime.ts forwarding close that loop, and the unit test asserts the flag lands on both payloads.
  • z.literal(true).optional() matches the established event-schema style — the flag is either true or absent, never false noise on the wire, and the ...(allowReservedAttributes ? { allowReservedAttributes: true as const } : {}) spread keeps the payloads clean in the default case (also pinned by the not-requested test).
  • The negative test matters most: still enforces non-reserved validation rules when allowReservedAttributes is set proves the flag only bypasses the $-prefix check, not size caps — the escape hatch doesn't accidentally become a validation bypass.
  • The option docstring is the best namespace-ownership explanation in the attributes surface so far ("only flip this to true if your caller is itself a framework or library that owns a $-prefixed sub-namespace").
  • The e2e test smartly reuses experimentalSetAttributesWorkflow and asserts the seeded reserved key survives the workflow's own attr_set writes — covering the merge path, not just creation.
  • No v4 docs this time — correctly scoped to v5 only, since attributes are a v5/spec-4 surface. (A pleasant break from the recurring sequencing flag.)

Verified locally

  • 27 start tests, full core suite (1189), and world suite (50) all pass
  • Docs link target (experimental-set-attributes.mdx) exists
  • Changeset covers exactly the changed packages (workflow/@workflow/core fixed pair + @workflow/world), all minor — correct for new API surface

One observation (no action needed)

Version-skew safety of the new RunInputSchema field: an older consumer parsing a queue message with the extra field would silently strip it (Zod non-strict) and reject the reserved keys on the resilient path — but queue messages are deployment-pinned to the SDK that enqueued them, so producer and consumer can't skew. Worth knowing, not worth changing.

CI fully green. LGTM.

@pranaygp
pranaygp merged commit 628795a into mainJun 12, 2026
121 checks passed
@pranaygp
pranaygp deleted the start-allow-reserved-attributes branch June 12, 2026 22:23
@github-actionsgithub-actionsBot mentioned this pull request Jun 12, 2026
@github-actions

Copy link
Copy Markdown
Contributor

No backport to stable for 628795a (AI decision).

This change builds directly on the native run-attributes surface introduced only on main: I verified that on origin/stable, packages/core/src/runtime/start.ts, packages/world/src/queue.ts, and packages/core/src/runtime.ts contain no attributes support at all (no start(..., { attributes }), no RunInputSchema.attributes, no normalizeAttributeChanges), and the touched docs page docs/content/docs/v5/api-reference/workflow-api/start.mdx does not exist on stable. Without the underlying attributes/spec-version-4 feature from #2226 and experimental_setAttributes, the allowReservedAttributes option has nothing to attach to on stable.

To override, re-run the Backport to stable workflow manually via workflow_dispatch and paste this commit SHA into the ref input:

628795aa8729bef442c7a1583cf2f3d986e9e4fc

pranaygp added a commit that referenced this pull request Jun 13, 2026
…docs-run-idempotency
* origin-https/main:
test: e2e coverage for run-idempotency conflict-handling strategies (#2387)
fix(docs): repair broken links, fix the link linter, and version-correct v5 Card + edit links (#2391)
feat(web-shared): RelativeTimeCard with shared ContextCard provider (#2328)
Add allowReservedAttributes option to start() (#2385)
# Conflicts:
#	docs/content/docs/v4/cookbook/common-patterns/idempotency.mdx
#	docs/content/docs/v5/cookbook/common-patterns/idempotency.mdx
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@pranaygp@TooTallNate