← Plugin catalog
Developer Tools

Inngest

Inngest v0.4.3

Debug Inngest Cloud workflows.

Create a free account to save this plugin.

From the developer

Declared capabilities

  • Code
  • MCP

Not specified in the available declarations: limitations, pricing & account requirements.

Sources & dates

Developer declarations; not independently tested. Listing last checked Nov 11, 2026. Package observed Nov 10, 2026.

View package source →

Description

From the marketplace listing

Connect your Inngest account to inspect deployed apps, functions, events, runs, traces, and Insights through OAuth MCP. Diagnose failures and carry out requested workflow operations in the selected environment. Coding hosts can also use the bundled skills to build durable functions and agents, audit codebases, and test locally with an optional Dev Server connection.

Language: English · Automatically detected from descriptions.

Matches for “no code”

Exact text from the indicated source. A mention alone does not establish support for your task.

Publisher full description

Connect your Inngest account to inspect deployed apps, functions, events, runs, traces, and Insights through OAuth MCP. Diagnose failures and carry out requested workflow operations in the selected environment. Coding hosts can also use the bundled skills to build durable functions and agents, audit codebases, and test locally with an optional Dev Server connection.

Publisher capabilities · listing

Code MCP

Publisher keywords · listing

inngest durable-functions background-jobs agent-evals workflow codex mcp

What changed

· 7 observations

Capabilities & instructions

Skill instructions changed from “Reference](../references/expressions.md)” to “Reference](../../references/expressions.md)”.

View comparison →
Capabilities & instructions

Skill instructions changed from “Reference](../references/expressions.md)” to “Reference](../../references/expressions.md)”.

View comparison →
Capabilities & instructions

Supporting files updated; open the comparison for details. Skill instructions changed from “Reference](../references/expressions.md)” to “Reference](../../references/expressions.md)”.

View comparison →

Technical updates · 3

Supporting file metadata differs

View technical comparison →

Package or technical metadata updated

View technical comparison →

Package or technical metadata updated

View technical comparison →

Keywords

Files & skills

File archives

Plugin package47 files · 93.9 KBBrowse files →
Skill instructions
inngest-agent-evals10.7 KB

View saved version →

---
name: inngest-agent-evals
description: "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."
---

# Inngest Agent Evals

Use this skill when the user wants to evaluate AI agents or AI workflows in
production, add scoring, compare prompts/models/tools, group related runs, or
debug why an agent outcome was good or bad.

Agent Evals is not a separate package. It is the production evaluation workflow
built from Inngest functions, durable steps, scores, deferred scorers, sessions,
traces, experiments, and Insights.

## Canonical References

Check the public docs first when exact API details matter:

- Agent Evals overview: https://www.inngest.com/docs/learn/agent-evals
- Scoring guide: https://www.inngest.com/docs/features/inngest-functions/steps-workflows/scoring
- Deferred scoring guide: https://www.inngest.com/docs/features/inngest-functions/steps-workflows/deferred-scoring
- Step experiments guide: https://www.inngest.com/docs/features/inngest-functions/steps-workflows/step-experiments
- Sessions: https://www.inngest.com/docs/features/events-triggers/sessions
- Traces: https://www.inngest.com/docs/platform/monitor/traces
- Insights: https://www.inngest.com/docs/platform/monitor/insights
- Scoring reference: https://www.inngest.com/docs/reference/typescript/v4/functions/scoring
- `group.experiment()` reference: https://www.inngest.com/docs/reference/typescript/v4/functions/group-experiment
- Launch context: https://www.inngest.com/blog/introducing-agent-evals

## Decision Flow

Start from the outcome, not the mechanism:

1. Identify the product or quality signal: helpful click, ticket resolution,
   conversion, guardrail pass, retrieval quality, model confidence, latency,
   cost, human review, or LLM-as-judge result.
2. Decide when the signal appears:
   - During the run: use direct scoring with `step.score()` or
     `inngest.score()`.
   - After the run: use deferred scoring with `createScorer()` and `defer()`,
     or explicit `inngest.score({ runId })`.
3. Decide how humans will inspect related work:
   - Use `meta.sessions` for repeated high-cardinality identifiers such as
     `conversation_id`, `ticket_id`, `agent_run_id`, or `import_id`.
   - Use Insights for ad hoc historical analysis, low-cardinality filters, SQL
     aggregates, and broad investigation.
4. Decide whether to compare variants:
   - Use `group.experiment()` for prompt, model, provider, tool, workflow, or
     rollout comparisons.
   - Pass `experimentRef` to deferred or later scores when the score should be
     credited to the selected variant.
5. Preserve traceability:
   - Keep model calls, tool calls, waits, database writes, and scoring work in
     durable steps so traces explain why the score happened.

## Setup Requirements

- Use TypeScript SDK v4 and install the latest SDK: `npm install inngest@latest`.
- Scoring and deferred scoring are beta APIs; verify current imports against
  the docs before shipping user-facing examples.
- `step.score()` requires `scoreMiddleware()` from `inngest/experimental` on
  the Inngest client.
- `createScorer()` is imported from `inngest/experimental` and the scorer must
  be registered in the serve handler with other functions.
- Sessions sent through the TypeScript SDK require v4.7.0 or later.
- Step experiments require v4.8.0 or later for `group.experiment()` and the
  `experiment` helper from `inngest`.

Client shape:

```typescript
import { Inngest } from "inngest";
import { scoreMiddleware } from "inngest/experimental";

exp

Preview of the first 4,000 characters. Read full instructions →

inngest-agents8.92 KB

View saved version →

---
name: inngest-agents
description: 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.
---

# Inngest Agents

Use this skill when the user wants to build, migrate, or debug an AI agent,
multi-step AI workflow, tool-calling loop, support agent, research agent,
human-in-the-loop review flow, or realtime agent UI.

Inngest's AgentKit defines agents with `createAgent`; when an AgentKit run is
owned by an Inngest function, model calls use Inngest `step.ai` so they retry
and cache model results durably. Use the lower-level Inngest step primitives
around the agent for database reads/writes, tool side effects, waits,
approvals, realtime progress, and flow control.

Official references:

- AgentKit agents: https://agentkit.inngest.com/concepts/agents
- `createAgent`: https://agentkit.inngest.com/reference/create-agent
- AI inference and `step.ai`: https://www.inngest.com/docs/features/inngest-functions/steps-workflows/step-ai-orchestration
- Agent Evals: https://www.inngest.com/docs/learn/agent-evals
- AgentKit realtime hooks: https://www.inngest.com/changelog/2025-09-24-agentkit-use-agent

## Copyable Example

When starting a durable support or tool-calling agent from scratch, inspect the
companion example at `../../examples/durable-agent`. It shows the expected
agent-first shape: quick HTTP trigger, typed events, AgentKit inside an
Inngest function, step-scoped context loading, human approval with
`step.waitForEvent`, and durable side effects after approval.

## When to Use Inngest for Agents

Good fit:

- Agent can take longer than one HTTP request.
- Agent calls tools, APIs, databases, browsers, sandboxes, or MCP servers.
- Agent needs to survive deploys, crashes, serverless timeouts, or model/API
  failures.
- Agent may wait for human approval, external callbacks, scheduled follow-up,
  or user input.
- Agent progress should stream to a UI from the durable workflow.
- Model/provider calls need concurrency or throttle limits.
- Duplicate sends, charges, writes, or model calls would be costly.

Not usually worth it:

- One short, read-only model call with no side effects and no need for durable
  progress.
- UI-only autocomplete where losing the request is acceptable.

## Architecture

Use this shape unless the repo already has a stronger established pattern:

1. The HTTP/server action layer validates auth, stores the user's intent if
   needed, emits an event with a stable `id`, and returns quickly.
2. An Inngest function owns the agent run.
3. Load state and external context inside `step.run`.
4. Create AgentKit agents inside the function or import agent/network
   factories.
5. Run model inference through AgentKit / `step.ai`; wrap non-model tool side
   effects in `step.run`.
6. Use `step.waitForEvent` or `step.waitForSignal` for human approval and
   external callbacks.
7. Publish durable progress with native realtime.
8. Add sessions and scores when the agent outcome needs to be evaluated later.
9. Apply flow control at the function level for provider and tenant limits.

## Basic AgentKit Function

Prefer a small, typed function first; add networks and extra tools after the
single-agent path is proven.

```typescript
import { createAgent, openai } from "@inngest/agent-kit";
import { inngest } from "@/inngest/client";

export const summarizeTicket = inngest.createFunction(
  {
    id: "summarize-ticket",
    triggers: [{ event: "support/ticket.created" }],
    concurrency: [{ key: "event.data.accountId", limit: 2 }]
  },
  as

Preview of the first 4,000 characters. Read full instructions →

inngest-api4.93 KB

View saved version →

---
name: inngest-api
description: >-
  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/fetch requests, request-shape discovery, pagination,
  secret redaction, and when to prefer the `inngest-api-cli` skill instead.
---

# Inngest REST API v2

For Cloud operations with connected MCP tools, use `inngest-cloud` first.
Keep this skill for explicit terminal/HTTP work or a capability missing from
MCP. Do not ask for an API key when OAuth MCP can complete the task.

Use this skill for raw REST API v2 work and API reference lookup. If the task
can be completed through `npx inngest-cli@latest api`, use `inngest-api-cli`
instead; the CLI is safer for agents because it handles target/auth flags and
endpoint command wiring.

## Prefer CLI First

Use `inngest-api-cli` for:

- Run and trace debugging from a run ID or event ID.
- Account, environment, key, webhook, app sync, and function invocation checks.
- Insights table/schema/query workflows.
- Local dev server or Cloud operational checks.

Use raw REST API v2 only when:

- The CLI does not expose the needed endpoint.
- The user explicitly asks for HTTP, curl, fetch, OpenAPI, or API docs.
- You need to inspect request/response schemas before deciding what to do.

## Docs Lookup

When precision matters, fetch current docs instead of guessing:

- API overview: `https://api-docs.inngest.com/`
- Authentication: `https://api-docs.inngest.com/authentication`
- LLM index: `https://api-docs.inngest.com/llms.txt`
- OpenAPI v2 spec: `https://api-docs.inngest.com/api-specs/v2.json`
- Markdown page pattern: add `.md` to a docs URL, for example
  `https://api-docs.inngest.com/v2/runs/GetFunctionTrace.md`
- Endpoint request/response schemas:
  [references/rest-api-v2.md](references/rest-api-v2.md)

If a Markdown page returns an error or omits generated reference details, use
the OpenAPI spec for methods, paths, parameters, request bodies, and schemas.

## Base URLs

- Cloud v2: `https://api.inngest.com/v2`
- Local dev server v2: `http://localhost:8288/api/v2`
- API docs say the dev server may also be reached through the local server
  origin. Confirm the actual dev server port before making local requests.

## Authentication

The REST API uses Bearer token authentication.

- Prefer `INNGEST_API_KEY` for requests from CI, scripts, tools, and agents.
- Signing keys are primarily for apps communicating with Inngest; use them for
  API requests only when that is the available, appropriate credential.
- API keys are for v2 endpoints only.
- Include `X-Inngest-Env` or use an environment-scoped API key when operating
  outside the default production environment.
- Never paste, print, commit, or log API keys, event keys, signing keys,
  webhook URLs, or decrypted secrets.

Example:

```bash
curl -fsSL \
  -H "Authorization: Bearer $INNGEST_API_KEY" \
  -H "X-Inngest-Env: $INNGEST_ENV" \
  https://api.inngest.com/v2/account
```

## Endpoint Discovery

Use the OpenAPI spec as the source of truth:

```bash
curl -fsSL https://api-docs.inngest.com/api-specs/v2.json
```

Current v2 areas include account, environments, keys, webhooks, apps, function
invocation, event-run lookup, function runs, traces, Insights, and partner APIs.
Endpoint coverage can change, so inspect the spec before writing a raw request.

For API-only or access-gated endpoints, such as partner-account endpoints,
confirm the user has the needed access before attempting a call.

## Request Rules

- Derive method, path, query params, headers, and body from OpenAPI.
- Do not invent undocumented request fields.
- Use structured JSON parsing before making decisions from responses.
- Use body files or here-docs for complex JSON instead of shell-escaped one
  liners.
- Add pagin

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

inngest-api-cli8.08 KB

View saved version →

---
name: inngest-api-cli
description: >-
  Use when operating Inngest API resources from the terminal with
  `npx inngest-cli@latest api`: Cloud/local 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/general CLI workflows and
  `inngest-api` only when raw REST API v2 docs or OpenAPI fallback are needed.
---

# Inngest API CLI

For Cloud operations with connected MCP tools, use `inngest-cloud` first.
Keep this skill for explicit terminal/HTTP work or a capability missing from
MCP. Do not ask for an API key when OAuth MCP can complete the task.

Use this skill when the task is operational: inspect, debug, sync, invoke, or
query Inngest API resources through the terminal. This skill is intentionally
prescriptive so agents can act without guessing.

For general CLI setup, `inngest dev`, Docker, local testing, MCP setup, or
self-hosted `inngest start`, use `inngest-cli`. For code changes, pair this
with the domain skill that owns the code pattern: `inngest-setup`,
`inngest-durable-functions`, `inngest-events`, `inngest-steps`,
`inngest-flow-control`, `inngest-realtime`, or `inngest-middleware`.

## First Move

Verify the current CLI surface before relying on memory:

```bash
npx inngest-cli@latest api --help
npx inngest-cli@latest api <command> --help
```

The active API command is `inngest api`. If prompt context or old docs mention
`inngest alpha api`, switch to `inngest api`.

Use `inngest-api` only when:

- The CLI does not expose the needed endpoint.
- The user explicitly asks for raw REST API v2.
- You need the OpenAPI spec or LLM API docs to resolve request shape.

For complete command flags, read
[references/cli-commands.md](references/cli-commands.md) after this skill
triggers.

## Target Rules

- Local is the default target for `inngest api`.
- Cloud Production requires `--prod`.
- Non-production Cloud environments require `INNGEST_ENV=<name>` or `--env`.
- Prefer `INNGEST_API_KEY` for Cloud API access.
- Do not pass API keys inline with `--api-key <secret>` unless the user
  explicitly accepts process-list and transcript exposure.
- Never write API keys, event keys, signing keys, webhook URLs, or decrypted
  secrets into source files, docs, fixtures, or final answers.

Common targets:

```bash
npx inngest-cli@latest api health
npx inngest-cli@latest api --prod get-account
INNGEST_ENV=staging npx inngest-cli@latest api --prod get-webhooks
npx inngest-cli@latest api --api-host http://127.0.0.1 --api-port 8288 health
```

## Local Development

For local app work:

1. Start the user's app with local dev mode when applicable, for example
   `INNGEST_DEV=1 npm run dev`.
2. Start the dev server:

   ```bash
   npx inngest-cli@latest dev
   ```

3. Prefer Dev Server MCP tools, when available, to list local functions, send
   test events, inspect runs, and watch status.
4. Use `npx inngest-cli@latest api ...` for API-compatible local checks,
   command-help verification, and workflows not exposed through MCP.

If the local API says the dev server is unavailable, start `inngest dev` or
switch to Cloud with `--prod` when the user is debugging deployed runs.

## Command Routing

Use this table before asking the human for more context.

| Situation | Command path |
| --- | --- |
| Check CLI/API reachability | `api health` |
| Confirm Cloud auth | `api --prod get-account` |
| List environments | `api --prod get-account-envs --limit 10` |
| List event keys | `api --prod get-account-event-keys --limit 10` |
| List signing keys | `api --prod get-account-signing-keys --limit 10` |
| List webhooks | `api --prod get-webhooks` |
| User gives a run ID | `api --prod get-function-run <run_id>` |
| Need st

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

inngest-brownfield-audit10.3 KB

View saved version →

---
name: inngest-brownfield-audit
description: 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.
---

# Inngest Brownfield Audit

Use this skill when the user asks Codex to inspect an existing codebase, add
Inngest "where it makes sense", migrate fragile background work, or find
durability gaps before making changes.

This is an agent-first workflow. Do the audit from evidence in the repo, name
the specific files and call sites that drove each conclusion, and make small
integration moves that preserve current behavior.

## When to Trigger

Use this skill for requests like:

- "Audit this repo for Inngest opportunities"
- "Add Inngest to this codebase"
- "Make our webhooks / cron jobs / background tasks reliable"
- "Find places where work can be lost on deploy or process crash"
- "Replace fragile polling, delayed jobs, or fire-and-forget promises"
- "Make this AI workflow / agent durable"

If the user is starting from scratch instead of a brownfield repo, use
`inngest-setup`, `inngest-durable-functions`, `inngest-events`,
`inngest-steps`, and, for AI workflows, the agent patterns in this skill. Use
`inngest-agent-evals` when the request includes scoring, sessions, experiments,
deferred scorers, Insights, or outcome-based evaluation.

## Audit Loop

1. **Map the project shape.**
   - Read `package.json`, workspace files, app/router structure, server entry
     points, deployment config, and test scripts.
   - Identify framework: Next.js App Router, Next.js Pages Router, Express,
     Hono, Fastify, Remix, SvelteKit, Astro, NestJS, worker-only service, or
     other.
   - Detect package manager and TypeScript conventions before adding files.

2. **Find existing Inngest usage.**
   - Search for `inngest`, `createFunction`, `serve(`, `/api/inngest`,
     `INNGEST_`, `step.run`, `step.sleep`, `step.waitForEvent`,
     `step.sendEvent`, `step.invoke`, `step.ai`, `inngest.send`, and
     `@inngest/realtime`.
   - If Inngest exists, inspect version, client config, serve endpoint,
     registered functions, event naming, env vars, and v3/v4 API shape before
     changing anything.

3. **Find durability gaps.**
   - Search for fire-and-forget work: `void someAsync()`, un-awaited promises,
     `.then(` chains, `setTimeout`, `setInterval`, detached jobs after HTTP
     response, and background work in route handlers.
   - Search for cron and schedulers: `cron`, `node-cron`, `agenda`, `bull`,
     `bullmq`, `bee-queue`, `qstash`, `sqs`, `temporal`, `trigger.dev`,
     deployment cron config, and scheduled API routes.
   - Search for webhooks and at-least-once producers: Stripe, Clerk, GitHub,
     Slack, Shopify, HubSpot, Linear, Svix, and generic `webhook`.
   - Search for long-running work: PDF generation, exports, video/image
     processing, embeddings, bulk email, imports, ETL, sync jobs, polling loops,
     retries, and external API calls.
   - Search for AI agent shapes: tool loops, LLM calls, streaming tokens,
     human approval, multi-step reasoning, vector search, eval loops, scoring,
     experiment assignment, user-feedback signals, and provider calls that need
     rate limits or retry-safe state.

4. **Classify each candidate.**
   - **P0:** user-visible loss, duplicate charge/email/action, timeout, missed
     webhook, or crash-prone workflow.
   - **P1:** fragile but recoverable background work, manual retry burden,
     noisy 429s, or poor observability.
   - **P2:** cleanup, ergonomics, or future migration opportunity.
   - For each candidate, record: file, current trigger, side effects,
     idempotency key, failure mode, recommended Inngest primitive, migration
     s

Preview of the first 4,000 characters. Read full instructions →

inngest-cli13.9 KB

View saved version →

---
name: inngest-cli
description: 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/test`, local event sending, platform gotchas, and production/self-hosted server flags.
---

# Inngest CLI

Master the Inngest CLI for local development, testing, and self-hosted production. The CLI provides the Dev Server — a fully-featured, open-source local version of the Inngest Platform.

> **These skills are focused on TypeScript.** For Python or Go, refer to the [Inngest documentation](https://www.inngest.com/llms.txt) for language-specific guidance. Core concepts apply across all languages.

Use this skill for CLI setup, Dev Server workflows, local testing, Docker, MCP, and self-hosted server operations. For run/trace inspection through `inngest api`, use `inngest-api-cli` when available.

## Installation

```bash
# npx (recommended — always latest)
npx inngest-cli@latest dev

# yarn
yarn dlx inngest-cli@latest dev

# pnpm
pnpm dlx inngest-cli@latest dev

# Global install
npm install -g inngest-cli

# Docker
docker pull inngest/inngest
```

If your npm configuration disables lifecycle scripts and the binary is missing, retry with `npx --ignore-scripts=false inngest-cli@latest dev`. Bun does not support lifecycle scripts by default, so prefer `npx` for the CLI even in Bun projects.

## `inngest dev` — Local Dev Server

Starts an in-memory local version of Inngest with a browser UI at `http://localhost:8288`.

```bash
# Auto-discover apps on common ports/endpoints
npx inngest-cli@latest dev

# Specify your app URL
npx inngest-cli@latest dev -u http://localhost:3000/api/inngest

# Custom port
npx inngest-cli@latest dev -p 9999

# Multiple apps
npx inngest-cli@latest dev \
  -u http://localhost:3000/api/inngest \
  -u http://localhost:4000/api/inngest

# Disable auto-discovery (use with -u)
npx inngest-cli@latest dev --no-discovery -u http://localhost:3000/api/inngest
```

### CLI Flags

| Flag | Short | Default | Description |
|---|---|---|---|
| `--sdk-url` | `-u` | `http://localhost:3000/api/inngest` | App serve endpoint URL(s) |
| `--port` | `-p` | `8288` | Dev Server port |
| `--host` | | | Dev Server host |
| `--no-discovery` | | `false` | Disable auto-discovery of apps |
| `--no-poll` | | `false` | Disable polling apps for changes |
| `--config` | | | Path to configuration file |
| `--connect-gateway-port` | | `8289` | Connect gateway endpoint port |
| `--persist` | | `false` | Persist data between restarts |
| `--poll-interval` | | `5` | Seconds between app polling checks |
| `--queue-workers` | | `100` | Number of executor workers |
| `--retry-interval` | | `0` | Linear retry interval in seconds |
| `--tick` | | `150` | Executor queue polling interval in milliseconds |

### Auto-Discovery

Without `--no-discovery`, the Dev Server scans common ports and endpoints automatically:

**Ports scanned:** Common development ports including 3000, 3030, and others

**Endpoints scanned:**
- `/api/inngest`
- `/x/inngest`
- `/.netlify/functions/inngest`
- `/.redwood/functions/inngest`

## Configuration File

Create an `inngest.json` (or `.yaml`, `.toml`) in your project root. The CLI walks up directories to find it.

```json
{
  "sdk-url": [
    "http://localhost:3000/api/inngest",
    "http://localhost:3030/api/inngest"
  ],
  "no-discovery": true
}
```

```yaml
# inngest.yaml
sdk-url:
  - "http://localhost:3000/api/inngest"
  - "http://localhost:3030/api/inngest"
no-discovery: true
```

## Environment Variables

| Variable | Description |
|---|---|
| `INNGEST_DEV` | `=1` enables Dev Mode (disables signature verification). `=0` forces Cloud mode. Accepts a URL (e.g., `http://localhost:8288`). **Defaults to Cloud mode if unset.** |
| `INNGEST_BASE_URL` | Host fo

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 1 — file references are metadata, not package contents.

inngest-cloud4.62 KB

View saved version →

---
name: inngest-cloud
description: Inspect and operate Inngest Cloud through its OAuth MCP connection. Use for deployed apps and functions, failed or slow runs, traces, events, environments, sessions, experiments, and Insights. Prefer this for Cloud operations when MCP tools are available; use CLI or REST skills for explicit terminal or HTTP tasks.
---

# Inngest Cloud

Use the connected Inngest Cloud MCP server at `https://api.inngest.com/mcp`.
Read the tools and input schemas exposed by the current connection before
constructing calls. Tool names below omit host-specific prefixes.

## Connection and target

- Use the host's OAuth sign-in or reconnect flow. Do not request tokens or API
  keys in chat. A plugin connection does not authenticate a separate CLI.
- Resolve the account with `fetch_account` when account context is missing.
  Use `list_envs` and the user's task to resolve the environment. Carry the
  selected `env` through environment-specific calls; do not infer production
  from an omitted value or switch environments after an access error.
- Use `get_apps` and `list_functions` to discover identifiers. Don't ask the
  user for an ID the tools can find. Ask when multiple accounts, environments,
  apps, or functions fit the request.
- A `401` needs reconnection; a scope or permission error needs the appropriate
  grant. Neither means that a resource is absent. Do not fall back to another
  credential to bypass the connection's access limits.
- The local Dev Server is a separate, opt-in connection named `inngest-dev`.
  Reuse an existing local connection under its configured name.
  Both servers can coexist. Use the server matching the requested target and
  never fall back from local to Cloud on a connection failure. For local setup,
  use `inngest-cli` when installed. Cloud MCP cannot see a local process.

## Investigate a run

1. If the user gives a run ID, use `get_run`. Otherwise find a bounded set with
   `list_runs` or `list_function_runs`, using the requested time range, status,
   app, and function. Follow pagination when needed and report the query window.
2. Use `get_run_trace` for the relevant run. Start with trace metadata and fetch
   input/output only when needed to explain a failure. Inspect nested spans.
3. Separate observed failures, waits, retries, and cancellations from hypotheses.
   Cite the run ID, failed step, and error that support the conclusion. An empty
   result is evidence only about the filters and accessible environment queried.
4. When code is available, connect the failed step to its implementation and
   propose or make the requested fix. In chat without repository access, give
   the diagnosis and concrete code guidance without claiming a patch was applied.

**Do:** inspect a failed run and trace before deciding whether a retry helps.
**Don't:** rerun, cancel, invoke, or send an event merely to diagnose a failure.

## Events and operations

For an explicitly requested event test, resolve the environment and inspect the
function's trigger first. Send the requested event with `send_event`, then use
`get_event_runs` and inspect the resulting runs. Sending an event or invoking a
function can execute real application side effects.

Before a write, resolve the exact target, payload, and requested effect. Honor
existing user authorization; ask only when the scope or target is unclear.
Use mutations such as `rerun`, `cancel_run`, `invoke_function`, `sync_app`, and
environment or webhook changes only when they are part of the user's request.
Do not retry a timed-out write blindly: check for its result first to avoid
sending duplicate events or starting duplicate runs.

## Insights, sessions, and experiments

Use `list_insights_tables` and the live schema before building an Insights
query. Bound time ranges and result counts, prefer aggregates, and inspect SQL
returned by `query_insights_prompt` before executing it with `query_insights`.
Use the session and experiment tools for their respec

Preview of the first 4,000 characters. Read full instructions →

inngest-durable-functions14.4 KB

View saved version →

---
name: inngest-durable-functions
description: 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.
---

# Inngest Durable Functions

Master Inngest's durable execution model for building fault-tolerant, long-running workflows. This skill covers the complete lifecycle from triggers to error handling.

> **These skills are focused on TypeScript.** For Python or Go, refer to the [Inngest documentation](https://www.inngest.com/llms.txt) for language-specific guidance. Core concepts apply across all languages.

## Core Concepts You Need to Know

### **Durable Execution Model**

- **Each step** should encapsulate side-effects and non-deterministic code
- **Memoization** prevents re-execution of completed steps
- **State persistence** survives infrastructure failures
- **Automatic retries** with configurable retry count

### **Step Execution Flow**

```typescript
// ❌ BAD: Non-deterministic logic outside steps
async ({ event, step }) => {
  const timestamp = Date.now(); // This runs multiple times!

  const result = await step.run("process-data", () => {
    return processData(event.data);
  });
};

// ✅ GOOD: All non-deterministic logic in steps
async ({ event, step }) => {
  const result = await step.run("process-with-timestamp", () => {
    const timestamp = Date.now(); // Only runs once
    return processData(event.data, timestamp);
  });
};
```

## Function Limits

**Every Inngest function has these hard limits:**

- **Maximum 1,000 steps** per function run
- **Maximum 4MB** returned data for each step
- **Maximum 32MB** combined function run state including, event data, step output, and function output
- Each step = separate HTTP request (~50-100ms overhead)

If you're hitting these limits, break your function into smaller functions connected via `step.invoke()` or `step.sendEvent()`.

## When to Use Steps

**Always wrap in `step.run()`:**

- API calls and network requests
- Database reads and writes
- File I/O operations
- Any non-deterministic operation
- Anything you want retried independently on failure

**Never wrap in `step.run()`:**

- Pure calculations and data transformations
- Simple validation logic
- Deterministic operations with no side effects
- Logging (use outside steps)

## Function Creation

### Basic Function Structure

```typescript
const processOrder = inngest.createFunction(
  {
    id: "process-order", // Unique, never change this
    triggers: [{ event: "order/created" }],
    retries: 4, // Default: 4 retries per step
    concurrency: 10 // Max concurrent executions
  },
  async ({ event, step }) => {
    // Your durable workflow
  }
);
```

### **Step IDs and Memoization**

```typescript
// Step IDs can be reused - Inngest handles counters automatically
const data = await step.run("fetch-data", () => fetchUserData());
const more = await step.run("fetch-data", () => fetchOrderData()); // Different execution

// Use descriptive IDs for clarity
await step.run("validate-payment", () => validatePayment(event.data.paymentId));
await step.run("charge-customer", () => chargeCustomer(event.data));
await step.run("send-confirmation", () => sendEmail(event.data.email));
```

## Triggers and Events

### **Event Triggers**

Triggers are defined in the `triggers` array in the first argument of `createFunction`:

```typescript
// Single event trigger
inngest.createFunction(
  { id: "my-fn", triggers: [{ event: "user/signup" }] },
  async ({ event }) => { /* ... */ }
);

// Event with conditional filter
inngest.createFunction(
  { id: "my-fn", triggers: [{ e

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 4 — file references are metadata, not package contents.

inngest-events11.8 KB

View saved version →

---
name: inngest-events
description: 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/function.failed.
---

# Inngest Events

Master Inngest event design and delivery patterns. Events are the foundation of Inngest - learn to design robust event schemas, implement idempotency, leverage fan-out patterns, and handle system events effectively.

> **These skills are focused on TypeScript.** For Python or Go, refer to the [Inngest documentation](https://www.inngest.com/llms.txt) for language-specific guidance. Core concepts apply across all languages.

## Event Payload Format

Every Inngest event is a JSON object with required and optional properties:

### Required Properties

```typescript
type Event = {
  name: string; // Event type (triggers functions)
  data: object; // Payload data (any nested JSON)
};
```

### Complete Schema

```typescript
type EventPayload = {
  name: string; // Required: event type
  data: Record<string, any>; // Required: event data
  id?: string; // Optional: deduplication ID
  ts?: number; // Optional: timestamp (Unix ms)
  v?: string; // Optional: schema version
};
```

### Basic Event Example

```typescript
await inngest.send({
  name: "billing/invoice.paid",
  data: {
    customerId: "cus_NffrFeUfNV2Hib",
    invoiceId: "in_1J5g2n2eZvKYlo2C0Z1Z2Z3Z",
    userId: "user_03028hf09j2d02",
    amount: 1000,
    metadata: {
      accountId: "acct_1J5g2n2eZvKYlo2C0Z1Z2Z3Z",
      accountName: "Acme.ai"
    }
  }
});
```

## Event Naming Conventions

**Use the Object-Action pattern:** `domain/noun.verb`

### Recommended Patterns

```typescript
// ✅ Good: Clear object-action pattern
"billing/invoice.paid";
"user/profile.updated";
"order/item.shipped";
"ai/summary.completed";

// ✅ Good: Domain prefixes for organization
"stripe/customer.created";
"intercom/conversation.assigned";
"slack/message.posted";

// ❌ Avoid: Unclear or inconsistent
"payment"; // What happened?
"user_update"; // Use dots, not underscores
"invoiceWasPaid"; // Too verbose
```

### Naming Guidelines

- **Past tense:** Events describe what happened (`created`, `updated`, `failed`)
- **Dot notation:** Use dots for hierarchy (`billing/invoice.paid`)
- **Prefixes:** Group related events (`api/user.created`, `webhook/stripe.received`)
- **Consistency:** Establish patterns and stick to them

## Event IDs and Idempotency

**When to use IDs:** Prevent duplicate processing when events might be sent multiple times.

### Basic Deduplication

```typescript
await inngest.send({
  id: "cart-checkout-completed-ed12c8bde", // Unique per event type
  name: "storefront/cart.checkout.completed",
  data: {
    cartId: "ed12c8bde",
    items: ["item1", "item2"]
  }
});
```

### ID Best Practices

```typescript
// ✅ Good: Specific to event type and instance
id: `invoice-paid-${invoiceId}`;
id: `user-signup-${userId}-${timestamp}`;
id: `order-shipped-${orderId}-${trackingNumber}`;

// ❌ Bad: Generic IDs shared across event types
id: invoiceId; // Could conflict with other events
id: "user-action"; // Too generic
id: customerId; // Same customer, different events
```

**Deduplication window:** 24 hours from first event reception

See **inngest-durable-functions** for idempotency configuration.

## The `ts` Parameter for Delayed Delivery

**When to use:** Schedule events for future processing or maintain event ordering.

### Future Scheduling

```typescript
const oneHourFromNow = Date.now() + 60 * 60 * 1000;

await inngest.send({
  name: "trial/reminder.send",
  ts: oneHourFromNow, // Deliver in 1 hour
  data: {
    userId: "user_123",
    trialExpiresAt: "2024-02-15T12:00:00Z"
  }
})

Preview of the first 4,000 characters. Read full instructions →

inngest-flow-control8.66 KB

View saved version →

---
name: inngest-flow-control
description: "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."
---

# Inngest Flow Control

Master Inngest flow control mechanisms to manage resources, prevent overloading systems, and ensure application reliability. This skill covers all flow control options with prescriptive guidance on when and how to use each.

> **These skills are focused on TypeScript.** For Python or Go, refer to the [Inngest documentation](https://www.inngest.com/llms.txt) for language-specific guidance. Core concepts apply across all languages.

## Quick Decision Guide

- **"Limit how many run at once"** → Concurrency
- **"Spread runs over time"** → Throttling
- **"Block after N runs in a period"** → Rate Limiting
- **"Wait for activity to stop, then run once"** → Debounce
- **"Only one run at a time for this key"** → Singleton
- **"Process events in groups"** → Batching
- **"Some runs are more important"** → Priority

## Concurrency

**When to use:** Limit the number of executing steps (not function runs) to manage computing resources and prevent system overwhelm.

**Key insight:** Concurrency limits active code execution, not function runs. A function waiting on `step.sleep()` or `step.waitForEvent()` doesn't count against the limit.

### Basic Concurrency

```typescript
inngest.createFunction(
  {
    id: "process-images",
    concurrency: 5,
    triggers: [{ event: "media/image.uploaded" }]
  },
  async ({ event, step }) => {
    // Only 5 steps can execute simultaneously
    await step.run("resize", () => resizeImage(event.data.imageUrl));
  }
);
```

### Concurrency with Keys (Multi-tenant)

Use `key` parameter to apply limit per unique value of the key.

```typescript
inngest.createFunction(
  {
    id: "user-sync",
    concurrency: [
      {
        key: "event.data.user_id",
        limit: 1
      }
    ],
    triggers: [{ event: "user/profile.updated" }]
  },
  async ({ event, step }) => {
    // Only 1 step per user can execute at once
    // Prevents race conditions in user-specific operations
  }
);
```

### Account-level Shared Limits

```typescript
inngest.createFunction(
  {
    id: "ai-summary",
    concurrency: [
      {
        scope: "account",
        key: `"openai"`,
        limit: 60
      }
    ],
    triggers: [{ event: "ai/summary.requested" }]
  },
  async ({ event, step }) => {
    // Share 60 concurrent OpenAI calls across all functions
  }
);
```

**When to use each:**

- Basic: Protect databases or limit general capacity
- Keyed: Multi-tenant fairness, prevent "noisy neighbor" issues
- Account-level: Share quotas across multiple functions (API limits)

## Throttling

**When to use:** Control the rate of function starts over time to work around API rate limits or smooth traffic spikes.

**Key difference from concurrency:** Throttling limits function run starts; concurrency limits step execution.

```typescript
inngest.createFunction(
  {
    id: "sync-crm-data",
    throttle: {
      limit: 10, // 10 function starts
      period: "60s", // per minute
      burst: 5, // plus 5 immediate bursts
      key: "event.data.customer_id" // per customer
    },
    triggers: [{ event: "crm/contact.updated" }]
  },
  async ({ event, step }) => {
    // Respects CRM API rate limits: 10 calls/min per customer
    await step.run("sync", () => crmApi.updateContact(event.data));
  }
);
```

**Configuration:**

- `limit`: Functions that can start per period
- `period`: Time window (1s to 7d)
- `burst`: Extra immediate starts allowed
- `key`: Apply limits per unique key value

## Ra

Preview of the first 4,000 characters. Read full instructions →

inngest-middleware9.97 KB

View saved version →

---
name: inngest-middleware
description: 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/middleware-encryption, @inngest/middleware-sentry, and custom middleware patterns.
---

# Inngest Middleware

Master Inngest middleware to handle cross-cutting concerns like logging, error tracking, dependency injection, and data transformation. Middleware runs at key points in the function lifecycle, enabling powerful patterns for observability and shared functionality.

> **These skills are focused on TypeScript.** For Python or Go, refer to the [Inngest documentation](https://www.inngest.com/llms.txt) for language-specific guidance. Core concepts apply across all languages.

> **Note:** The middleware system was significantly rewritten in v4. The lifecycle hooks documented here reflect the v4 API. If migrating from v3, consult the [migration guide](https://www.inngest.com/docs-markdown/reference/typescript/v4/migrations/v3-to-v4) for details on breaking changes.

> **⚠ For Realtime use the `inngest-realtime` skill, NOT this one.** Inngest v3 used `realtimeMiddleware()` from `@inngest/realtime` to inject a `publish` arg into function handlers. **v4 ships realtime natively** — `step.realtime.publish` is built-in, no middleware required. Do NOT install `@inngest/realtime` on a v4 project (it's a v3-era package and produces `TypeError: Cls is not a constructor` at runtime). See the `inngest-realtime` skill for the v4 pattern.

## What is Middleware?

Middleware allows code to run at various points in an Inngest client's lifecycle - during function execution, event sending, and more. Think of middleware as hooks into the Inngest execution pipeline.

**When to use middleware:**

- **Observability:** Add logging, tracing, or metrics
- **Dependency injection:** Share client instances across functions
- **Data transformation:** Encrypt/decrypt, validate, or enrich data
- **Error handling:** Custom error tracking and alerting
- **Authentication:** Validate user context or permissions

## Middleware Lifecycle

Middleware can be registered at **client-level** (affects all functions) or **function-level** (affects specific functions).

### Execution Order

```typescript
const inngest = new Inngest({
  id: "my-app",
  middleware: [
    loggingMiddleware, // Runs 1st
    errorMiddleware // Runs 2nd
  ]
});

inngest.createFunction(
  {
    id: "example",
    middleware: [
      authMiddleware, // Runs 3rd
      metricsMiddleware // Runs 4th
    ],
    triggers: [{ event: "test" }]
  },
  async () => {
    /* function code */
  }
);
```

**Order matters:** Client middleware runs first, then function middleware, in the order specified.

## Creating Custom Middleware

### Basic Middleware Structure

```typescript
import { InngestMiddleware } from "inngest";

const loggingMiddleware = new InngestMiddleware({
  name: "Logging Middleware",
  init() {
    // Setup phase - runs when client initializes
    const logger = setupLogger();

    return {
      // Function execution lifecycle
      // Note: `fn` is loosely typed in middleware generics; fn.id works at runtime
      onFunctionRun({ ctx, fn }) {
        return {
          beforeExecution() {
            logger.info("Function starting", {
              functionId: fn.id,
              eventName: ctx.event.name,
              runId: ctx.runId
            });
          },

          afterExecution() {
            logger.info("Function completed", {
              functionId: fn.id,
              runId: ctx.runId
            });
          },

          transformOutput({ result }) {
            // Log function output
    

Preview of the first 4,000 characters. Read full instructions →

Referenced files: 2 — file references are metadata, not package contents.

inngest-realtime18.1 KB

View saved version →

---
name: inngest-realtime
description: "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/Next.js client components."
---

# Inngest Realtime

Stream updates from durable Inngest functions to live UIs. Use channels and topics to broadcast progress, render workflow execution as it happens, or build bi-directional human-in-the-loop flows.

> **These skills are focused on TypeScript.** For Python or Go, refer to the [Inngest documentation](https://www.inngest.com/llms.txt) for language-specific guidance. Core concepts apply across all languages.

> **⚠ CRITICAL: v3 vs v4 package selection**
>
> Realtime in Inngest v4 lives at the SDK subpath `inngest/realtime`. The standalone `@inngest/realtime` npm package is a **v3-era package** and is **NOT compatible with `inngest@4.x`**. If your project is on v4 (the npm default), do not install `@inngest/realtime`. Use the imports below.
>
> Symptoms of using the wrong package on v4: `TypeError: Cls is not a constructor` on every `PUT /api/inngest`, 401 on subscription tokens, type incompatibility on `new Inngest({ middleware: [...] })`. Verify your `package.json` shows `"inngest": "^4.x"` before reading further.

## Prerequisites

- Inngest v4 SDK installed (`npm install inngest`) — see the `inngest-setup` skill
- `INNGEST_DEV=1` set in `.env.local` for local development (without it, the SDK demands cloud signing keys and 401s on token requests)
- Local Inngest dev server running (`npx inngest-cli@latest dev`)
- Optional: `zod` for schema validation on topics

## When to use Realtime

| Problem shape | Pattern |
|---|---|
| Order status page animates as durable workflow steps complete | Per-run channel, publish per step, client subscribes |
| AI agent streams tokens to a chat UI | Per-conversation channel, publish chunks, stream to browser |
| Log tail for a long-running job | Single channel, log topic, append to UI |
| Human-in-the-loop approval | Channel + waitForEvent, publish prompt, wait for response |
| Admin dashboard with live order list | Global admin channel, fan-out from each function |

## Architecture

Three pieces:

1. **Channel definition** — a typed contract for what gets published. Lives in shared module so both server and client can reference the same channel name.
2. **Publishing** — call `step.realtime.publish` between steps to wrap a durable publish, or `inngest.realtime.publish` inside `step.run` because you're already inside a memoized step. See "Which publish method to use" below.
3. **Subscribing** — server action mints a subscription token; React client uses the `useRealtime` hook (or the lower-level `subscribe()` API for non-React consumers).

## Step 1: Define a channel

Channels are pure data — no class hierarchy, no zod runtime required (but recommended for type safety). Define them once and import where needed.

```typescript
// src/inngest/channels.ts
import { channel } from 'inngest/realtime';
import { z } from 'zod';

// Per-run channel: each fulfill-order run publishes step updates to its own channel.
export const orderChannel = channel({
  name: (orderId: string) => `order:${orderId}`,
  topics: {
    step: {
      schema: z.object({
        name: z.string(),
        status: z.enum(['running', 'complete', 'failed']),
        output: z.record(z.string(), z.unknown()).optional(),
        ts: z.number(),
      }),
    },
  },
});

// Global admin channel: fan-out for cross-cutting visibility.
export const adminChannel = channel({
  name: 'admin',
  topics: {
    order: {
      schema: z.object({
        orderId: z.string(),
        step:

Preview of the first 4,000 characters. Read full instructions →

inngest-setup11.8 KB

View saved version →

---
name: inngest-setup
description: 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.
---

# Inngest Setup

This skill sets up Inngest in a TypeScript project from scratch, covering installation, client configuration, connection modes, and local development.

> **These skills are focused on TypeScript.** For Python or Go, refer to the [Inngest documentation](https://www.inngest.com/llms.txt) for language-specific guidance. Core concepts apply across all languages.

## Prerequisites

- Node.js 18+ (Node.js 22.4+ recommended for WebSocket support)
- TypeScript project
- Package manager (npm, yarn, pnpm, or bun)

## Step 1: Install the Inngest SDK

Install the `inngest` npm package in your project:

```bash
npm install inngest
# or
yarn add inngest
# or
pnpm add inngest
# or
bun add inngest
```

## Step 2: Create an Inngest Client

Create a shared client file that you'll import throughout your codebase:

```typescript
// src/inngest/client.ts
import { Inngest } from "inngest";

export const inngest = new Inngest({
  id: "my-app" // Unique identifier for your application (hyphenated slug)
});
// IMPORTANT: v4 defaults to Cloud mode. For local dev, set INNGEST_DEV=1 env var.
// Without it, your serve endpoint will return 500 ("In cloud mode but no signing key").
// In production, set INNGEST_SIGNING_KEY (required for Cloud mode).
```

### Key Configuration Options

- **`id`** (required): Unique identifier for your app. Use a hyphenated slug like `"my-app"` or `"user-service"`
- **`eventKey`**: Event key for sending events (prefer `INNGEST_EVENT_KEY` env var)
- **`env`**: Environment name for Branch Environments
- **`isDev`**: Force Dev mode (`true`) or Cloud mode (`false`). **v4 defaults to Cloud mode**, so set `INNGEST_DEV=1` env var for local development. **Never hardcode `isDev: true` in source code** — it will silently break in production. Always use the env var.
- **`signingKey`**: Signing key for production (prefer `INNGEST_SIGNING_KEY` env var). Moved from `serve()` to client in v4
- **`signingKeyFallback`**: Fallback signing key for key rotation (prefer `INNGEST_SIGNING_KEY_FALLBACK` env var)
- **`baseUrl`**: Custom Inngest API base URL (prefer `INNGEST_BASE_URL` env var)
- **`logger`**: Custom logger instance (e.g. winston, pino) — enables `logger` in function context
- **`middleware`**: Array of middleware (see **inngest-middleware** skill)

### Typed Events with eventType()

```typescript
import { Inngest, eventType } from "inngest";
import { z } from "zod";

const signupCompleted = eventType("user/signup.completed", {
  schema: z.object({
    userId: z.string(),
    email: z.string(),
    plan: z.enum(["free", "pro"])
  })
});

const orderPlaced = eventType("order/placed", {
  schema: z.object({
    orderId: z.string(),
    amount: z.number()
  })
});

export const inngest = new Inngest({ id: "my-app" });

// Use event types as triggers for full type safety:
inngest.createFunction(
  { id: "handle-signup", triggers: [signupCompleted] },
  async ({ event }) => {
    event.data.userId; /* typed as string */
  }
);

// Use event types when sending events:
await inngest.send(
  signupCompleted.create({
    userId: "user_123",
    email: "user@example.com",
    plan: "pro"
  })
);
```

### Environment Variables Setup

Set these environment variables in your `.env` file or deployment environment:

```env
# Required for production
INNGEST_EVENT_KEY=your-event-key-here
INNGEST_SIGNING_KEY=your-signing-key-here

# Force dev mode during local development
INNGEST_DEV=1

# Optional - custom dev server URL (default: http://localhost:8288)
INNGEST_BASE_URL=http://localhost:8288
```

**⚠️ Common Gotcha**: Ne

Preview of the first 4,000 characters. Read full instructions →

inngest-steps11.2 KB

View saved version →

---
name: inngest-steps
description: "Use when implementing delays that must survive process restarts (e.g., 24-hour cart abandonment, scheduled follow-ups), waiting for human approval or external events with timeouts (review gates, webhook callbacks, async API completion), polling external services without losing state on crashes, calling other functions and awaiting their results, memoizing expensive operations so they don't re-run on retry, or running async work in parallel inside a workflow. Covers Inngest step methods: step.run, step.sleep, step.waitForEvent, step.waitForSignal, step.sendEvent, step.invoke, step.ai, plus patterns for loops and parallel execution."
---

# Inngest Steps

Build robust, durable workflows with Inngest's step methods. Each step is a separate HTTP request that can be independently retried and monitored.

> **These skills are focused on TypeScript.** For Python or Go, refer to the [Inngest documentation](https://www.inngest.com/llms.txt) for language-specific guidance. Core concepts apply across all languages.

## Core Concept

**🔄 Critical: Each step re-runs your function from the beginning.** Put ALL non-deterministic code (API calls, DB queries, randomness) inside steps, never outside.

**📊 Step Limits:** Every function has a maximum of 1,000 steps and 4MB total step data.

```typescript
// ❌ WRONG - will run 4 times
export default inngest.createFunction(
  { id: "bad-example", triggers: [{ event: "test" }] },
  async ({ step }) => {
    console.log("This logs 4 times!"); // Outside step = bad
    await step.run("a", () => console.log("a"));
    await step.run("b", () => console.log("b"));
    await step.run("c", () => console.log("c"));
  }
);

// ✅ CORRECT - logs once each
export default inngest.createFunction(
  { id: "good-example", triggers: [{ event: "test" }] },
  async ({ step }) => {
    await step.run("log-hello", () => console.log("hello"));
    await step.run("a", () => console.log("a"));
    await step.run("b", () => console.log("b"));
    await step.run("c", () => console.log("c"));
  }
);
```

## step.run()

Execute retriable code as a step. **Each step ID can be reused** - Inngest automatically handles counters.

```typescript
// Basic usage
const result = await step.run("fetch-user", async () => {
  const user = await db.user.findById(userId);
  return user; // Always return useful data
});

// Synchronous code works too
const transformed = await step.run("transform-data", () => {
  return processData(result);
});

// Side effects (no return needed)
await step.run("send-notification", async () => {
  await sendEmail(user.email, "Welcome!");
});
```

**✅ DO:**

- Put ALL non-deterministic logic inside steps
- Return useful data for subsequent steps
- Reuse step IDs in loops (counters handled automatically)

**❌ DON'T:**

- Put deterministic logic in steps unnecessarily
- Forget that each step = separate HTTP request

## step.sleep()

Pause execution without using compute time.

```typescript
// Duration strings
await step.sleep("wait-24h", "24h");
await step.sleep("short-delay", "30s");
await step.sleep("weekly-pause", "7d");

// Use in workflows
await step.run("send-welcome", () => sendEmail(email));
await step.sleep("wait-for-engagement", "3d");
await step.run("send-followup", () => sendFollowupEmail(email));
```

## step.sleepUntil()

Sleep until a specific datetime.

```typescript
const reminderDate = new Date("2024-12-25T09:00:00Z");
await step.sleepUntil("wait-for-christmas", reminderDate);

// From event data
const scheduledTime = new Date(event.data.remind_at);
await step.sleepUntil("wait-for-scheduled-time", scheduledTime);
```

## step.waitForEvent()

**🚨 CRITICAL: waitForEvent ONLY catches events sent AFTER this step executes.**

- ❌ Event sent before waitForEvent runs → will NOT be caught
- ✅ Event sent after waitForEvent runs → will be caught
- Always check for `null` return (means timeout, event never arrived)

```typescript
// Basic event waiting with timeout
con

Preview of the first 4,000 characters. Read full instructions →

inngest-v3-v4-migration9.78 KB

View saved version →

---
name: inngest-v3-v4-migration
description: Use when upgrading an existing TypeScript codebase from Inngest SDK v3 to v4, or when fixing mixed v3/v4 API usage. Covers detecting current SDK usage, moving triggers into createFunction options, replacing EventSchemas with eventType/staticSchema, moving serve options to the client, updating realtime imports, rewriting step.invoke string IDs, checkpointing/serverless runtime settings, Connect option changes, and verification.
---

# Inngest v3 to v4 Migration

Use this skill when the user asks to upgrade Inngest, fix v3/v4 errors, migrate
realtime, or clean up a codebase that has mixed SDK patterns.

Primary reference:
https://www.inngest.com/docs/reference/typescript/v4/migrations/v3-to-v4

This skill is agent-first: detect actual usage first, make mechanical API
changes in a controlled order, then typecheck and run focused tests.

## When to Trigger

Use this skill for requests like:

- "Upgrade Inngest from v3 to v4"
- "Fix our Inngest v4 migration"
- "We're getting signing key required / cloud mode errors after upgrading"
- "`step.invoke` with a string function ID stopped working"
- "`@inngest/realtime` broke after installing `inngest@4`"
- "Move from EventSchemas to eventType"
- "Make this existing Inngest repo v4-compatible"

If the user asks for a broad codebase reliability audit first, use
`inngest-brownfield-audit` to choose scope, then return here for the v4 changes.

## Migration Scan

Start by locating all Inngest surfaces:

```bash
rg -n '"inngest"|"@inngest/realtime"|"@inngest/agent-kit"' package.json **/package.json
rg -n 'new Inngest|EventSchemas|eventType|staticSchema|createFunction\\(|serve\\(|connect\\(|step\\.invoke|referenceFunction|@inngest/realtime|realtimeMiddleware|useInngestSubscription|serveHost|rewriteGatewayEndpoint|logLevel|streaming:|signingKey|signingKeyFallback|baseUrl|INNGEST_DEV|INNGEST_SIGNING_KEY' .
```

Then classify the repo:

- **No Inngest yet:** use `inngest-setup`, not this migration skill.
- **v3 only:** migrate the SDK and all breaking changes together.
- **mixed v3/v4:** prioritize removing broken v3 APIs from v4 code.
- **v4 mostly done:** focus on missed runtime gotchas like local dev mode,
  serverless `maxRuntime`, realtime package imports, and string `step.invoke`.

Before editing, record:

```text
Inngest migration scan:
- Current package versions:
- Client files:
- Serve/connect entrypoints:
- Functions using old trigger syntax:
- EventSchemas usage:
- Realtime v3 package usage:
- step.invoke string IDs:
- Serverless runtime constraints:
- Tests/checks available:
```

## Upgrade Order

1. Update package versions.
2. Fix client construction and local/prod mode.
3. Move serve options to the client.
4. Move triggers into `createFunction` options.
5. Replace `EventSchemas` with `eventType()` / `staticSchema()`.
6. Rewrite `step.invoke()` string IDs.
7. Migrate realtime from `@inngest/realtime` to v4 native APIs.
8. Update middleware and logging.
9. Configure checkpointing/serverless runtime.
10. Typecheck, run tests, and optionally sync with the dev server.

## Package and Environment

Install the latest v4 SDK:

```bash
npm install inngest@latest
# or pnpm add inngest@latest
# or yarn add inngest@latest
```

If the repo uses v3 realtime, remove `@inngest/realtime`; v4 realtime lives in
the `inngest` package and subpaths such as `inngest/realtime`, `inngest/react`,
and native `step.realtime` / `inngest.realtime`.

v4 defaults to Cloud mode. For local development, use an env var:

```bash
INNGEST_DEV=1 npm run dev
```

Do not hardcode `isDev: true` in source unless the repo's existing environment
pattern clearly scopes it to local-only code. Production should use
`INNGEST_SIGNING_KEY`.

## Client and Serve Options

In v4, options such as `signingKey`, `signingKeyFallback`, and `baseUrl` belong
on `new Inngest(...)`, not on `serve(...)`.

```typescript
// Old v3
app.use(
  "/api/inngest",
  serve({
    client: inngest,
    functions,

Preview of the first 4,000 characters. Read full instructions →

Package details

Publisher declarations from the archived package. These are separate from our research and the live service's terms.

Package license
MIT
Package author
Inngest, Inc.
Keywords
See keywords

Declared capabilities

  • Code
  • MCP

Package observed Nov 10, 2026.

Technical details
First seen
Oct 24, 2026 · 12:40 UTC
Last seen
Nov 11, 2026 · 00:00 UTC
Latest observed change
Nov 5, 2026 · 01:00 UTC
Collection status
Collected

plugin_asdk_app_6abe99ad4764819183b795f0d74e5216

Download plugin data (JSON)

Plugin details: freshly prepared. Prepared . Refreshed when plugin data changes or after 6 hours. Your account and Follow status are live.