Install any skill in seconds. Free to start, no credit card required.
Get Started Free →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, and crash-safe execution. 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.
.claude/skills/asymmetric-al-inngest-agents/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 68% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 64% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 38% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 51% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 51% | 0% |
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:
createAgent: https://agentkit.inngest.com/reference/create-agentstep.ai: https://www.inngest.com/docs/features/inngest-functions/steps-workflows/step-ai-orchestrationWhen starting a durable support or tool-calling agent from scratch, use the official inngest/inngest-codex-plugin companion example at plugins/inngest/examples/durable-agent as the upstream reference. This repo does not vendor Codex plugin examples; copy only the patterns needed for a separate product integration change.
Good fit:
failures.
or user input.
Not usually worth it:
progress.
Use this shape unless the repo already has a stronger established pattern:
needed, emits an event with a stable id, and returns quickly.
step.run.factories.
step.ai; wrap non-model tool sideeffects in step.run.
step.waitForEvent or step.waitForSignal for human approval andexternal callbacks.
Prefer a small, typed function first; add networks and extra tools after the single-agent path is proven.
typescriptimport { 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 }], }, async ({ event, step }) => { const ticket = await step.run("load-ticket", () => { return getTicket(event.data.ticketId); }); const writer = createAgent({ name: "support-summary-writer", system: "Write a concise support-ticket summary with next actions.", model: openai({ model: "gpt-4o" }), }); const { output } = await writer.run(JSON.stringify(ticket)); await step.run("save-summary", () => { return saveTicketSummary(event.data.ticketId, output); }); return { ticketId: event.data.ticketId }; }, );
Tools can be defined with AgentKit, but agent-safe tools should still follow durability rules:
step.runboundaries, or implemented as tool handlers that use the provided step.
Tool side-effect checklist:
text- What external state can this tool change? - What idempotency key prevents duplicate writes? - What should happen if the model calls the same tool twice? - Is the output safe to store in function run state? - Does the tool need provider-specific concurrency or throttle limits?
Use a durable wait instead of polling a database or keeping state in memory.
typescriptconst approval = await step.waitForEvent("wait-for-approval", { event: "support/reply.approved", timeout: "3d", match: "data.ticketId", }); if (!approval) { await step.run("mark-review-timeout", () => { return markTicketNeedsManualReview(event.data.ticketId); }); return { status: "timed_out" }; } await step.run("send-reply", () => { return sendSupportReply({ ticketId: event.data.ticketId, approvalId: approval.data.approvalId, }); });
For v4 native realtime:
step.realtime.publish between steps.inngest.realtime.publish inside an existing step.run.@inngest/realtime package for v4 projects.durable function.
For AgentKit-specific UI hooks, check the installed @inngest/agent-kit version and current docs before wiring useAgent or useChat.
Agent workloads often need provider and tenant limits:
expensive runs.
not re-charge earlier model calls.
Example:
typescript{ id: "support-agent-run", triggers: [{ event: "support/agent.requested" }], throttle: { limit: 120, period: "1m", key: `"openai"` }, concurrency: [ { key: "event.data.accountId", limit: 3 } ] }
When migrating an existing agent:
approval polling, and external side effects.
step.ai.step.run or durable tool handlers.step.waitForEvent orstep.waitForSignal.
Use inngest-brownfield-audit first when the repo has multiple possible workflows and the user has not picked one.
try/catch around all model and tool calls.setTimeout, cron polling, or Redis TTL as the human-review mechanism.continues elsewhere.
These upstream Inngest instructions are vendored for agent tooling and integration work in this monorepo.
Use this skill when inngest-agents matches the current Inngest task. If the right skill is unclear, start with docs/ai/skills/inngest/SKILL.md.
integration.
inngest-brownfield-audit before changing existing app workflows orfragile background work.
AGENTS.md, reporulebooks, framework docs, and runtime evidence.
INNGEST_* envrequirements out of agent-tooling-only changes.
or dependencies.
workflow behavior.
port.
docs/ai/skills/inngest/references/upstream.md.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-02 | fail→fail | 18,015 | 12,787 | -29% | 1 | 1 | 0% | 3,251 | 4,709 | +45% | 0 | 0 | — |
case-01 | fail→pass | 13,231 | 8,928 | -33% | 1 | 1 | 0% | 2,496 | 4,196 | +68% | 0 | 0 | — |
case-03 | pass→pass | 10,600 | 5,063 | -52% | 1 | 1 | 0% | 1,692 | 3,128 | +85% | 0 | 0 | — |
case-04 | pass→pass | 13,656 | 7,970 | -42% | 1 | 1 | 0% | 2,247 | 3,709 | +65% | 0 | 0 | — |
case-05 | pass→pass | 11,236 | 5,121 | -54% | 1 | 1 | 0% | 1,805 | 3,290 | +82% | 0 | 0 | — |
case-06 | pass→pass | 10,063 | 8,387 | -17% | 1 | 1 | 0% | 1,912 | 3,948 | +106% | 0 | 0 | — |
case-07 | fail→pass | 14,863 | 9,801 | -34% | 1 | 1 | 0% | 2,672 | 4,375 | +64% | 0 | 0 | — |
case-08 | pass→pass | 12,607 | 9,155 | -27% | 1 | 1 | 0% | 2,108 | 3,893 | +85% | 0 | 0 | — |
case-09 | pass→pass | 13,627 | 9,452 | -31% | 1 | 1 | 0% | 2,282 | 3,930 | +72% | 0 | 0 | — |
case-10 | pass→pass | 11,276 | 7,110 | -37% | 1 | 1 | 0% | 1,756 | 3,490 | +99% | 0 | 0 | — |
case-11 | fail→pass | 17,028 | 9,217 | -46% | 1 | 1 | 0% | 2,887 | 3,973 | +38% | 0 | 0 | — |
case-12 | fail→pass | 11,611 | 4,079 | -65% | 1 | 1 | 0% | 2,063 | 3,106 | +51% | 0 | 0 | — |
case-13 | pass→pass | 16,145 | 10,442 | -35% | 1 | 1 | 0% | 2,758 | 4,119 | +49% | 0 | 0 | — |
case-14 | fail→pass | 14,350 | 5,945 | -59% | 1 | 1 | 0% | 2,250 | 3,404 | +51% | 0 | 0 | — |
case-15 | fail→pass | 13,531 | 8,123 | -40% | 1 | 1 | 0% | 2,148 | 3,699 | +72% | 0 | 0 | — |
case-16 | fail→pass | 14,961 | 5,106 | -66% | 1 | 1 | 0% | 2,209 | 3,144 | +42% | 0 | 0 | — |
case-17 | pass→pass | 14,033 | 7,837 | -44% | 1 | 1 | 0% | 2,455 | 3,746 | +53% | 0 | 0 | — |
case-18 | pass→pass | 10,521 | 6,192 | -41% | 1 | 1 | 0% | 1,770 | 3,391 | +92% | 0 | 0 | — |
case-19 | pass→pass | 7,080 | 3,321 | -53% | 1 | 1 | 0% | 1,221 | 2,822 | +131% | 0 | 0 | — |
case-20 | pass→pass | 11,419 | 7,621 | -33% | 1 | 1 | 0% | 1,776 | 3,624 | +104% | 0 | 0 | — |
case-21 | pass→pass | 16,909 | 11,013 | -35% | 1 | 1 | 0% | 2,864 | 4,328 | +51% | 0 | 0 | — |
case-22 | pass→pass | 8,331 | 5,782 | -31% | 1 | 1 | 0% | 1,519 | 3,458 | +128% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +32 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.