dist/codex/medusa-commerce/skills/medusa-workflows/SKILL.md
Build Medusa v2 workflows — steps with createStep, compensation/rollback, parallel execution, hooks for extending built-in workflows, and when conditions. Use when orchestrating multi-step operations.
npx skillsauth add orcaqubits/agentic-commerce-claude-plugins medusa-workflowsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Fetch live docs:
https://docs.medusajs.com/learn/fundamentals/workflows for workflow overviewsite:docs.medusajs.com createStep createWorkflow for step and workflow APIsite:docs.medusajs.com workflow compensation rollback for compensation patternssite:docs.medusajs.com workflow hooks for extending built-in workflowssite:docs.medusajs.com built-in workflows list for available core workflowsWorkflows orchestrate multi-step, transactional operations in Medusa v2:
| Phase | On Success | On Failure | |-------|-----------|-----------| | Step invoked | Execute function | — | | Execute function | Proceed to next step | Trigger compensation | | All steps done | Workflow complete | — | | Compensation | Rollback completed steps in reverse order | Manual resolution |
// Fetch live docs for createStep signature
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
const myStep = createStep("my-step", async (input, { container }) => {
const service = container.resolve("my-module")
const result = await service.createMyEntity(input)
return new StepResponse(result, result.id) // data, compensationInput
})
// Fetch live docs for compensation function signature
const myStep = createStep("my-step",
async (input, { container }) => {
return new StepResponse(result, result.id) // forward logic
},
async (compensationInput, { container }) => {
// Rollback logic: undo what forward did
})
// Fetch live docs for createWorkflow API
import { createWorkflow, WorkflowResponse }
from "@medusajs/framework/workflows-sdk"
const myWorkflow = createWorkflow("my-workflow", (input) => {
const stepResult = myStep(input)
return new WorkflowResponse(stepResult)
})
| Pattern | API | Purpose |
|---------|-----|---------|
| Sequential | Default step ordering | Steps run one after another |
| Parallel | parallelize(stepA, stepB) | Steps run concurrently |
| Conditional | when(condition, () => step()) | Skip steps based on data |
| Transform | transform(data, fn) | Transform data between steps |
// Fetch live docs for parallelize import
import { parallelize } from "@medusajs/framework/workflows-sdk"
const [resultA, resultB] = parallelize(stepA(input), stepB(input))
// Fetch live docs for when() API
import { when } from "@medusajs/framework/workflows-sdk"
when(input, (data) => data.sendEmail === true, () => {
return sendEmailStep(input)
})
| Context | Invocation Pattern |
|---------|-------------------|
| API Route | await myWorkflow(req.scope).run({ input }) |
| Subscriber | await myWorkflow(container).run({ input }) |
| Scheduled Job | await myWorkflow(container).run({ input }) |
| Another Workflow | Use as a step with createStep wrapping |
Hooks allow extending built-in workflows without modifying core code:
| Hook Type | Purpose |
|-----------|---------|
| before | Run custom logic before a built-in step |
| after | Run custom logic after a built-in step |
// src/workflows/hooks/my-hook.ts
// Fetch live docs for hook registration API
import { createProductsWorkflow } from "@medusajs/medusa/core-flows"
createProductsWorkflow.hooks.productsCreated(
async ({ products, additional_data }, { container }) => {})
// Fetch live docs for available hook names per workflow
| Workflow | Domain | Key Hooks |
|----------|--------|-----------|
| createProductsWorkflow | Catalog | productsCreated |
| updateProductsWorkflow | Catalog | productsUpdated |
| createCartWorkflow | Cart | cartCreated |
| completeCartWorkflow | Checkout | cartCompleted |
| createOrderWorkflow | Orders | orderCreated |
| createFulfillmentWorkflow | Fulfillment | fulfillmentCreated |
| createPaymentCollectionWorkflow | Payments | hook available |
| createCustomerAccountWorkflow | Customers | hook available |
Fetch live docs for the complete list -- new workflows and hooks are added in each Medusa release.
| Scenario | Compensation Action | |----------|-------------------| | Record created | Delete the created record | | Payment captured | Refund the payment | | Inventory reserved | Release the reservation | | Email sent | Log warning (cannot unsend) | | External API called | Call reverse/cancel endpoint |
Key rules:
StepResponseparallelize for independent steps to improve performancewhen for conditional logic -- do not put branching inside stepsreserve-inventory-step)transform for data reshaping -- do not create steps that only transform dataFetch the Medusa workflow documentation for exact createStep/createWorkflow signatures, hook names, and built-in workflow list before implementing.
development
Build with Spree's headless Next.js storefront — the official `spree/storefront` repo (Next.js 16 App Router with Server Actions and Turbopack, React 19 Server Components, Tailwind CSS 4, TypeScript 5, `@spree/sdk`, Sentry), server-only auth (httpOnly JWT cookies + publishable key), MeiliSearch faceted catalog, one-page checkout with Apple/Google Pay/Klarna/Affirm/SEPA, multi-region market routing, GA4 + JSON-LD SEO, and Vercel/Docker deployment. Use when forking or customizing the storefront, or evaluating headless adoption.
tools
Build Spree extensions as Rails engines — gem scaffolding, `bin/rails g spree:extension`, mounting routes/migrations/assets, the modern `prepend` decorator pattern (`*_decorator.rb` with `self.prepended(base)`), generators (`spree:model_decorator`, `spree:controller_decorator`), the four customization surfaces in preference order (Events > Webhooks > Dependencies > Decorators), Spree::Dependencies for swapping service objects, gem release/versioning, and the deprecated Deface engine. Use when building a reusable Spree extension or adding non-trivial customization to an app.
development
Build with Spree's event bus and Webhooks 2.0 — `Spree::Events` publication, `Spree::Subscriber` DSL with `subscribes_to` and `on`, wildcard matching, lifecycle events (`{model}.created/.updated/.deleted` via `publishes_lifecycle_events`), the canonical event catalog (order.*, payment.*, shipment.*, product.*), Webhooks 2.0 endpoints, HMAC-SHA256 signing (`X-Spree-Webhook-Signature`), exponential-backoff retries, and Sidekiq job orchestration. Use when wiring event-driven business logic, building webhook consumers, or replacing ActiveSupport callback chains.
tools
Cross-cutting Spree development patterns — the customization preference hierarchy (Events > Webhooks > Dependencies > Decorators), `Spree::Dependencies` service-object swapping, the `_decorator.rb` + `prepend` + `self.prepended` idiom, idempotent subscribers and webhook receivers, multi-store scoping discipline, prefixed IDs, calculator polymorphism (shipping/promotion/tax share the base), service-object composition with `dry-monads` or simple results, why to avoid `class_eval` reopening and Deface, and Spree-on-Rails idioms (Hotwire/Turbo Stimulus, ActiveStorage, Action Cable, Sidekiq). Use when designing the architecture of a Spree extension or solving cross-cutting concerns.