Build With Simplepdf
SimplePDF/simplepdf-embed
Integrate SimplePDF into a web application for PDF viewing, editing, filling, signing, programmatic control, AI-agent interaction, human-in-the-loop form prefilling, submissions, webhooks, or…
A skill your agent uses 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…
$ npx skills add Asymmetric-al/core --skill inngest-steps -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install Asymmetric-al/core inngest-steps --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/Asymmetric-al/core.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/inngest-steps .claude/skills/inngest-steps && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "inngest-steps" agent skill from https://github.com/Asymmetric-al/core/tree/develop/.agents/skills/inngest-steps into .claude/skills/inngest-steps/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "inngest-steps", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/Asymmetric-al/core/tree/develop/.agents/skills/inngest-stepsType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add Asymmetric-al/core --skill inngest-steps -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install Asymmetric-al/core inngest-steps --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Asymmetric-al/core.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/inngest-steps .agents/skills/inngest-steps && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "inngest-steps" agent skill from https://github.com/Asymmetric-al/core/tree/develop/.agents/skills/inngest-steps into .agents/skills/inngest-steps/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "inngest-steps", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Asymmetric-al/core --skill inngest-steps -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install Asymmetric-al/core inngest-steps --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Asymmetric-al/core.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/inngest-steps .cursor/skills/inngest-steps && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "inngest-steps" agent skill from https://github.com/Asymmetric-al/core/tree/develop/.agents/skills/inngest-steps into .cursor/skills/inngest-steps/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "inngest-steps", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/Asymmetric-al/core.git --path .agents/skills/inngest-steps--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add Asymmetric-al/core --skill inngest-steps -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install Asymmetric-al/core inngest-steps --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Asymmetric-al/core.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/inngest-steps .gemini/skills/inngest-steps && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "inngest-steps" agent skill from https://github.com/Asymmetric-al/core/tree/develop/.agents/skills/inngest-steps into .gemini/skills/inngest-steps/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "inngest-steps", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install Asymmetric-al/core inngest-stepsInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add Asymmetric-al/core --skill inngest-steps -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/Asymmetric-al/core.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/inngest-steps .github/skills/inngest-steps && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "inngest-steps" agent skill from https://github.com/Asymmetric-al/core/tree/develop/.agents/skills/inngest-steps into .github/skills/inngest-steps/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "inngest-steps", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Asymmetric-al/core --skill inngest-steps -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install Asymmetric-al/core inngest-steps --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Asymmetric-al/core.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/inngest-steps .opencode/skills/inngest-steps && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "inngest-steps" agent skill from https://github.com/Asymmetric-al/core/tree/develop/.agents/skills/inngest-steps into .opencode/skills/inngest-steps/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "inngest-steps", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
inngest-stepsA skill your agent uses 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…
Inngest Steps is an agent skill from Asymmetric-al/core. 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…
Its SKILL.md is about 3.2k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Backend & APIs, covering Human-in-the-loop approvals and Webhooks. The repository describes itself as: A high-performance, enterprise-grade Next.js 16 application for mission-focused non-profit organizations. Built for high impact teams. The licence is AGPL-3.0.
4 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit c30c8ff. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are typescript).
From the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
inngest.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Inngest Steps loads about 3.2k tokens when it runs. Until then it costs about 163 tokens; SKILL.md has 702 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from Asymmetric-al/core at commit c30c8ff, republished under its AGPL-3.0 licence (© Asymmetric-al). 702 words, ~3,177 tokens.
.claude/skills/inngest-steps/SKILL.md (or your agent's skills folder).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 for language-specific guidance. Core concepts apply across all languages.
🔄 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.
// ❌ 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"));
},
);Execute retriable code as a step. Each step ID can be reused - Inngest automatically handles counters.
// 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:
❌ DON'T:
Pause execution without using compute time.
// 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));Sleep until a specific datetime.
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);🚨 CRITICAL: waitForEvent ONLY catches events sent AFTER this step executes.
null return (means timeout, event never arrived)// Basic event waiting with timeout
const approval = await step.waitForEvent("wait-for-approval", {
event: "app/invoice.approved",
timeout: "7d",
match: "data.invoiceId", // Simple matching
});
// Expression-based matching (CEL syntax)
const subscription = await step.waitForEvent("wait-for-subscription", {
event: "app/subscription.created",
timeout: "30d",
if: "event.data.userId == async.data.userId && async.data.plan == 'pro'",
});
// Handle timeout
if (!approval) {
await step.run("handle-timeout", () => {
// Approval never came
return notifyAccountingTeam();
});
}✅ DO:
❌ DON'T:
In expressions, event = the original triggering event, async = the new event being matched. See Expression Syntax Reference for full syntax, operators, and patterns.
Wait for unique signals (not events). Better for 1:1 matching.
const taskId = "task-" + crypto.randomUUID();
const signal = await step.waitForSignal("wait-for-task-completion", {
signal: taskId,
timeout: "1h",
onConflict: "replace", // Required: "replace" overwrites pending signal, "fail" throws an error
});
// Send signal elsewhere via Inngest API or SDK
// POST /v1/events with signal matching taskIdWhen to use:
Fan out to other functions without waiting for results.
// Trigger other functions
await step.sendEvent("notify-systems", {
name: "user/profile.updated",
data: { userId: user.id, changes: profileChanges },
});
// Multiple events at once
await step.sendEvent("batch-notifications", [
{ name: "billing/invoice.created", data: { invoiceId } },
{ name: "email/invoice.send", data: { email: user.email, invoiceId } },
]);Use when: You want to trigger other functions but don't need their results in the current function.
Call other functions and handle their results. Perfect for composition.
const computeSquare = inngest.createFunction(
{ id: "compute-square", triggers: [{ event: "calculate/square" }] },
async ({ event }) => {
return { result: event.data.number * event.data.number };
},
);
// Invoke and use result
const square = await step.invoke("get-square", {
function: computeSquare,
data: { number: 4 },
});
console.log(square.result); // 16, fully typed!
// For cross-app invocation (when you can't import the function directly):
import { referenceFunction } from "inngest";
const externalFn = referenceFunction({
appId: "other-app",
functionId: "other-fn",
});
const result = await step.invoke("call-external", {
function: externalFn,
data: { key: "value" },
});Warning: v4 Breaking Change: String function IDs (e.g., function: "my-app-other-fn") are no longer supported in step.invoke(). Use an imported function reference or referenceFunction() for cross-app calls.
Great for:
Reuse step IDs - Inngest handles counters automatically.
const allProducts = [];
let cursor = null;
let hasMore = true;
while (hasMore) {
// Same ID "fetch-page" reused - counters handled automatically
const page = await step.run("fetch-page", async () => {
return shopify.products.list({ cursor, limit: 50 });
});
allProducts.push(...page.products);
if (page.products.length < 50) {
hasMore = false;
} else {
cursor = page.products[49].id;
}
}
await step.run("process-products", () => {
return processAllProducts(allProducts);
});Use Promise.all for parallel steps. In v4, parallel step execution is optimized by default
// Create steps without awaiting
const sendEmail = step.run("send-email", async () => {
return await sendWelcomeEmail(user.email);
});
const updateCRM = step.run("update-crm", async () => {
return await crmService.addUser(user);
});
const createSubscription = step.run("create-subscription", async () => {
return await subscriptionService.create(user.id);
});
// Run all in parallel
const [emailId, crmRecord, subscription] = await Promise.all([
sendEmail,
updateCRM,
createSubscription,
]);
// Parallel steps are optimized by default in v4
export default inngest.createFunction(
{
id: "parallel-heavy-function",
triggers: [{ event: "process/batch" }],
},
async ({ event, step }) => {
const results = await Promise.all(
event.data.items.map((item, i) =>
step.run(`process-item-${i}`, () => processItem(item)),
),
);
},
);
// ⚠️ Promise.race() behavior with v4's optimized parallelism:
// All promises settle before race resolves. Use group.parallel() for true race:
const winner = await group.parallel(async () => {
return Promise.race([
step.run("fast-service", () => callFastService()),
step.run("slow-service", () => callSlowService()),
]);
});
// To disable optimized parallelism if needed:
// At the client level: new Inngest({ id: "app", optimizeParallelism: false })
// At the function level: { id: "fn", optimizeParallelism: false, triggers: [...] }See inngest-flow-control for concurrency and throttling options.
Perfect for batch processing with parallel steps.
export default inngest.createFunction(
{ id: "process-large-dataset", triggers: [{ event: "data/process.large" }] },
async ({ event, step }) => {
const chunks = chunkArray(event.data.items, 10);
// Process chunks in parallel
const results = await Promise.all(
chunks.map((chunk, index) =>
step.run(`process-chunk-${index}`, () => processChunk(chunk)),
),
);
// Combine results
await step.run("combine-results", () => {
return aggregateResults(results);
});
},
);🔄 Function Re-execution: Code outside steps runs on every step execution
⏰ Event Timing: waitForEvent only catches events sent AFTER the step runs
🔢 Step Limits: Max 1,000 steps per function, 4MB per step output, 32MB per function run in total
📨 HTTP Requests: Checkpointing is enabled by default in v4, reducing HTTP overhead. For serverless platforms, configure maxRuntime on the client
🔁 Step IDs: Can be reused in loops - Inngest handles counters
⚡ Parallelism: Use Promise.all for parallel steps (optimized by default in v4). Note that Promise.race() waits for all promises to settle — use group.parallel() for true race semantics
Remember: Steps make your functions durable, observable, and debuggable. Embrace them!
These upstream Inngest instructions are vendored for agent tooling and integration work in this monorepo.
Use this skill when inngest-steps matches the current Inngest task. If the
right skill is unclear, start with docs/ai/skills/inngest/SKILL.md.
inngest-brownfield-audit before changing existing app workflows or
fragile background work.AGENTS.md, repo
rulebooks, framework docs, and runtime evidence.INNGEST_* env
requirements out of agent-tooling-only changes.docs/ai/skills/inngest/references/upstream.md.© Asymmetric-al, AGPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .agents/skills/inngest-steps of Asymmetric-al/core.
Open the folder on GitHubat commit c30c8ff
Inngest Steps next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Inngest Steps this skillAsymmetric-al/core | 381 | — | ~3.2k | Automated safety check: Pass | AGPL-3.0 | |
| Build With SimplepdfSimplePDF/simplepdf-embed | 407 | — | ~7k | Automated safety check: Pass | MIT | |
| Hitl ProtocolLeoYeAI/openclaw-master-skills | 2.2k | — | ~5.3k | Automated safety check: Pass | Apache-2.0 | |
| Zalo AgentPhucMPham/zalo-agent-cli | 166 | — | ~2.3k | Automated safety check: Pass | MIT | |
| AWS Lambda Durable Functionsawslabs/agent-plugins | 916 | — | ~2.3k | Automated safety check: Pass | Apache-2.0 | |
| GitLab MCP Skillzereight/gitlab-mcp | 2k | — | ~2.2k | Automated safety check: Pass | MIT |
SimplePDF/simplepdf-embed
Integrate SimplePDF into a web application for PDF viewing, editing, filling, signing, programmatic control, AI-agent interaction, human-in-the-loop form prefilling, submissions, webhooks, or…
LeoYeAI/openclaw-master-skills
HITL Protocol — the open standard for human decisions in autonomous agent workflows.
PhucMPham/zalo-agent-cli
Automate Zalo messaging, Official Account (OA), and MCP server integration via zalo-agent-cli.
awslabs/agent-plugins
Build resilient, long-running, multi-step applications with AWS Lambda durable functions with automatic state persistence, retry logic, and orchestration for long-running executions.
zereight/gitlab-mcp
A skill your agent uses when working with the GitLab MCP server tools for merge requests, issues, repositories, pipelines, work items, variables, dependency proxy, vulnerabilities, webhooks, search…
aws/agent-toolkit-for-aws
Builds resilient, long-running, multi-step applications with AWS Lambda durable functions with automatic state persistence, retry logic, and orchestration for long-running executions.
Asymmetric-al/core
Implement idempotency keys and handling to ensure operations can be safely retried without duplicate effects.
Asymmetric-al/core
Audit and fix accessibility in Core UI. An agent skill from Asymmetric-al/core.
Asymmetric-al/core
A skill your agent uses when building any system where email content triggers actions — AI agent inboxes, automated support handlers, email-to-task pipelines, or any workflow processing untrusted…
Asymmetric-al/core
Build modern, composable, and accessible React UI components following the components.build specification.
Asymmetric-al/core
Guides a one-question-at-a-time design interview, captures alignment in agent/EVE-BRIEF.md, then scaffolds and implements a runnable eve agent with verbose teaching comments.
Asymmetric-al/core
Design engineering principles and patterns for building polished, accessible web interfaces.
Categories
A skill your agent uses 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…. Inngest Steps is an agent skill from Asymmetric-al/core., 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.
Inngest Steps fits situations like: implementing delays that must survive process restarts (e.g; 24-hour cart abandonment; scheduled follow-ups); waiting for human approval.
Run `npx skills add Asymmetric-al/core --skill inngest-steps -a claude-code`. Or copy the skill folder (.agents/skills/inngest-steps in Asymmetric-al/core) into .claude/skills/inngest-steps in your project. Claude Code loads it when a task matches its description.
Run `npx skills add Asymmetric-al/core --skill inngest-steps -a codex`. Or copy the skill folder (.agents/skills/inngest-steps in Asymmetric-al/core) into .agents/skills/inngest-steps in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Asymmetric-al/core --skill inngest-steps -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/inngest-steps, .gemini/skills/inngest-steps, .github/skills/inngest-steps and .opencode/skills/inngest-steps in your project.
SKILL.md names no scripts, command-line tools or credentials: Inngest Steps is instructions for the agent only. Our summary lists: Python 3.
SKILL.md names 1 domain. As links in the text: inngest.com. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Inngest Steps is published under the AGPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.2k tokens (SKILL.md is roughly 13k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Inngest Steps: Build With Simplepdf (SimplePDF/simplepdf-embed, 407 stars), Hitl Protocol (LeoYeAI/openclaw-master-skills, 2.2k stars), Zalo Agent (PhucMPham/zalo-agent-cli, 166 stars) and AWS Lambda Durable Functions (awslabs/agent-plugins, 916 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Asymmetric-al (a GitHub organization) maintains it in Asymmetric-al/core, which has 381 GitHub stars. The repository holds 43 skills in this directory. The repository was last updated on October 9, 2026.
Source: Asymmetric-al/core on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.