[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-inngest-inngest-brownfield-audit":3,"mdc--gdgpwz-key":41,"related-repo-inngest-inngest-brownfield-audit":1615,"related-org-inngest-inngest-brownfield-audit":1711},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":23,"repoUrl":24,"updatedAt":25,"license":26,"forks":27,"topics":28,"repo":36,"sourceUrl":39,"mdContent":40},"inngest-brownfield-audit","audit codebases for Inngest integration","Use when analyzing an existing TypeScript or JavaScript codebase to decide where and how to introduce Inngest. Covers repository discovery, framework and package detection, finding durability gaps in HTTP handlers, webhooks, cron jobs, queues, long-running jobs, AI agents, Agent Evals, polling loops, eval loops, and side-effect-heavy code, then producing and implementing an incremental integration plan.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"inngest","Inngest","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Finngest.png",[12,16,17,20],{"name":13,"slug":14,"type":15},"Automation","automation","tag",{"name":9,"slug":8,"type":15},{"name":18,"slug":19,"type":15},"Engineering","engineering",{"name":21,"slug":22,"type":15},"Code Analysis","code-analysis",26,"https:\u002F\u002Fgithub.com\u002Finngest\u002Finngest-skills","2026-07-12T07:36:55.811247",null,5,[29,30,31,32,33,34,35],"agent-skill-repository","agent-skills","agentic-skills","ai-agents","claude-code-skills","cursor-skills","openclaw-skills",{"repoUrl":24,"stars":23,"forks":27,"topics":37,"description":38},[29,30,31,32,33,34,35],"Agent Skills for building with Inngest","https:\u002F\u002Fgithub.com\u002Finngest\u002Finngest-skills\u002Ftree\u002FHEAD\u002Fskills\u002Finngest-brownfield-audit","---\nname: inngest-brownfield-audit\ndescription: Use when analyzing an existing TypeScript or JavaScript codebase to decide where and how to introduce Inngest. Covers repository discovery, framework and package detection, finding durability gaps in HTTP handlers, webhooks, cron jobs, queues, long-running jobs, AI agents, Agent Evals, polling loops, eval loops, and side-effect-heavy code, then producing and implementing an incremental integration plan.\n---\n\n# Inngest Brownfield Audit\n\nUse this skill when asked to inspect an existing codebase, add\nInngest \"where it makes sense\", migrate fragile background work, or find\ndurability gaps before making changes.\n\nThis is an agent-first workflow. Do the audit from evidence in the repo, name\nthe specific files and call sites that drove each conclusion, and make small\nintegration moves that preserve current behavior.\n\n## When to Trigger\n\nUse this skill for requests like:\n\n- \"Audit this repo for Inngest opportunities\"\n- \"Add Inngest to this codebase\"\n- \"Make our webhooks \u002F cron jobs \u002F background tasks reliable\"\n- \"Find places where work can be lost on deploy or process crash\"\n- \"Replace fragile polling, delayed jobs, or fire-and-forget promises\"\n- \"Make this AI workflow \u002F agent durable\"\n\nIf the user is starting from scratch instead of a brownfield repo, use\n`inngest-setup`, `inngest-durable-functions`, `inngest-events`,\n`inngest-steps`, and, for AI workflows, the agent patterns in this skill. Use\n`inngest-agent-evals` when the request includes scoring, sessions, experiments,\ndeferred scorers, Insights, or outcome-based evaluation.\n\n## Audit Loop\n\n1. **Map the project shape.**\n   - Read `package.json`, workspace files, app\u002Frouter structure, server entry\n     points, deployment config, and test scripts.\n   - Identify framework: Next.js App Router, Next.js Pages Router, Express,\n     Hono, Fastify, Remix, SvelteKit, Astro, NestJS, worker-only service, or\n     other.\n   - Detect package manager and TypeScript conventions before adding files.\n\n2. **Find existing Inngest usage.**\n   - Search for `inngest`, `createFunction`, `serve(`, `\u002Fapi\u002Finngest`,\n     `INNGEST_`, `step.run`, `step.sleep`, `step.waitForEvent`,\n     `step.sendEvent`, `step.invoke`, `step.ai`, `inngest.send`, and\n     `@inngest\u002Frealtime`.\n   - If Inngest exists, inspect version, client config, serve endpoint,\n     registered functions, event naming, env vars, and v3\u002Fv4 API shape before\n     changing anything.\n\n3. **Find durability gaps.**\n   - Search for fire-and-forget work: `void someAsync()`, un-awaited promises,\n     `.then(` chains, `setTimeout`, `setInterval`, detached jobs after HTTP\n     response, and background work in route handlers.\n   - Search for cron and schedulers: `cron`, `node-cron`, `agenda`, `bull`,\n     `bullmq`, `bee-queue`, `qstash`, `sqs`, `temporal`, `trigger.dev`,\n     deployment cron config, and scheduled API routes.\n   - Search for webhooks and at-least-once producers: Stripe, Clerk, GitHub,\n     Slack, Shopify, HubSpot, Linear, Svix, and generic `webhook`.\n   - Search for long-running work: PDF generation, exports, video\u002Fimage\n     processing, embeddings, bulk email, imports, ETL, sync jobs, polling loops,\n     retries, and external API calls.\n   - Search for AI agent shapes: tool loops, LLM calls, streaming tokens,\n     human approval, multi-step reasoning, vector search, eval loops, scoring,\n     experiment assignment, user-feedback signals, and provider calls that need\n     rate limits or retry-safe state.\n\n4. **Classify each candidate.**\n   - **P0:** user-visible loss, duplicate charge\u002Femail\u002Faction, timeout, missed\n     webhook, or crash-prone workflow.\n   - **P1:** fragile but recoverable background work, manual retry burden,\n     noisy 429s, or poor observability.\n   - **P2:** cleanup, ergonomics, or future migration opportunity.\n   - For each candidate, record: file, current trigger, side effects,\n     idempotency key, failure mode, recommended Inngest primitive, migration\n     size, and confidence.\n\n5. **Choose the smallest safe integration.**\n   - Prefer one vertical slice over a wide rewrite.\n   - Keep existing domain functions and data models where possible.\n   - Add an Inngest client and serve endpoint only once.\n   - Move side effects into `step.run` one boundary at a time.\n   - Make event IDs and database writes idempotent before adding retries.\n   - Add tests around existing behavior and the new event\u002Ffunction boundary.\n\n## Useful Discovery Commands\n\nRun commands that fit the repo. Prefer `rg`; keep output focused.\n\n```bash\nrg -n \"inngest|createFunction|step\\\\.|serve\\\\(|\u002Fapi\u002Finngest|INNGEST_\" .\nrg -n \"setTimeout|setInterval|Promise\\\\.all|void [a-zA-Z0-9_]+\\\\(|\\\\.then\\\\(\" .\nrg -n \"cron|node-cron|schedule|bull|bullmq|bee-queue|agenda|qstash|sqs\" .\nrg -n \"webhook|stripe|svix|clerk|github|shopify|slack|hubspot|linear\" .\nrg -n \"retry|backoff|poll|status|timeout|429|rate limit|rate-limit\" .\nrg -n \"openai|anthropic|ai\\\\.|generateText|streamText|tool|agent|embedding\" .\n```\n\nWhen the repo is large, narrow searches to app source directories and exclude\ngenerated\u002Fvendor folders.\n\n## Brownfield Decision Matrix\n\n| Existing shape | Inngest fit | Primary primitives |\n|---|---|---|\n| HTTP handler does slow side effects before responding | Emit event, return fast | `inngest.send`, event trigger, `step.run` |\n| Webhook must acknowledge quickly but process reliably | Verify signature, emit idempotent event | Event ID, `step.run`, retries |\n| Cron job loses progress midway | Cron-triggered durable function | Cron trigger, page-level `step.run`, flow control |\n| Polling loop waits for external async work | Durable wait or durable poll | `step.waitForEvent`, `step.sleep`, `step.run` |\n| Large fan-out exceeds request\u002Fserverless limits | Split orchestration and item work | `step.sendEvent`, per-item function, concurrency |\n| External API hits 429s | Move limits to function config | `throttle`, `rateLimit`, `concurrency` |\n| Human review can take days | Persist the wait in Inngest | `step.waitForEvent`, timeout, realtime |\n| AI agent\u002Ftool loop needs retry-safe progress | One step per tool\u002Fmodel boundary | `step.ai`, `step.run`, `step.sleep`, realtime |\n| AI workflow needs production evals | Attach outcome signals to durable runs | `meta.sessions`, `step.score`, `createScorer`, `defer`, `group.experiment` |\n| Existing queue only hides fragile work | Replace queue boundary gradually | Event trigger, idempotency, function-level retries |\n\n## Integration Plan Format\n\nBefore editing, summarize findings in this compact shape:\n\n```text\nInngest audit:\n- Existing Inngest: none \u002F partial \u002F healthy \u002F risky\n- Framework: \u003Cframework and evidence>\n- Best first slice: \u003Cfile + workflow>\n- Why: \u003Closs\u002Ftimeout\u002Fretry\u002Fidempotency failure>\n- Proposed primitives: \u003Cevent, steps, flow control, waits, realtime>\n- Idempotency key: \u003Csource of truth>\n- Files likely touched: \u003Cshort list>\n- Tests\u002Fchecks: \u003Ccommands or focused cases>\n```\n\nThen implement unless the user asked for audit-only.\n\n## Existing Inngest Checklist\n\nIf Inngest is already present, verify:\n\n- A single shared client is exported from a stable module.\n- The app `id` is a stable slug and is not derived from deploy-specific data.\n- v4 local development uses `INNGEST_DEV=1`; production uses\n  `INNGEST_SIGNING_KEY`.\n- Serve endpoint path is discoverable, usually `\u002Fapi\u002Finngest`.\n- The serve handler registers all functions that should sync.\n- Side effects and non-deterministic work are inside steps.\n- Step IDs are stable and descriptive.\n- Event names follow `domain\u002Fnoun.verb`.\n- Events that may be replayed use deterministic IDs.\n- Webhook handlers verify signatures before emitting events.\n- Flow control is configured where external APIs have limits.\n- Realtime uses v4 native `inngest\u002Frealtime`, not the v3\n  `@inngest\u002Frealtime` package.\n\n## Durable Agent Patterns\n\nUse Inngest when an AI or agent workflow needs durable progress across model\ncalls, tool calls, waits, approvals, or streaming UI updates.\n\nGood candidates:\n\n- Multi-step agent that calls tools or external APIs.\n- LLM workflow that may exceed one HTTP request lifetime.\n- Human-in-the-loop review, approval, correction, or escalation.\n- Agent that must pause for an external event or scheduled follow-up.\n- Bulk AI work that needs provider-level rate limits and cost protection.\n- User-visible agent progress that should stream from durable execution.\n\nRecommended shape:\n\n1. HTTP\u002FUI request stores the user intent and emits an event with a stable\n   `id`.\n2. Inngest function loads state inside `step.run`.\n3. Each model call, tool call, vector search, and external side effect lives in\n   its own `step.ai` or `step.run` boundary.\n4. Human pauses use `step.waitForEvent` or `step.waitForSignal` with a timeout.\n5. Progress updates use `step.realtime.publish` between steps, or\n   `inngest.realtime.publish` inside an existing `step.run`.\n6. Provider rate limits use `concurrency`, `throttle`, or `rateLimit`, not\n   ad hoc in-process throttlers.\n\nAvoid:\n\n- Keeping agent state only in memory.\n- Retrying whole agent loops after a single tool failure.\n- Charging for repeated successful model calls because the result was not\n  memoized.\n- Using `setTimeout` or a cron poller for follow-ups and approvals.\n- Streaming progress from a process-local WebSocket server when the workflow\n  itself is durable elsewhere.\n\n## Implementation Guardrails\n\n- Do not replace working queues, crons, or webhooks blindly. First preserve\n  behavior with a thin Inngest slice.\n- Do not create duplicate clients or serve endpoints if the repo already has\n  them.\n- Do not put database writes, API calls, random IDs, timestamps, or LLM calls\n  outside steps in the new function.\n- Do not hide missing idempotency behind retries. Retries require idempotent\n  side effects.\n- Do not hardcode secrets or dev-mode flags in source.\n- Do not leave the app unable to sync: register new functions with the serve\n  endpoint and run available type\u002Ftests.\n\n## Verification\n\nPick checks that prove the integration path:\n\n- Typecheck\u002Fbuild\u002Flint the touched app.\n- Run existing tests around the migrated handler or workflow.\n- Add focused tests for \"handler emits event and returns fast\" and \"function\n  calls the same domain operations in step boundaries\" where the repo supports\n  it.\n- If local runtime is available, start the app and Inngest dev server, confirm\n  the function syncs, then send a sample event.\n- If only static checks are available, explicitly state that runtime sync was\n  not verified.\n",{"data":42,"body":43},{"name":4,"description":6},{"type":44,"children":45},"root",[46,54,60,65,72,77,112,157,163,554,560,573,831,836,842,1171,1177,1182,1192,1197,1203,1208,1322,1328,1333,1338,1371,1376,1491,1496,1531,1537,1570,1576,1581,1609],{"type":47,"tag":48,"props":49,"children":50},"element","h1",{"id":4},[51],{"type":52,"value":53},"text","Inngest Brownfield Audit",{"type":47,"tag":55,"props":56,"children":57},"p",{},[58],{"type":52,"value":59},"Use this skill when asked to inspect an existing codebase, add\nInngest \"where it makes sense\", migrate fragile background work, or find\ndurability gaps before making changes.",{"type":47,"tag":55,"props":61,"children":62},{},[63],{"type":52,"value":64},"This is an agent-first workflow. Do the audit from evidence in the repo, name\nthe specific files and call sites that drove each conclusion, and make small\nintegration moves that preserve current behavior.",{"type":47,"tag":66,"props":67,"children":69},"h2",{"id":68},"when-to-trigger",[70],{"type":52,"value":71},"When to Trigger",{"type":47,"tag":55,"props":73,"children":74},{},[75],{"type":52,"value":76},"Use this skill for requests like:",{"type":47,"tag":78,"props":79,"children":80},"ul",{},[81,87,92,97,102,107],{"type":47,"tag":82,"props":83,"children":84},"li",{},[85],{"type":52,"value":86},"\"Audit this repo for Inngest opportunities\"",{"type":47,"tag":82,"props":88,"children":89},{},[90],{"type":52,"value":91},"\"Add Inngest to this codebase\"",{"type":47,"tag":82,"props":93,"children":94},{},[95],{"type":52,"value":96},"\"Make our webhooks \u002F cron jobs \u002F background tasks reliable\"",{"type":47,"tag":82,"props":98,"children":99},{},[100],{"type":52,"value":101},"\"Find places where work can be lost on deploy or process crash\"",{"type":47,"tag":82,"props":103,"children":104},{},[105],{"type":52,"value":106},"\"Replace fragile polling, delayed jobs, or fire-and-forget promises\"",{"type":47,"tag":82,"props":108,"children":109},{},[110],{"type":52,"value":111},"\"Make this AI workflow \u002F agent durable\"",{"type":47,"tag":55,"props":113,"children":114},{},[115,117,124,126,132,133,139,141,147,149,155],{"type":52,"value":116},"If the user is starting from scratch instead of a brownfield repo, use\n",{"type":47,"tag":118,"props":119,"children":121},"code",{"className":120},[],[122],{"type":52,"value":123},"inngest-setup",{"type":52,"value":125},", ",{"type":47,"tag":118,"props":127,"children":129},{"className":128},[],[130],{"type":52,"value":131},"inngest-durable-functions",{"type":52,"value":125},{"type":47,"tag":118,"props":134,"children":136},{"className":135},[],[137],{"type":52,"value":138},"inngest-events",{"type":52,"value":140},",\n",{"type":47,"tag":118,"props":142,"children":144},{"className":143},[],[145],{"type":52,"value":146},"inngest-steps",{"type":52,"value":148},", and, for AI workflows, the agent patterns in this skill. Use\n",{"type":47,"tag":118,"props":150,"children":152},{"className":151},[],[153],{"type":52,"value":154},"inngest-agent-evals",{"type":52,"value":156}," when the request includes scoring, sessions, experiments,\ndeferred scorers, Insights, or outcome-based evaluation.",{"type":47,"tag":66,"props":158,"children":160},{"id":159},"audit-loop",[161],{"type":52,"value":162},"Audit Loop",{"type":47,"tag":164,"props":165,"children":166},"ol",{},[167,202,315,460,506],{"type":47,"tag":82,"props":168,"children":169},{},[170,176],{"type":47,"tag":171,"props":172,"children":173},"strong",{},[174],{"type":52,"value":175},"Map the project shape.",{"type":47,"tag":78,"props":177,"children":178},{},[179,192,197],{"type":47,"tag":82,"props":180,"children":181},{},[182,184,190],{"type":52,"value":183},"Read ",{"type":47,"tag":118,"props":185,"children":187},{"className":186},[],[188],{"type":52,"value":189},"package.json",{"type":52,"value":191},", workspace files, app\u002Frouter structure, server entry\npoints, deployment config, and test scripts.",{"type":47,"tag":82,"props":193,"children":194},{},[195],{"type":52,"value":196},"Identify framework: Next.js App Router, Next.js Pages Router, Express,\nHono, Fastify, Remix, SvelteKit, Astro, NestJS, worker-only service, or\nother.",{"type":47,"tag":82,"props":198,"children":199},{},[200],{"type":52,"value":201},"Detect package manager and TypeScript conventions before adding files.",{"type":47,"tag":82,"props":203,"children":204},{},[205,210],{"type":47,"tag":171,"props":206,"children":207},{},[208],{"type":52,"value":209},"Find existing Inngest usage.",{"type":47,"tag":78,"props":211,"children":212},{},[213,310],{"type":47,"tag":82,"props":214,"children":215},{},[216,218,223,224,230,231,237,238,244,245,251,252,258,259,265,266,272,273,279,280,286,287,293,294,300,302,308],{"type":52,"value":217},"Search for ",{"type":47,"tag":118,"props":219,"children":221},{"className":220},[],[222],{"type":52,"value":8},{"type":52,"value":125},{"type":47,"tag":118,"props":225,"children":227},{"className":226},[],[228],{"type":52,"value":229},"createFunction",{"type":52,"value":125},{"type":47,"tag":118,"props":232,"children":234},{"className":233},[],[235],{"type":52,"value":236},"serve(",{"type":52,"value":125},{"type":47,"tag":118,"props":239,"children":241},{"className":240},[],[242],{"type":52,"value":243},"\u002Fapi\u002Finngest",{"type":52,"value":140},{"type":47,"tag":118,"props":246,"children":248},{"className":247},[],[249],{"type":52,"value":250},"INNGEST_",{"type":52,"value":125},{"type":47,"tag":118,"props":253,"children":255},{"className":254},[],[256],{"type":52,"value":257},"step.run",{"type":52,"value":125},{"type":47,"tag":118,"props":260,"children":262},{"className":261},[],[263],{"type":52,"value":264},"step.sleep",{"type":52,"value":125},{"type":47,"tag":118,"props":267,"children":269},{"className":268},[],[270],{"type":52,"value":271},"step.waitForEvent",{"type":52,"value":140},{"type":47,"tag":118,"props":274,"children":276},{"className":275},[],[277],{"type":52,"value":278},"step.sendEvent",{"type":52,"value":125},{"type":47,"tag":118,"props":281,"children":283},{"className":282},[],[284],{"type":52,"value":285},"step.invoke",{"type":52,"value":125},{"type":47,"tag":118,"props":288,"children":290},{"className":289},[],[291],{"type":52,"value":292},"step.ai",{"type":52,"value":125},{"type":47,"tag":118,"props":295,"children":297},{"className":296},[],[298],{"type":52,"value":299},"inngest.send",{"type":52,"value":301},", and\n",{"type":47,"tag":118,"props":303,"children":305},{"className":304},[],[306],{"type":52,"value":307},"@inngest\u002Frealtime",{"type":52,"value":309},".",{"type":47,"tag":82,"props":311,"children":312},{},[313],{"type":52,"value":314},"If Inngest exists, inspect version, client config, serve endpoint,\nregistered functions, event naming, env vars, and v3\u002Fv4 API shape before\nchanging anything.",{"type":47,"tag":82,"props":316,"children":317},{},[318,323],{"type":47,"tag":171,"props":319,"children":320},{},[321],{"type":52,"value":322},"Find durability gaps.",{"type":47,"tag":78,"props":324,"children":325},{},[326,362,438,450,455],{"type":47,"tag":82,"props":327,"children":328},{},[329,331,337,339,345,347,353,354,360],{"type":52,"value":330},"Search for fire-and-forget work: ",{"type":47,"tag":118,"props":332,"children":334},{"className":333},[],[335],{"type":52,"value":336},"void someAsync()",{"type":52,"value":338},", un-awaited promises,\n",{"type":47,"tag":118,"props":340,"children":342},{"className":341},[],[343],{"type":52,"value":344},".then(",{"type":52,"value":346}," chains, ",{"type":47,"tag":118,"props":348,"children":350},{"className":349},[],[351],{"type":52,"value":352},"setTimeout",{"type":52,"value":125},{"type":47,"tag":118,"props":355,"children":357},{"className":356},[],[358],{"type":52,"value":359},"setInterval",{"type":52,"value":361},", detached jobs after HTTP\nresponse, and background work in route handlers.",{"type":47,"tag":82,"props":363,"children":364},{},[365,367,373,374,380,381,387,388,394,395,401,402,408,409,415,416,422,423,429,430,436],{"type":52,"value":366},"Search for cron and schedulers: ",{"type":47,"tag":118,"props":368,"children":370},{"className":369},[],[371],{"type":52,"value":372},"cron",{"type":52,"value":125},{"type":47,"tag":118,"props":375,"children":377},{"className":376},[],[378],{"type":52,"value":379},"node-cron",{"type":52,"value":125},{"type":47,"tag":118,"props":382,"children":384},{"className":383},[],[385],{"type":52,"value":386},"agenda",{"type":52,"value":125},{"type":47,"tag":118,"props":389,"children":391},{"className":390},[],[392],{"type":52,"value":393},"bull",{"type":52,"value":140},{"type":47,"tag":118,"props":396,"children":398},{"className":397},[],[399],{"type":52,"value":400},"bullmq",{"type":52,"value":125},{"type":47,"tag":118,"props":403,"children":405},{"className":404},[],[406],{"type":52,"value":407},"bee-queue",{"type":52,"value":125},{"type":47,"tag":118,"props":410,"children":412},{"className":411},[],[413],{"type":52,"value":414},"qstash",{"type":52,"value":125},{"type":47,"tag":118,"props":417,"children":419},{"className":418},[],[420],{"type":52,"value":421},"sqs",{"type":52,"value":125},{"type":47,"tag":118,"props":424,"children":426},{"className":425},[],[427],{"type":52,"value":428},"temporal",{"type":52,"value":125},{"type":47,"tag":118,"props":431,"children":433},{"className":432},[],[434],{"type":52,"value":435},"trigger.dev",{"type":52,"value":437},",\ndeployment cron config, and scheduled API routes.",{"type":47,"tag":82,"props":439,"children":440},{},[441,443,449],{"type":52,"value":442},"Search for webhooks and at-least-once producers: Stripe, Clerk, GitHub,\nSlack, Shopify, HubSpot, Linear, Svix, and generic ",{"type":47,"tag":118,"props":444,"children":446},{"className":445},[],[447],{"type":52,"value":448},"webhook",{"type":52,"value":309},{"type":47,"tag":82,"props":451,"children":452},{},[453],{"type":52,"value":454},"Search for long-running work: PDF generation, exports, video\u002Fimage\nprocessing, embeddings, bulk email, imports, ETL, sync jobs, polling loops,\nretries, and external API calls.",{"type":47,"tag":82,"props":456,"children":457},{},[458],{"type":52,"value":459},"Search for AI agent shapes: tool loops, LLM calls, streaming tokens,\nhuman approval, multi-step reasoning, vector search, eval loops, scoring,\nexperiment assignment, user-feedback signals, and provider calls that need\nrate limits or retry-safe state.",{"type":47,"tag":82,"props":461,"children":462},{},[463,468],{"type":47,"tag":171,"props":464,"children":465},{},[466],{"type":52,"value":467},"Classify each candidate.",{"type":47,"tag":78,"props":469,"children":470},{},[471,481,491,501],{"type":47,"tag":82,"props":472,"children":473},{},[474,479],{"type":47,"tag":171,"props":475,"children":476},{},[477],{"type":52,"value":478},"P0:",{"type":52,"value":480}," user-visible loss, duplicate charge\u002Femail\u002Faction, timeout, missed\nwebhook, or crash-prone workflow.",{"type":47,"tag":82,"props":482,"children":483},{},[484,489],{"type":47,"tag":171,"props":485,"children":486},{},[487],{"type":52,"value":488},"P1:",{"type":52,"value":490}," fragile but recoverable background work, manual retry burden,\nnoisy 429s, or poor observability.",{"type":47,"tag":82,"props":492,"children":493},{},[494,499],{"type":47,"tag":171,"props":495,"children":496},{},[497],{"type":52,"value":498},"P2:",{"type":52,"value":500}," cleanup, ergonomics, or future migration opportunity.",{"type":47,"tag":82,"props":502,"children":503},{},[504],{"type":52,"value":505},"For each candidate, record: file, current trigger, side effects,\nidempotency key, failure mode, recommended Inngest primitive, migration\nsize, and confidence.",{"type":47,"tag":82,"props":507,"children":508},{},[509,514],{"type":47,"tag":171,"props":510,"children":511},{},[512],{"type":52,"value":513},"Choose the smallest safe integration.",{"type":47,"tag":78,"props":515,"children":516},{},[517,522,527,532,544,549],{"type":47,"tag":82,"props":518,"children":519},{},[520],{"type":52,"value":521},"Prefer one vertical slice over a wide rewrite.",{"type":47,"tag":82,"props":523,"children":524},{},[525],{"type":52,"value":526},"Keep existing domain functions and data models where possible.",{"type":47,"tag":82,"props":528,"children":529},{},[530],{"type":52,"value":531},"Add an Inngest client and serve endpoint only once.",{"type":47,"tag":82,"props":533,"children":534},{},[535,537,542],{"type":52,"value":536},"Move side effects into ",{"type":47,"tag":118,"props":538,"children":540},{"className":539},[],[541],{"type":52,"value":257},{"type":52,"value":543}," one boundary at a time.",{"type":47,"tag":82,"props":545,"children":546},{},[547],{"type":52,"value":548},"Make event IDs and database writes idempotent before adding retries.",{"type":47,"tag":82,"props":550,"children":551},{},[552],{"type":52,"value":553},"Add tests around existing behavior and the new event\u002Ffunction boundary.",{"type":47,"tag":66,"props":555,"children":557},{"id":556},"useful-discovery-commands",[558],{"type":52,"value":559},"Useful Discovery Commands",{"type":47,"tag":55,"props":561,"children":562},{},[563,565,571],{"type":52,"value":564},"Run commands that fit the repo. Prefer ",{"type":47,"tag":118,"props":566,"children":568},{"className":567},[],[569],{"type":52,"value":570},"rg",{"type":52,"value":572},"; keep output focused.",{"type":47,"tag":574,"props":575,"children":580},"pre",{"className":576,"code":577,"language":578,"meta":579,"style":579},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","rg -n \"inngest|createFunction|step\\\\.|serve\\\\(|\u002Fapi\u002Finngest|INNGEST_\" .\nrg -n \"setTimeout|setInterval|Promise\\\\.all|void [a-zA-Z0-9_]+\\\\(|\\\\.then\\\\(\" .\nrg -n \"cron|node-cron|schedule|bull|bullmq|bee-queue|agenda|qstash|sqs\" .\nrg -n \"webhook|stripe|svix|clerk|github|shopify|slack|hubspot|linear\" .\nrg -n \"retry|backoff|poll|status|timeout|429|rate limit|rate-limit\" .\nrg -n \"openai|anthropic|ai\\\\.|generateText|streamText|tool|agent|embedding\" .\n","bash","",[581],{"type":47,"tag":118,"props":582,"children":583},{"__ignoreMap":579},[584,642,707,736,765,793],{"type":47,"tag":585,"props":586,"children":589},"span",{"class":587,"line":588},"line",1,[590,595,601,607,612,618,623,627,632,637],{"type":47,"tag":585,"props":591,"children":593},{"style":592},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[594],{"type":52,"value":570},{"type":47,"tag":585,"props":596,"children":598},{"style":597},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[599],{"type":52,"value":600}," -n",{"type":47,"tag":585,"props":602,"children":604},{"style":603},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[605],{"type":52,"value":606}," \"",{"type":47,"tag":585,"props":608,"children":609},{"style":597},[610],{"type":52,"value":611},"inngest|createFunction|step",{"type":47,"tag":585,"props":613,"children":615},{"style":614},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[616],{"type":52,"value":617},"\\\\",{"type":47,"tag":585,"props":619,"children":620},{"style":597},[621],{"type":52,"value":622},".|serve",{"type":47,"tag":585,"props":624,"children":625},{"style":614},[626],{"type":52,"value":617},{"type":47,"tag":585,"props":628,"children":629},{"style":597},[630],{"type":52,"value":631},"(|\u002Fapi\u002Finngest|INNGEST_",{"type":47,"tag":585,"props":633,"children":634},{"style":603},[635],{"type":52,"value":636},"\"",{"type":47,"tag":585,"props":638,"children":639},{"style":597},[640],{"type":52,"value":641}," .\n",{"type":47,"tag":585,"props":643,"children":645},{"class":587,"line":644},2,[646,650,654,658,663,667,672,676,681,685,690,694,699,703],{"type":47,"tag":585,"props":647,"children":648},{"style":592},[649],{"type":52,"value":570},{"type":47,"tag":585,"props":651,"children":652},{"style":597},[653],{"type":52,"value":600},{"type":47,"tag":585,"props":655,"children":656},{"style":603},[657],{"type":52,"value":606},{"type":47,"tag":585,"props":659,"children":660},{"style":597},[661],{"type":52,"value":662},"setTimeout|setInterval|Promise",{"type":47,"tag":585,"props":664,"children":665},{"style":614},[666],{"type":52,"value":617},{"type":47,"tag":585,"props":668,"children":669},{"style":597},[670],{"type":52,"value":671},".all|void [a-zA-Z0-9_]+",{"type":47,"tag":585,"props":673,"children":674},{"style":614},[675],{"type":52,"value":617},{"type":47,"tag":585,"props":677,"children":678},{"style":597},[679],{"type":52,"value":680},"(|",{"type":47,"tag":585,"props":682,"children":683},{"style":614},[684],{"type":52,"value":617},{"type":47,"tag":585,"props":686,"children":687},{"style":597},[688],{"type":52,"value":689},".then",{"type":47,"tag":585,"props":691,"children":692},{"style":614},[693],{"type":52,"value":617},{"type":47,"tag":585,"props":695,"children":696},{"style":597},[697],{"type":52,"value":698},"(",{"type":47,"tag":585,"props":700,"children":701},{"style":603},[702],{"type":52,"value":636},{"type":47,"tag":585,"props":704,"children":705},{"style":597},[706],{"type":52,"value":641},{"type":47,"tag":585,"props":708,"children":710},{"class":587,"line":709},3,[711,715,719,723,728,732],{"type":47,"tag":585,"props":712,"children":713},{"style":592},[714],{"type":52,"value":570},{"type":47,"tag":585,"props":716,"children":717},{"style":597},[718],{"type":52,"value":600},{"type":47,"tag":585,"props":720,"children":721},{"style":603},[722],{"type":52,"value":606},{"type":47,"tag":585,"props":724,"children":725},{"style":597},[726],{"type":52,"value":727},"cron|node-cron|schedule|bull|bullmq|bee-queue|agenda|qstash|sqs",{"type":47,"tag":585,"props":729,"children":730},{"style":603},[731],{"type":52,"value":636},{"type":47,"tag":585,"props":733,"children":734},{"style":597},[735],{"type":52,"value":641},{"type":47,"tag":585,"props":737,"children":739},{"class":587,"line":738},4,[740,744,748,752,757,761],{"type":47,"tag":585,"props":741,"children":742},{"style":592},[743],{"type":52,"value":570},{"type":47,"tag":585,"props":745,"children":746},{"style":597},[747],{"type":52,"value":600},{"type":47,"tag":585,"props":749,"children":750},{"style":603},[751],{"type":52,"value":606},{"type":47,"tag":585,"props":753,"children":754},{"style":597},[755],{"type":52,"value":756},"webhook|stripe|svix|clerk|github|shopify|slack|hubspot|linear",{"type":47,"tag":585,"props":758,"children":759},{"style":603},[760],{"type":52,"value":636},{"type":47,"tag":585,"props":762,"children":763},{"style":597},[764],{"type":52,"value":641},{"type":47,"tag":585,"props":766,"children":767},{"class":587,"line":27},[768,772,776,780,785,789],{"type":47,"tag":585,"props":769,"children":770},{"style":592},[771],{"type":52,"value":570},{"type":47,"tag":585,"props":773,"children":774},{"style":597},[775],{"type":52,"value":600},{"type":47,"tag":585,"props":777,"children":778},{"style":603},[779],{"type":52,"value":606},{"type":47,"tag":585,"props":781,"children":782},{"style":597},[783],{"type":52,"value":784},"retry|backoff|poll|status|timeout|429|rate limit|rate-limit",{"type":47,"tag":585,"props":786,"children":787},{"style":603},[788],{"type":52,"value":636},{"type":47,"tag":585,"props":790,"children":791},{"style":597},[792],{"type":52,"value":641},{"type":47,"tag":585,"props":794,"children":796},{"class":587,"line":795},6,[797,801,805,809,814,818,823,827],{"type":47,"tag":585,"props":798,"children":799},{"style":592},[800],{"type":52,"value":570},{"type":47,"tag":585,"props":802,"children":803},{"style":597},[804],{"type":52,"value":600},{"type":47,"tag":585,"props":806,"children":807},{"style":603},[808],{"type":52,"value":606},{"type":47,"tag":585,"props":810,"children":811},{"style":597},[812],{"type":52,"value":813},"openai|anthropic|ai",{"type":47,"tag":585,"props":815,"children":816},{"style":614},[817],{"type":52,"value":617},{"type":47,"tag":585,"props":819,"children":820},{"style":597},[821],{"type":52,"value":822},".|generateText|streamText|tool|agent|embedding",{"type":47,"tag":585,"props":824,"children":825},{"style":603},[826],{"type":52,"value":636},{"type":47,"tag":585,"props":828,"children":829},{"style":597},[830],{"type":52,"value":641},{"type":47,"tag":55,"props":832,"children":833},{},[834],{"type":52,"value":835},"When the repo is large, narrow searches to app source directories and exclude\ngenerated\u002Fvendor folders.",{"type":47,"tag":66,"props":837,"children":839},{"id":838},"brownfield-decision-matrix",[840],{"type":52,"value":841},"Brownfield Decision Matrix",{"type":47,"tag":843,"props":844,"children":845},"table",{},[846,870],{"type":47,"tag":847,"props":848,"children":849},"thead",{},[850],{"type":47,"tag":851,"props":852,"children":853},"tr",{},[854,860,865],{"type":47,"tag":855,"props":856,"children":857},"th",{},[858],{"type":52,"value":859},"Existing shape",{"type":47,"tag":855,"props":861,"children":862},{},[863],{"type":52,"value":864},"Inngest fit",{"type":47,"tag":855,"props":866,"children":867},{},[868],{"type":52,"value":869},"Primary primitives",{"type":47,"tag":871,"props":872,"children":873},"tbody",{},[874,903,928,953,986,1009,1045,1068,1103,1153],{"type":47,"tag":851,"props":875,"children":876},{},[877,883,888],{"type":47,"tag":878,"props":879,"children":880},"td",{},[881],{"type":52,"value":882},"HTTP handler does slow side effects before responding",{"type":47,"tag":878,"props":884,"children":885},{},[886],{"type":52,"value":887},"Emit event, return fast",{"type":47,"tag":878,"props":889,"children":890},{},[891,896,898],{"type":47,"tag":118,"props":892,"children":894},{"className":893},[],[895],{"type":52,"value":299},{"type":52,"value":897},", event trigger, ",{"type":47,"tag":118,"props":899,"children":901},{"className":900},[],[902],{"type":52,"value":257},{"type":47,"tag":851,"props":904,"children":905},{},[906,911,916],{"type":47,"tag":878,"props":907,"children":908},{},[909],{"type":52,"value":910},"Webhook must acknowledge quickly but process reliably",{"type":47,"tag":878,"props":912,"children":913},{},[914],{"type":52,"value":915},"Verify signature, emit idempotent event",{"type":47,"tag":878,"props":917,"children":918},{},[919,921,926],{"type":52,"value":920},"Event ID, ",{"type":47,"tag":118,"props":922,"children":924},{"className":923},[],[925],{"type":52,"value":257},{"type":52,"value":927},", retries",{"type":47,"tag":851,"props":929,"children":930},{},[931,936,941],{"type":47,"tag":878,"props":932,"children":933},{},[934],{"type":52,"value":935},"Cron job loses progress midway",{"type":47,"tag":878,"props":937,"children":938},{},[939],{"type":52,"value":940},"Cron-triggered durable function",{"type":47,"tag":878,"props":942,"children":943},{},[944,946,951],{"type":52,"value":945},"Cron trigger, page-level ",{"type":47,"tag":118,"props":947,"children":949},{"className":948},[],[950],{"type":52,"value":257},{"type":52,"value":952},", flow control",{"type":47,"tag":851,"props":954,"children":955},{},[956,961,966],{"type":47,"tag":878,"props":957,"children":958},{},[959],{"type":52,"value":960},"Polling loop waits for external async work",{"type":47,"tag":878,"props":962,"children":963},{},[964],{"type":52,"value":965},"Durable wait or durable poll",{"type":47,"tag":878,"props":967,"children":968},{},[969,974,975,980,981],{"type":47,"tag":118,"props":970,"children":972},{"className":971},[],[973],{"type":52,"value":271},{"type":52,"value":125},{"type":47,"tag":118,"props":976,"children":978},{"className":977},[],[979],{"type":52,"value":264},{"type":52,"value":125},{"type":47,"tag":118,"props":982,"children":984},{"className":983},[],[985],{"type":52,"value":257},{"type":47,"tag":851,"props":987,"children":988},{},[989,994,999],{"type":47,"tag":878,"props":990,"children":991},{},[992],{"type":52,"value":993},"Large fan-out exceeds request\u002Fserverless limits",{"type":47,"tag":878,"props":995,"children":996},{},[997],{"type":52,"value":998},"Split orchestration and item work",{"type":47,"tag":878,"props":1000,"children":1001},{},[1002,1007],{"type":47,"tag":118,"props":1003,"children":1005},{"className":1004},[],[1006],{"type":52,"value":278},{"type":52,"value":1008},", per-item function, concurrency",{"type":47,"tag":851,"props":1010,"children":1011},{},[1012,1017,1022],{"type":47,"tag":878,"props":1013,"children":1014},{},[1015],{"type":52,"value":1016},"External API hits 429s",{"type":47,"tag":878,"props":1018,"children":1019},{},[1020],{"type":52,"value":1021},"Move limits to function config",{"type":47,"tag":878,"props":1023,"children":1024},{},[1025,1031,1032,1038,1039],{"type":47,"tag":118,"props":1026,"children":1028},{"className":1027},[],[1029],{"type":52,"value":1030},"throttle",{"type":52,"value":125},{"type":47,"tag":118,"props":1033,"children":1035},{"className":1034},[],[1036],{"type":52,"value":1037},"rateLimit",{"type":52,"value":125},{"type":47,"tag":118,"props":1040,"children":1042},{"className":1041},[],[1043],{"type":52,"value":1044},"concurrency",{"type":47,"tag":851,"props":1046,"children":1047},{},[1048,1053,1058],{"type":47,"tag":878,"props":1049,"children":1050},{},[1051],{"type":52,"value":1052},"Human review can take days",{"type":47,"tag":878,"props":1054,"children":1055},{},[1056],{"type":52,"value":1057},"Persist the wait in Inngest",{"type":47,"tag":878,"props":1059,"children":1060},{},[1061,1066],{"type":47,"tag":118,"props":1062,"children":1064},{"className":1063},[],[1065],{"type":52,"value":271},{"type":52,"value":1067},", timeout, realtime",{"type":47,"tag":851,"props":1069,"children":1070},{},[1071,1076,1081],{"type":47,"tag":878,"props":1072,"children":1073},{},[1074],{"type":52,"value":1075},"AI agent\u002Ftool loop needs retry-safe progress",{"type":47,"tag":878,"props":1077,"children":1078},{},[1079],{"type":52,"value":1080},"One step per tool\u002Fmodel boundary",{"type":47,"tag":878,"props":1082,"children":1083},{},[1084,1089,1090,1095,1096,1101],{"type":47,"tag":118,"props":1085,"children":1087},{"className":1086},[],[1088],{"type":52,"value":292},{"type":52,"value":125},{"type":47,"tag":118,"props":1091,"children":1093},{"className":1092},[],[1094],{"type":52,"value":257},{"type":52,"value":125},{"type":47,"tag":118,"props":1097,"children":1099},{"className":1098},[],[1100],{"type":52,"value":264},{"type":52,"value":1102},", realtime",{"type":47,"tag":851,"props":1104,"children":1105},{},[1106,1111,1116],{"type":47,"tag":878,"props":1107,"children":1108},{},[1109],{"type":52,"value":1110},"AI workflow needs production evals",{"type":47,"tag":878,"props":1112,"children":1113},{},[1114],{"type":52,"value":1115},"Attach outcome signals to durable runs",{"type":47,"tag":878,"props":1117,"children":1118},{},[1119,1125,1126,1132,1133,1139,1140,1146,1147],{"type":47,"tag":118,"props":1120,"children":1122},{"className":1121},[],[1123],{"type":52,"value":1124},"meta.sessions",{"type":52,"value":125},{"type":47,"tag":118,"props":1127,"children":1129},{"className":1128},[],[1130],{"type":52,"value":1131},"step.score",{"type":52,"value":125},{"type":47,"tag":118,"props":1134,"children":1136},{"className":1135},[],[1137],{"type":52,"value":1138},"createScorer",{"type":52,"value":125},{"type":47,"tag":118,"props":1141,"children":1143},{"className":1142},[],[1144],{"type":52,"value":1145},"defer",{"type":52,"value":125},{"type":47,"tag":118,"props":1148,"children":1150},{"className":1149},[],[1151],{"type":52,"value":1152},"group.experiment",{"type":47,"tag":851,"props":1154,"children":1155},{},[1156,1161,1166],{"type":47,"tag":878,"props":1157,"children":1158},{},[1159],{"type":52,"value":1160},"Existing queue only hides fragile work",{"type":47,"tag":878,"props":1162,"children":1163},{},[1164],{"type":52,"value":1165},"Replace queue boundary gradually",{"type":47,"tag":878,"props":1167,"children":1168},{},[1169],{"type":52,"value":1170},"Event trigger, idempotency, function-level retries",{"type":47,"tag":66,"props":1172,"children":1174},{"id":1173},"integration-plan-format",[1175],{"type":52,"value":1176},"Integration Plan Format",{"type":47,"tag":55,"props":1178,"children":1179},{},[1180],{"type":52,"value":1181},"Before editing, summarize findings in this compact shape:",{"type":47,"tag":574,"props":1183,"children":1187},{"className":1184,"code":1186,"language":52,"meta":579},[1185],"language-text","Inngest audit:\n- Existing Inngest: none \u002F partial \u002F healthy \u002F risky\n- Framework: \u003Cframework and evidence>\n- Best first slice: \u003Cfile + workflow>\n- Why: \u003Closs\u002Ftimeout\u002Fretry\u002Fidempotency failure>\n- Proposed primitives: \u003Cevent, steps, flow control, waits, realtime>\n- Idempotency key: \u003Csource of truth>\n- Files likely touched: \u003Cshort list>\n- Tests\u002Fchecks: \u003Ccommands or focused cases>\n",[1188],{"type":47,"tag":118,"props":1189,"children":1190},{"__ignoreMap":579},[1191],{"type":52,"value":1186},{"type":47,"tag":55,"props":1193,"children":1194},{},[1195],{"type":52,"value":1196},"Then implement unless the user asked for audit-only.",{"type":47,"tag":66,"props":1198,"children":1200},{"id":1199},"existing-inngest-checklist",[1201],{"type":52,"value":1202},"Existing Inngest Checklist",{"type":47,"tag":55,"props":1204,"children":1205},{},[1206],{"type":52,"value":1207},"If Inngest is already present, verify:",{"type":47,"tag":78,"props":1209,"children":1210},{},[1211,1216,1229,1249,1260,1265,1270,1275,1287,1292,1297,1302],{"type":47,"tag":82,"props":1212,"children":1213},{},[1214],{"type":52,"value":1215},"A single shared client is exported from a stable module.",{"type":47,"tag":82,"props":1217,"children":1218},{},[1219,1221,1227],{"type":52,"value":1220},"The app ",{"type":47,"tag":118,"props":1222,"children":1224},{"className":1223},[],[1225],{"type":52,"value":1226},"id",{"type":52,"value":1228}," is a stable slug and is not derived from deploy-specific data.",{"type":47,"tag":82,"props":1230,"children":1231},{},[1232,1234,1240,1242,1248],{"type":52,"value":1233},"v4 local development uses ",{"type":47,"tag":118,"props":1235,"children":1237},{"className":1236},[],[1238],{"type":52,"value":1239},"INNGEST_DEV=1",{"type":52,"value":1241},"; production uses\n",{"type":47,"tag":118,"props":1243,"children":1245},{"className":1244},[],[1246],{"type":52,"value":1247},"INNGEST_SIGNING_KEY",{"type":52,"value":309},{"type":47,"tag":82,"props":1250,"children":1251},{},[1252,1254,1259],{"type":52,"value":1253},"Serve endpoint path is discoverable, usually ",{"type":47,"tag":118,"props":1255,"children":1257},{"className":1256},[],[1258],{"type":52,"value":243},{"type":52,"value":309},{"type":47,"tag":82,"props":1261,"children":1262},{},[1263],{"type":52,"value":1264},"The serve handler registers all functions that should sync.",{"type":47,"tag":82,"props":1266,"children":1267},{},[1268],{"type":52,"value":1269},"Side effects and non-deterministic work are inside steps.",{"type":47,"tag":82,"props":1271,"children":1272},{},[1273],{"type":52,"value":1274},"Step IDs are stable and descriptive.",{"type":47,"tag":82,"props":1276,"children":1277},{},[1278,1280,1286],{"type":52,"value":1279},"Event names follow ",{"type":47,"tag":118,"props":1281,"children":1283},{"className":1282},[],[1284],{"type":52,"value":1285},"domain\u002Fnoun.verb",{"type":52,"value":309},{"type":47,"tag":82,"props":1288,"children":1289},{},[1290],{"type":52,"value":1291},"Events that may be replayed use deterministic IDs.",{"type":47,"tag":82,"props":1293,"children":1294},{},[1295],{"type":52,"value":1296},"Webhook handlers verify signatures before emitting events.",{"type":47,"tag":82,"props":1298,"children":1299},{},[1300],{"type":52,"value":1301},"Flow control is configured where external APIs have limits.",{"type":47,"tag":82,"props":1303,"children":1304},{},[1305,1307,1313,1315,1320],{"type":52,"value":1306},"Realtime uses v4 native ",{"type":47,"tag":118,"props":1308,"children":1310},{"className":1309},[],[1311],{"type":52,"value":1312},"inngest\u002Frealtime",{"type":52,"value":1314},", not the v3\n",{"type":47,"tag":118,"props":1316,"children":1318},{"className":1317},[],[1319],{"type":52,"value":307},{"type":52,"value":1321}," package.",{"type":47,"tag":66,"props":1323,"children":1325},{"id":1324},"durable-agent-patterns",[1326],{"type":52,"value":1327},"Durable Agent Patterns",{"type":47,"tag":55,"props":1329,"children":1330},{},[1331],{"type":52,"value":1332},"Use Inngest when an AI or agent workflow needs durable progress across model\ncalls, tool calls, waits, approvals, or streaming UI updates.",{"type":47,"tag":55,"props":1334,"children":1335},{},[1336],{"type":52,"value":1337},"Good candidates:",{"type":47,"tag":78,"props":1339,"children":1340},{},[1341,1346,1351,1356,1361,1366],{"type":47,"tag":82,"props":1342,"children":1343},{},[1344],{"type":52,"value":1345},"Multi-step agent that calls tools or external APIs.",{"type":47,"tag":82,"props":1347,"children":1348},{},[1349],{"type":52,"value":1350},"LLM workflow that may exceed one HTTP request lifetime.",{"type":47,"tag":82,"props":1352,"children":1353},{},[1354],{"type":52,"value":1355},"Human-in-the-loop review, approval, correction, or escalation.",{"type":47,"tag":82,"props":1357,"children":1358},{},[1359],{"type":52,"value":1360},"Agent that must pause for an external event or scheduled follow-up.",{"type":47,"tag":82,"props":1362,"children":1363},{},[1364],{"type":52,"value":1365},"Bulk AI work that needs provider-level rate limits and cost protection.",{"type":47,"tag":82,"props":1367,"children":1368},{},[1369],{"type":52,"value":1370},"User-visible agent progress that should stream from durable execution.",{"type":47,"tag":55,"props":1372,"children":1373},{},[1374],{"type":52,"value":1375},"Recommended shape:",{"type":47,"tag":164,"props":1377,"children":1378},{},[1379,1390,1401,1420,1439,1466],{"type":47,"tag":82,"props":1380,"children":1381},{},[1382,1384,1389],{"type":52,"value":1383},"HTTP\u002FUI request stores the user intent and emits an event with a stable\n",{"type":47,"tag":118,"props":1385,"children":1387},{"className":1386},[],[1388],{"type":52,"value":1226},{"type":52,"value":309},{"type":47,"tag":82,"props":1391,"children":1392},{},[1393,1395,1400],{"type":52,"value":1394},"Inngest function loads state inside ",{"type":47,"tag":118,"props":1396,"children":1398},{"className":1397},[],[1399],{"type":52,"value":257},{"type":52,"value":309},{"type":47,"tag":82,"props":1402,"children":1403},{},[1404,1406,1411,1413,1418],{"type":52,"value":1405},"Each model call, tool call, vector search, and external side effect lives in\nits own ",{"type":47,"tag":118,"props":1407,"children":1409},{"className":1408},[],[1410],{"type":52,"value":292},{"type":52,"value":1412}," or ",{"type":47,"tag":118,"props":1414,"children":1416},{"className":1415},[],[1417],{"type":52,"value":257},{"type":52,"value":1419}," boundary.",{"type":47,"tag":82,"props":1421,"children":1422},{},[1423,1425,1430,1431,1437],{"type":52,"value":1424},"Human pauses use ",{"type":47,"tag":118,"props":1426,"children":1428},{"className":1427},[],[1429],{"type":52,"value":271},{"type":52,"value":1412},{"type":47,"tag":118,"props":1432,"children":1434},{"className":1433},[],[1435],{"type":52,"value":1436},"step.waitForSignal",{"type":52,"value":1438}," with a timeout.",{"type":47,"tag":82,"props":1440,"children":1441},{},[1442,1444,1450,1452,1458,1460,1465],{"type":52,"value":1443},"Progress updates use ",{"type":47,"tag":118,"props":1445,"children":1447},{"className":1446},[],[1448],{"type":52,"value":1449},"step.realtime.publish",{"type":52,"value":1451}," between steps, or\n",{"type":47,"tag":118,"props":1453,"children":1455},{"className":1454},[],[1456],{"type":52,"value":1457},"inngest.realtime.publish",{"type":52,"value":1459}," inside an existing ",{"type":47,"tag":118,"props":1461,"children":1463},{"className":1462},[],[1464],{"type":52,"value":257},{"type":52,"value":309},{"type":47,"tag":82,"props":1467,"children":1468},{},[1469,1471,1476,1477,1482,1484,1489],{"type":52,"value":1470},"Provider rate limits use ",{"type":47,"tag":118,"props":1472,"children":1474},{"className":1473},[],[1475],{"type":52,"value":1044},{"type":52,"value":125},{"type":47,"tag":118,"props":1478,"children":1480},{"className":1479},[],[1481],{"type":52,"value":1030},{"type":52,"value":1483},", or ",{"type":47,"tag":118,"props":1485,"children":1487},{"className":1486},[],[1488],{"type":52,"value":1037},{"type":52,"value":1490},", not\nad hoc in-process throttlers.",{"type":47,"tag":55,"props":1492,"children":1493},{},[1494],{"type":52,"value":1495},"Avoid:",{"type":47,"tag":78,"props":1497,"children":1498},{},[1499,1504,1509,1514,1526],{"type":47,"tag":82,"props":1500,"children":1501},{},[1502],{"type":52,"value":1503},"Keeping agent state only in memory.",{"type":47,"tag":82,"props":1505,"children":1506},{},[1507],{"type":52,"value":1508},"Retrying whole agent loops after a single tool failure.",{"type":47,"tag":82,"props":1510,"children":1511},{},[1512],{"type":52,"value":1513},"Charging for repeated successful model calls because the result was not\nmemoized.",{"type":47,"tag":82,"props":1515,"children":1516},{},[1517,1519,1524],{"type":52,"value":1518},"Using ",{"type":47,"tag":118,"props":1520,"children":1522},{"className":1521},[],[1523],{"type":52,"value":352},{"type":52,"value":1525}," or a cron poller for follow-ups and approvals.",{"type":47,"tag":82,"props":1527,"children":1528},{},[1529],{"type":52,"value":1530},"Streaming progress from a process-local WebSocket server when the workflow\nitself is durable elsewhere.",{"type":47,"tag":66,"props":1532,"children":1534},{"id":1533},"implementation-guardrails",[1535],{"type":52,"value":1536},"Implementation Guardrails",{"type":47,"tag":78,"props":1538,"children":1539},{},[1540,1545,1550,1555,1560,1565],{"type":47,"tag":82,"props":1541,"children":1542},{},[1543],{"type":52,"value":1544},"Do not replace working queues, crons, or webhooks blindly. First preserve\nbehavior with a thin Inngest slice.",{"type":47,"tag":82,"props":1546,"children":1547},{},[1548],{"type":52,"value":1549},"Do not create duplicate clients or serve endpoints if the repo already has\nthem.",{"type":47,"tag":82,"props":1551,"children":1552},{},[1553],{"type":52,"value":1554},"Do not put database writes, API calls, random IDs, timestamps, or LLM calls\noutside steps in the new function.",{"type":47,"tag":82,"props":1556,"children":1557},{},[1558],{"type":52,"value":1559},"Do not hide missing idempotency behind retries. Retries require idempotent\nside effects.",{"type":47,"tag":82,"props":1561,"children":1562},{},[1563],{"type":52,"value":1564},"Do not hardcode secrets or dev-mode flags in source.",{"type":47,"tag":82,"props":1566,"children":1567},{},[1568],{"type":52,"value":1569},"Do not leave the app unable to sync: register new functions with the serve\nendpoint and run available type\u002Ftests.",{"type":47,"tag":66,"props":1571,"children":1573},{"id":1572},"verification",[1574],{"type":52,"value":1575},"Verification",{"type":47,"tag":55,"props":1577,"children":1578},{},[1579],{"type":52,"value":1580},"Pick checks that prove the integration path:",{"type":47,"tag":78,"props":1582,"children":1583},{},[1584,1589,1594,1599,1604],{"type":47,"tag":82,"props":1585,"children":1586},{},[1587],{"type":52,"value":1588},"Typecheck\u002Fbuild\u002Flint the touched app.",{"type":47,"tag":82,"props":1590,"children":1591},{},[1592],{"type":52,"value":1593},"Run existing tests around the migrated handler or workflow.",{"type":47,"tag":82,"props":1595,"children":1596},{},[1597],{"type":52,"value":1598},"Add focused tests for \"handler emits event and returns fast\" and \"function\ncalls the same domain operations in step boundaries\" where the repo supports\nit.",{"type":47,"tag":82,"props":1600,"children":1601},{},[1602],{"type":52,"value":1603},"If local runtime is available, start the app and Inngest dev server, confirm\nthe function syncs, then send a sample event.",{"type":47,"tag":82,"props":1605,"children":1606},{},[1607],{"type":52,"value":1608},"If only static checks are available, explicitly state that runtime sync was\nnot verified.",{"type":47,"tag":1610,"props":1611,"children":1612},"style",{},[1613],{"type":52,"value":1614},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":1616,"total":1710},[1617,1636,1649,1663,1676,1683,1698],{"slug":154,"name":154,"fn":1618,"description":1619,"org":1620,"tags":1621,"stars":23,"repoUrl":24,"updatedAt":1635},"build and debug Inngest agent evals","Use when building, migrating, or debugging Agent Evals on Inngest: scoring AI agent or workflow outcomes, deferred scorers, sessions, traces, step experiments, experiment variant attribution, Insights queries, or production eval loops for prompts, models, tools, providers, and agent behavior. Covers TypeScript SDK v4 scoring beta APIs, `scoreMiddleware`, `step.score`, `inngest.score`, `createScorer`, `defer`, `group.experiment`, `experimentRef`, `meta.sessions`, and when to use durable workflow primitives for outcome-based evaluation.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1622,1625,1628,1629,1632],{"name":1623,"slug":1624,"type":15},"Agents","agents",{"name":1626,"slug":1627,"type":15},"Evals","evals",{"name":9,"slug":8,"type":15},{"name":1630,"slug":1631,"type":15},"Observability","observability",{"name":1633,"slug":1634,"type":15},"Workflow Automation","workflow-automation","2026-07-12T07:36:51.711641",{"slug":1637,"name":1637,"fn":1638,"description":1639,"org":1640,"tags":1641,"stars":23,"repoUrl":24,"updatedAt":1648},"inngest-agents","build durable AI agent workflows","Use when building durable AI agents or agentic workflows with Inngest and AgentKit, including model calls, tool calls, multi-agent networks, human approval, realtime progress, provider rate limits, crash-safe execution, and Agent Evals handoff. Covers AgentKit, `step.ai`, `step.run`, `step.waitForEvent`, native realtime, and when to use lower-level Inngest primitives instead of an in-memory agent loop. Use `inngest-agent-evals` with this skill when the user wants scoring, sessions, experiments, deferred scorers, or outcome-based evaluation for the agent.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1642,1643,1644,1645],{"name":1623,"slug":1624,"type":15},{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},{"name":1646,"slug":1647,"type":15},"LLM","llm","2026-07-12T07:36:45.984181",{"slug":1650,"name":1650,"fn":1651,"description":1652,"org":1653,"tags":1654,"stars":23,"repoUrl":24,"updatedAt":1662},"inngest-api","interact with Inngest REST API","Use when the user explicitly asks for the Inngest REST API v2, raw HTTP, OpenAPI, API docs, API authentication, or an endpoint that the Inngest CLI does not expose. Covers api-docs.inngest.com, llms.txt, the OpenAPI v2 spec, Bearer authentication with API keys or signing keys, production and local base URLs, raw curl\u002Ffetch requests, request-shape discovery, pagination, secret redaction, and when to prefer the `inngest-api-cli` skill instead.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1655,1658,1661],{"name":1656,"slug":1657,"type":15},"API Development","api-development",{"name":1659,"slug":1660,"type":15},"REST API","rest-api",{"name":1633,"slug":1634,"type":15},"2026-07-12T07:36:39.364409",{"slug":1664,"name":1664,"fn":1665,"description":1666,"org":1667,"tags":1668,"stars":23,"repoUrl":24,"updatedAt":1675},"inngest-api-cli","operate Inngest API resources via CLI","Use when operating Inngest API resources from the terminal with `npx inngest-cli@latest api`: Cloud\u002Flocal run debugging, event-run lookup, function traces, function invocation, app syncs, webhooks, environments, keys, account checks, and Insights queries. Provides prescriptive command routing for agents: which CLI command to run for a run ID, event ID, app ID, function ID, Cloud environment, API key, missing ID, or potentially mutating operation. Use `inngest-cli` for dev server setup\u002Fgeneral CLI workflows and `inngest-api` only when raw REST API v2 docs or OpenAPI fallback are needed.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1669,1670,1671,1674],{"name":1656,"slug":1657,"type":15},{"name":13,"slug":14,"type":15},{"name":1672,"slug":1673,"type":15},"CLI","cli",{"name":9,"slug":8,"type":15},"2026-07-12T07:36:47.58183",{"slug":4,"name":4,"fn":5,"description":6,"org":1677,"tags":1678,"stars":23,"repoUrl":24,"updatedAt":25},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1679,1680,1681,1682],{"name":13,"slug":14,"type":15},{"name":21,"slug":22,"type":15},{"name":18,"slug":19,"type":15},{"name":9,"slug":8,"type":15},{"slug":1684,"name":1684,"fn":1685,"description":1686,"org":1687,"tags":1688,"stars":23,"repoUrl":24,"updatedAt":1697},"inngest-cli","configure Inngest CLI and dev server","Use when installing or running the Inngest CLI and Dev Server for local development, local testing, serve endpoint debugging, Docker or Docker Compose setup, MCP configuration, self-hosted `inngest start`, or deployment workflow checks. Covers `inngest dev`, `inngest start`, auto-discovery, config files, environment variables, `@inngest\u002Ftest`, local event sending, platform gotchas, and production\u002Fself-hosted server flags.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1689,1690,1693,1694],{"name":1672,"slug":1673,"type":15},{"name":1691,"slug":1692,"type":15},"Docker","docker",{"name":9,"slug":8,"type":15},{"name":1695,"slug":1696,"type":15},"Local Development","local-development","2026-07-12T07:36:40.694652",{"slug":131,"name":131,"fn":1699,"description":1700,"org":1701,"tags":1702,"stars":23,"repoUrl":24,"updatedAt":1709},"build durable and retry-safe functions","Use when building functions that must survive process crashes, retry automatically on failure, run on a schedule, react to events, or maintain state across infrastructure failures — e.g., webhook handlers that drop events, flaky cron jobs, background jobs that fail mid-execution, or workflows that need to resume where they left off. Covers Inngest function configuration, triggers (events, cron, invoke), step execution and memoization, idempotency, cancellation, error handling, retries, logging, and observability.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1703,1704,1707,1708],{"name":13,"slug":14,"type":15},{"name":1705,"slug":1706,"type":15},"Backend","backend",{"name":9,"slug":8,"type":15},{"name":1633,"slug":1634,"type":15},"2026-07-12T07:36:57.141023",14,{"items":1712,"total":1710},[1713,1721,1728,1734,1741,1748,1755,1762,1773,1786,1802,1817],{"slug":154,"name":154,"fn":1618,"description":1619,"org":1714,"tags":1715,"stars":23,"repoUrl":24,"updatedAt":1635},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1716,1717,1718,1719,1720],{"name":1623,"slug":1624,"type":15},{"name":1626,"slug":1627,"type":15},{"name":9,"slug":8,"type":15},{"name":1630,"slug":1631,"type":15},{"name":1633,"slug":1634,"type":15},{"slug":1637,"name":1637,"fn":1638,"description":1639,"org":1722,"tags":1723,"stars":23,"repoUrl":24,"updatedAt":1648},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1724,1725,1726,1727],{"name":1623,"slug":1624,"type":15},{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},{"name":1646,"slug":1647,"type":15},{"slug":1650,"name":1650,"fn":1651,"description":1652,"org":1729,"tags":1730,"stars":23,"repoUrl":24,"updatedAt":1662},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1731,1732,1733],{"name":1656,"slug":1657,"type":15},{"name":1659,"slug":1660,"type":15},{"name":1633,"slug":1634,"type":15},{"slug":1664,"name":1664,"fn":1665,"description":1666,"org":1735,"tags":1736,"stars":23,"repoUrl":24,"updatedAt":1675},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1737,1738,1739,1740],{"name":1656,"slug":1657,"type":15},{"name":13,"slug":14,"type":15},{"name":1672,"slug":1673,"type":15},{"name":9,"slug":8,"type":15},{"slug":4,"name":4,"fn":5,"description":6,"org":1742,"tags":1743,"stars":23,"repoUrl":24,"updatedAt":25},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1744,1745,1746,1747],{"name":13,"slug":14,"type":15},{"name":21,"slug":22,"type":15},{"name":18,"slug":19,"type":15},{"name":9,"slug":8,"type":15},{"slug":1684,"name":1684,"fn":1685,"description":1686,"org":1749,"tags":1750,"stars":23,"repoUrl":24,"updatedAt":1697},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1751,1752,1753,1754],{"name":1672,"slug":1673,"type":15},{"name":1691,"slug":1692,"type":15},{"name":9,"slug":8,"type":15},{"name":1695,"slug":1696,"type":15},{"slug":131,"name":131,"fn":1699,"description":1700,"org":1756,"tags":1757,"stars":23,"repoUrl":24,"updatedAt":1709},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1758,1759,1760,1761],{"name":13,"slug":14,"type":15},{"name":1705,"slug":1706,"type":15},{"name":9,"slug":8,"type":15},{"name":1633,"slug":1634,"type":15},{"slug":138,"name":138,"fn":1763,"description":1764,"org":1765,"tags":1766,"stars":23,"repoUrl":24,"updatedAt":1772},"design event-driven workflows","Use when designing event-driven workflows, decoupling services, implementing fan-out patterns (one trigger, many downstream handlers), implementing idempotent event handling with IDs (24-hour dedupe window), or handling at-least-once delivery from external sources like Stripe webhooks. Covers Inngest event schema, payload format, naming conventions, IDs for idempotency, the ts param, fan-out patterns, and system events like inngest\u002Ffunction.failed.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1767,1770,1771],{"name":1768,"slug":1769,"type":15},"Data Pipeline","data-pipeline",{"name":9,"slug":8,"type":15},{"name":1633,"slug":1634,"type":15},"2026-07-12T07:36:44.685364",{"slug":1774,"name":1774,"fn":1775,"description":1776,"org":1777,"tags":1778,"stars":23,"repoUrl":24,"updatedAt":1785},"inngest-flow-control","manage API rate limits and load","Use when handling external API rate limits (e.g., OpenAI 429s, HubSpot or Stripe rate limits), preventing duplicate work from rapid event bursts (debouncing user actions), spreading load over time, ensuring per-tenant fairness, processing events in batches, limiting concurrent runs of the same operation, or assigning priority to important runs. Covers Inngest flow control: concurrency limits with keys, throttling, rate limiting, debounce, priority, singleton, and event batching.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1779,1780,1781,1782],{"name":1656,"slug":1657,"type":15},{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},{"name":1783,"slug":1784,"type":15},"Performance","performance","2026-07-12T07:36:52.987451",{"slug":1787,"name":1787,"fn":1788,"description":1789,"org":1790,"tags":1791,"stars":23,"repoUrl":24,"updatedAt":1801},"inngest-middleware","add middleware to Inngest durable functions","Use when adding cross-cutting concerns to durable functions — structured logging or tracing across all functions, error tracking with Sentry, payload encryption for sensitive data, dependency injection of clients (DB, Stripe, etc.) into function handlers, custom telemetry, or behavior that should apply uniformly across many functions. Covers Inngest middleware lifecycle, creating custom middleware, dependencyInjectionMiddleware, @inngest\u002Fmiddleware-encryption, @inngest\u002Fmiddleware-sentry, and custom middleware patterns.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1792,1793,1794,1797,1798],{"name":18,"slug":19,"type":15},{"name":9,"slug":8,"type":15},{"name":1795,"slug":1796,"type":15},"Middleware","middleware",{"name":1630,"slug":1631,"type":15},{"name":1799,"slug":1800,"type":15},"Sentry","sentry","2026-07-12T07:36:50.127999",{"slug":1803,"name":1803,"fn":1804,"description":1805,"org":1806,"tags":1807,"stars":23,"repoUrl":24,"updatedAt":1816},"inngest-realtime","stream durable workflow updates to UI","Use when streaming durable workflow updates to a UI in real time — live order status pages that animate as steps complete, AI agent token streaming from a function to the browser, log tailing for long-running jobs, or human-in-the-loop approval flows that publish a prompt and wait for a user reply. Covers Inngest v4 native realtime: defining typed channels, publishing from inside step.run, minting subscription tokens via server actions, and consuming the stream from React\u002FNext.js client components.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1808,1809,1812,1813],{"name":13,"slug":14,"type":15},{"name":1810,"slug":1811,"type":15},"Frontend","frontend",{"name":9,"slug":8,"type":15},{"name":1814,"slug":1815,"type":15},"Real-time","real-time","2026-07-12T07:36:48.895092",{"slug":123,"name":123,"fn":1818,"description":1819,"org":1820,"tags":1821,"stars":23,"repoUrl":24,"updatedAt":1828},"build durable TypeScript workflows","Use when adding durable execution to a TypeScript project — building retry-safe webhook handlers, background jobs that survive crashes, scheduled tasks, or long-running workflows that outlive a single request. Covers Inngest SDK installation, client config, environment variables, serve endpoints (Next.js, Express, Hono, Fastify), connect-as-worker mode, and the local dev server.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1822,1823,1824,1825],{"name":13,"slug":14,"type":15},{"name":1705,"slug":1706,"type":15},{"name":9,"slug":8,"type":15},{"name":1826,"slug":1827,"type":15},"TypeScript","typescript","2026-07-12T07:36:42.004122"]