GitShow/vercel/workflow
vercel

workflow

Workflow SDK: Build durable, reliable, and observable apps and AI Agents in TypeScript

by vercel
ai-agentsdurable-executionorchestrationserverlessvercelworkflow-engineworkflows
Star on GitHubForkWebsitenpm

TypeScript

2.3k stars326 forks109 contributorsActive · 10m agoSince 2025workflow@4.8.0Apache-2.0

Meet the team

See all 109 on GitHub →
TooTallNate
TooTallNate376 contributions
VaguelySerious
VaguelySerious321 contributions
pranaygp
pranaygp222 contributions
karthikscale3
karthikscale3118 contributions
vercel-release-bot
vercel-release-bot71 contributions
mitul-s
mitul-s67 contributions
adriandlam
adriandlam66 contributions
NathanColosimo
NathanColosimo64 contributions

Languages

View on GitHub →
TypeScript89.7%
Rust5%
JavaScript4.2%
CSS0.6%
Shell0.3%
HTML0.1%

Commit activity

Last 12 weeks · 517 commits

Full graph →

Community health

3 of 6 standards met

Community profile →
75
✓README✓License○Contributing✓Code of Conduct○Issue Template○PR Template

Recent PRs & issues

Active · Last activity 10m ago
See all on GitHub →
TooTallNate
core: clean-room rewrite of EventsConsumerOpenPR

Summary Experiment: rip out the existing logic and replace it with a clean-room rewrite, on the hypothesis that the failures under the runtime stem from timing holes in the old consumer's unconsumed-event check rather than from anything the server-side changes (e.g. event-slot incremental event IDs) are needed for. The external contract is unchanged (////, , ); the internals are rewritten from scratch: Single coalesced drain pump. However many / calls land in a tick, the log is walked once on the next tick (previously one full pass was scheduled per call). One explicit orphan-confirmation protocol () replaces the scattered version counters and shared timeout handles. Every step checks a single flag; an aborted probe is woken immediately so no timer or promise chain outlives its relevance. Invalidation on any activity. The old check was cancelled only by . A consumed event or an (retained-session resume) left a scheduled check live against a cursor that had moved. Now any subscribe/append/claim aborts the in-flight probe. Verify, then fire. The old check fired straight off the grace timer. The new protocol re-verifies quiescence after the window (promise queue drained, deliveries idle) and synchronously re-offers the event one final time — a lost timing bet becomes a protocol restart instead of a false (which burns divergence-recovery retries and escalates to terminal ). Cursor bug fix: consuming the end-of-log sentinel no longer advances (previously a pathological on the sentinel silently skipped the next appended event on a retained session). Timing constants are preserved: the empirically-derived 100ms grace window (, floor 10ms; 0/114 corruptions at 100ms vs 34/42 at 10ms on the local repro) and the delivery-idle gate semantics. Validation unit suite: 93 files, 2022 tests passing (includes , , and the delivery-ordering/barrier/divergence integration suites). This PR carries the label — success criterion for the experiment is zero corruptions** from the repro job.

TooTallNate · 6m ago
NathanColosimo
fix: resume open streams from tail cursorsOpenPR

Description Define a stream cursor as a checkpoint for any page that can be resumed: a page with more stored chunks or a non-empty page at the tail of an open stream. A completed final page returns , even when it contains exactly the requested limit. Readers page on and preserve only open-tail cursors for later polling, removing the previous final-page overlap and client-side frame skipping. The hosted World cursor behavior must be deployed before this SDK change. How did you test your changes? Added Local World, Postgres World, and hosted-World regressions for exact-limit terminal pages and open-tail resume cursors. Updated the core and dashboard pagination loops to use . Local World: 45 tests passed. Postgres World storage: 134 tests passed. Affected package typechecks passed. Web production build passed. Biome passed on all changed files with only pre-existing complexity warnings. PR Checklist - Required to merge [x] 📦 was run to create a changelog for this PR [x] 🔒 DCO sign-off passes (run on your commits) [ ] 📝 Ping in a comment once the PR is ready, and the above checklist is complete

NathanColosimo · 9m ago
VaguelySerious
[docs] v5 stable docsOpenPR

Makes v5 the default documentation version for the 5.0.0 GA. Companion to #3090 (exit changeset pre mode) and #3091 (pin 4.x publishes to ). Version flip and routing and now serve unprefixed — , , — and v4 moves under a prefix. The versioned source config drives both route trees (the root tree always renders ), so this is a move plus source re-binding, not a restructure. The only file moves are → . Version switcher: labels are / ; . Banner: → . v4 pages carry an amber notice (with dark-mode styling) whose "Go to Workflow 5 (Latest)" link deep-links to the same page on the current version; v4-only pages land on the nearest section index via the fallback redirects. v4 pages keep . Redirects (): → unprefixed equivalent (permanent; bare gets its own rule because expands to an empty otherwise). The world-docs and api-reference restructure rules are mirrored onto , and every page that exists in only one tree has a version-switcher fallback (verified by diffing the two content trees). Worlds routes: both the unprefixed and worlds routes pass an explicit version into the shared page components, whose semantics flipped with the switch — smoke checks (, ) now guard the pairing so the canonical pages can't silently serve the maintenance version or self-redirect-loop again. Link lint (): the two-space model swaps with the URL space; redirect destinations resolve against the real HTTP space since redirects are matched before render-time href rewriting. Intentional oddity: pulls unprefixed hrefs on v4 pages into the view, so a href is the only way for v4 content to point at a current page. Three such links are kept deliberately; the lint models this. Sidebar*: both docs layouts moved into their segment so is available server-side, and the getting-started section no longer drills in on (where every bare link lands). The per-navigation layout remount this causes is fine in practice — verified in a browser that geistdocs re-scrolls the active sidebar item into view after each navigation. What's new page and migration skill : new top-level page, first in the v5 sidebar. Leads with faster/cheaper runs (single-pass invocations, retained VM across inline steps, one-round-trip hook resume, skipped persistence round trips, payload compression — up to 80% lower compute and 70% lower storage cost on Vercel Workflows), then multi-region, in-flight cancellation, attributes GA, richer serialization, the redesigned trace viewer, and hook tokens outliving their run. A `/worlds/upgrading-to-v5/docs/whats-new/worlds/building-a-worldstablemaincreateLocalWorldcreateVercelWorldskills/migrating-workflow-v4-to-v5WORKFLOW_MAX_EVENTS_OVERRIDEWORKFLOW_MAX_EVENTSWORKFLOW_DISABLE_ANALYTICS_READSmainorigin/mainresumeHook()maxDurationexperimental_minRetentionDEPLOYMENT_MISMATCHexperimental_setAttributesDate()new.targetNestLocalBuilderworkflow/internal/private@workflow/web-sharedWORKFLOW_V2_TIMEOUT_MSWORKFLOW_QUICKJS_BASELINE_SNAPSHOTeventCountSPEC_VERSION_SUPPORTS_SLOT_IDENTITYworld-localworld-postgresslotEventIdsrun_createdbuilding-a-worldevent-sourcingcorrupted-event-logruntime-tuningpostgres/worlds/building-a-world44a53f0beclientcode-transform.mdxframework-integrations.mdxmode: "step"specVersionpreconditionGuardmaxConcurrencyanalyticscreateRunIddescribeRunexperimentalSetAttributessteps.getdelaySecondssleep()region=1set-worldcreate-worldWORKFLOW_TARGET_WORLDstart()start()setAttributes()AbortControllerAbortSignalregionstart()MAX_EVENTS_EXCEEDEDcreateWebhook()pnpm test:docs@workflow/world-localset-worldbun ./scripts/lint.tspnpm buildpnpm start/worlds/vercel/worlds/turso/v4/worlds/turso/v5/bun ./scripts/lint.tspnpm build/[lang]/worlds/upgrading-to-v5lint-rendered-linkspnpm start/worlds/upgrading-to-v5.mdorigin/mainMAX_EVENTS_EXCEEDEDregion/v5/_workflowmode: "step"regionattributes=0AbortControllerAbortSignalcreateWorld()QueueOptionsregionspecVersionsteps.getrunIdstart()setAttributes()step.invoke()start()triggerAndWait()start()Runstart()start().swcrc5.0.0-beta.335.0.05.0.0-beta.335.0.0WORKFLOW_MAX_EVENTS_OVERRIDE/v5WORKFLOW_MAX_EVENTSWORKFLOW_DISABLE_ANALYTICS_READScreateWebhook()createWebhook()message-queueing/v5specVersioncreateRunIddescribeRunsteps.getdelaySecondsregion5.0.0-beta.335.0.0· v45.0.0/v5workflow@4.0.1/v5/*/v5` redirect 🤖 Generated with Claude Code

VaguelySerious · 1h ago
Structured data for AI agents

Repository: vercel/workflow. Description: Workflow SDK: Build durable, reliable, and observable apps and AI Agents in TypeScript Stars: 2307, Forks: 326. Primary language: TypeScript. Languages: TypeScript (89.7%), Rust (5%), JavaScript (4.2%), CSS (0.6%), Shell (0.3%). License: Apache-2.0. Homepage: https://workflow-sdk.dev Topics: ai-agents, durable-execution, orchestration, serverless, vercel, workflow-engine, workflows. Latest release: workflow@4.8.0 (1w ago). Open PRs: 100, open issues: 203. Last activity: 10m ago. Community health: 75%. Top contributors: TooTallNate, VaguelySerious, pranaygp, karthikscale3, vercel-release-bot, mitul-s, adriandlam, NathanColosimo, ijjk, github-actions[bot] and others.

·@ofershap

Replace github.com with gitshow.dev