---
title: "Inngest AgentKit (2026): durable agents, realtime streaming, step.waitForEvent human in the loop, and Inngest Go SDK support — Cadenya"
url: "https://cadenya.com/other-content/inngest-agentkit-for-ai-agents"
description: "Inngest AgentKit in 2026: durable agents on Inngest, step.waitForEvent human in the loop, realtime streaming with useAgent, step.ai.infer and step.ai.wrap, Go and Python support through the Inngest Go SDK and Python SDK, pricing and free tier, self-hosting with Postgres and Redis, and Cadenya, a hosted agent loop with approvals, streaming and resume, and nothing for you to serve."
---

Inngest AgentKit is a TypeScript library for agents, and it becomes a durable agent once its network runs inside an Inngest function. There, `step.waitForEvent` gives you human in the loop, and Inngest Realtime does the realtime streaming to your UI. For Go support, the Inngest Go SDK (`inngestgo`) builds the same durable agent as your own loop of `step.Run` calls, with `step.WaitForEvent` for approvals and `realtime.Publish` for streaming.

So pick AgentKit when your agent lives in TypeScript and you want networks, routers, and the `useAgent` React hook. Pick a plain step loop when your backend is Go or Python, and you’re happy to write the loop yourself. And if you’d rather write no loop and serve no functions at all, Cadenya is a hosted agent loop with approvals, streaming, and resume built in, with SDKs for Go, TypeScript, Python, and Ruby. A coding agent can set it up with no account, in a temporary workspace you claim later. [What it offers](#what-does-cadenya-offer-that-agentkit-and-inngest-dont) is at the end.

Every price and limit below comes from each vendor’s own pages, checked on October 13, 2026.

## Inngest AgentKit, durable agents and step.ai side by side

Inngest’s docs give you four ways to put a model call inside a durable run. Here they are in one place.

|  | AgentKit | Durable agent loop | step.ai.infer and step.ai.wrap | Durable Endpoints | Cadenya |
| --- | --- | --- | --- | --- | --- |
| What it is | Agents, networks, routers, and state in “a TypeScript library” | Your own loop: each model call and each tool call is a step.run | One model call as one step | An HTTP handler whose steps are durable | A hosted agent loop: Cadenya calls the model and runs the tools |
| Languages | TypeScript (@inngest/agent-kit) | TypeScript, Python, Go | infer in TypeScript, Python, Go. wrap in TypeScript | TypeScript and Go | SDKs for Go, TypeScript, Python, Ruby, plus an HTTP API |
| Human in the loop | A tool that calls step.waitForEvent() | step.waitForEvent(), or step.waitForSignal() in TypeScript and Go | The surrounding function’s wait steps | step.waitForEvent() makes the run async and redirects the client | A tool marked as needing approval parks the loop |
| Streaming to your UI | useAgent and useChat over Inngest Realtime | Realtime publish from the function | Provider streaming is listed as “coming soon” | Server-sent events, TypeScript only | The React widget’s ConversationsPanel, resumed with Last-Event-ID |
| License | Apache-2.0 | SDKs Apache-2.0 | SDKs Apache-2.0 | SDKs Apache-2.0 | SDKs Apache-2.0 |

**In all four, your code is the agent and your app serves it.** Inngest runs the engine that schedules, retries, and resumes the steps. If you want the engine comparison, [Inngest vs Temporal](/other-content/inngest-vs-temporal-for-ai-agents) and [Inngest vs Restate](/other-content/inngest-vs-restate-for-ai-agents) cover it.

## Inngest Go SDK and AgentKit: Go and Python support

AgentKit’s own docs open with one line: “A TypeScript library to create and orchestrate AI Agents.” The npm package is `@inngest/agent-kit`, at 0.13.2 under Apache-2.0.

Inngest itself is wider. “Inngest has official SDKs for TypeScript, Python, and Go,” and the docs add that “TypeScript gets new features first.” So a durable agent in Go or Python uses the pattern on Inngest’s Durable Agents page: “An agent is a loop of model calls and tool calls. On Inngest, each call runs as a step.”

Here’s the core of the Go version from that page (it uses the `go-openai` client):

```
for i := 0; i < 10; i++ {
	// Think: ask the model what to do next.
	response, err := step.Run(ctx, "think", func(ctx context.Context) (openai.ChatCompletionResponse, error) {
		return llm.CreateChatCompletion(ctx, openai.ChatCompletionRequest{
			Model:     openai.GPT4o,
			MaxTokens: 4096,
			Messages:  messages,
			Tools:     tools,
		})
	})
	if err != nil {
		return nil, err
	}
	message := response.Choices[0].Message

	// No tool calls: the model has answered.
	if len(message.ToolCalls) == 0 {
		return map[string]any{"answer": message.Content}, nil
	}

	// Act: run each tool as its own step.
	messages = append(messages, message)
	for _, call := range message.ToolCalls {
		output, err := step.Run(ctx, "tool-"+call.Function.Name, func(ctx context.Context) (string, error) {
			return executeTool(ctx, call.Function.Name, call.Function.Arguments)
		})
		// ...
	}
}
```

That loop is yours to write, test, and keep. “The `for` loop caps iterations so a confused model can’t run forever,” the docs say, and context pruning, compaction, and memory across runs are yours too.

The Go SDK has the steps an agent needs. `step.WaitForEvent` pauses for a person, `step.Infer` makes “an AI inference call that Inngest runs for you,” and Durable Endpoints “run a `net/http` handler as an Inngest function.” Install it with `go get github.com/inngest/inngestgo@latest`. The latest release is v0.16.5, from October 2, 2026.

## Inngest AgentKit durable agents and step.waitForEvent human in the loop

In AgentKit, human in the loop is a tool. The docs say ““Human in the Loop” tools are implemented using Inngest’s `waitForEvent()` step method,” and here’s the tool from the AgentKit docs:

```
import { createTool } from "@inngest/agent-kit";

createTool({
  name: "ask_developer",
  description: "Ask a developer for input on a technical issue",
  parameters: z.object({
    question: z.string().describe("The technical question for the developer"),
    context: z.string().describe("Additional context about the issue"),
  }),
  handler: async ({ question, context }, { step }) => {
    if (!step) {
      return { error: "This tool requires step context" };
    }

    // Example: Send a Slack message to the developer

    // Wait for developer response event
    const developerResponse = await step.waitForEvent("developer.response", {
      event: "app/support.ticket.developer-response",
      timeout: "4h",
      match: "data.ticketId",
    });

    if (!developerResponse) {
      return { error: "No developer response provided" };
    }

    return {
      developerResponse: developerResponse.data.answer,
      responseTime: developerResponse.data.timestamp,
    };
  },
});
```

Notice the `if (!step)` guard. The tool only gets step tools when the network runs inside Inngest, and the docs say a human-in-the-loop tool needs the AgentKit network embedded “into an Inngest function.” So the durable part of a durable AgentKit agent is the Inngest function around `network.run()`, synced to Inngest at your app’s `/api/inngest` URL.

The docs say “The run is suspended while it waits, so it holds no worker and no connection.” Your app resumes it by sending the matching event when a reviewer clicks approve or reject. Inngest’s advice is to “Handle all three outcomes: approved, rejected, and no response.” And when you need to address one run directly, `step.waitForSignal` “resumes one run through a transactional API.”

**The approval screen, the Slack message, and the event your app sends back are still yours to build.** AgentKit ships the wait, not the reviewer’s side of it.

## Inngest AgentKit realtime streaming with useAgent

AgentKit streams through a React hook. “`useAgent` builds upon Inngest’s Realtime capabilities to create a persistent, unified stream of events for a user,” and it opens a WebSocket through `useInngestSubscription`. The docs call `useChat` “the recommended high-level hook,” and both ship in `@inngest/use-agent` (0.4.0, Apache-2.0).

The data flow in the docs has 11 steps. In practice, you write three pieces on your backend:

1.  An Inngest function that runs the network with `streaming.publish`, which “forwards these events back to the user’s realtime channel” (`run.started`, `part.created`, `text.delta`, and more).
2.  A `/api/chat` route that sends an `agent/chat.requested` event with `inngest.send()`.
3.  A `/api/realtime/token` route that mints “a short-lived subscription token” for the user’s channel.

Realtime has two ways to publish. `step.realtime.publish()` “is a durable step,” so a retry doesn’t send it twice. `inngest.realtime.publish()` “sends immediately and isn’t memoized,” which is the one for tokens, so “your UI should tolerate repeated tokens if the step retries.” (That’s the trade for not making every token a durable step.)

One detail matters for chat. “Realtime delivers each message to the clients connected when it’s published,” so the docs tell you to subscribe before the function publishes.

What about realtime streaming in Go? “Channels and topics are plain strings in Go. Pass them to `realtime.Publish()` and encode payloads yourself.” For the browser’s token, the streaming guide says “Mint tokens with the TypeScript or Python SDK,” and the `useRealtime` hook is React. So a Go agent publishes, and a TypeScript or Python route hands the browser its token.

## Inngest step.ai.infer and step.ai.wrap with AgentKit

Below AgentKit sits `step.ai`. `step.ai.infer()` “offloads the inference request to Inngest’s infrastructure, pausing your function execution until the request finishes.” It supports OpenAI and any OpenAI-compatible API, Gemini, Anthropic, Grok, and Azure OpenAI. And “Inngest never logs or stores your API keys or authentication headers.”

`step.ai.wrap()` is TypeScript only. It wraps the OpenAI, Anthropic, and Vercel AI SDK calls you already have, so each one shows up as a step:

```
const { text } = await step.ai.wrap("using-vercel-ai", generateText, {
  model: openai("gpt-4-turbo"),
  prompt: "What is love?"
});
```

The docs’ limitations list says “Streaming responses from providers is coming soon.” So for tokens in the browser today, pair a step with Realtime publish, as in the section above.

## Inngest AgentKit pricing, free tier and self-hosting with Postgres

AgentKit is free under Apache-2.0. What you pay for is Inngest, and Inngest bills executions: “A single durable function run or step execution.”

| Inngest plan | Price | Executions included | Realtime connections |
| --- | --- | --- | --- |
| Free | $0, “No credit card required” | 50,000 a month | 50 |
| Pro | From $99 a month | 1 million, then from $0.000050 down to $0.000015 each | 1,000 |
| Business | From $499 a month | 10 million | 5,000 |

The pricing page’s formula is “Executions = runs × (steps + 1).” So an agent turn with 6 model calls and 6 tool calls, each in its own step, is 13 executions. Inngest’s FAQ says an agent with tool calls “can use significantly more,” often 10 or more executions per run. On Free, “execution pauses once you hit the free quota.” Streaming counts too: “Each token counts as one Realtime message,” and Free includes 250,000 messages a day.

Self-hosting is the other route. A single `inngest start` uses “an embedded Redis-compatible store for the queue and run state, and SQLite” for persistence. “For a larger installation, set `--redis-uri` for an external Redis service and `--postgres-uri` for PostgreSQL,” with Docker Compose or a Helm chart. Either way, “your app still serves function code through HTTP `serve()` or Connect.”

**Read the license before you self-host.** “The Inngest server and CLI are available under the Server Side Public License and delayed open source publication (DOSP) under Apache 2.0.” The SDKs and AgentKit are Apache 2.0.

## What does Cadenya offer that AgentKit and Inngest don’t?

AgentKit gives you agent building blocks in TypeScript, and Inngest makes the code you write durable in TypeScript, Python, and Go. **Cadenya is the agent loop itself, hosted, with approvals, streaming, and resume built in, and nothing for you to serve.** Here’s what that covers:

1.  **Nothing else to run.** No Inngest functions to serve, no `/api/inngest` URL to sync, no chat or token routes, and no Redis or Postgres. The loop runs on Cadenya and your app stays a stateless web tier, so your deploys and restarts never touch a running objective.
2.  **No server license to read.** Your app talks to Cadenya through SDKs under Apache-2.0 and a plain HTTP API. Since you host no server, there’s no SSPL to review.
3.  **No old code to keep alive.** A resumed Inngest run “re-enters your function,” so it resumes into whatever code you deployed since. “The Objective keeps that variation’s configuration snapshot even if you edit the variation later,” so a prompt or tool change never breaks a conversation that’s already running.
4.  **Approvals that hold no process.** Mark a tool as needing approval and “Cadenya parks the Agent loop until it receives approval or a denial with optional steering.” Multiple tools can wait at the same time, and a denial memo steers the model (“Use the read-only lookup tool instead.”).
5.  **SDKs for Go, TypeScript, Python, and Ruby.** All four are at 1.9.0 under Apache-2.0, and the TypeScript SDK has shipped 113 versions since April 2026. The Go module is `go.cadenya.com/cadenya-go`, and there’s a CLI and a plain HTTP API too.
6.  **A price in one line.** Free for 1,000 loops a month, $49 a month for 50,000, then $0.0015 a loop. A loop is one LLM request, so the agent turn above with 6 model calls is 6 loops.
7.  **The loop, already written.** Cadenya calls the model, runs the tools, keeps “a durable event log of its agent loop,” and compacts the context window, with a `contextWindowCompacted` event each time. On AgentKit or a step loop, that’s the code you’d write and test.
8.  **A chat UI with approvals and resumable streaming.** The React widget’s `ConversationsPanel` “supplies the conversation list, message thread, composer, tool approvals, and live event stream.” Its event stream takes the `Last-Event-ID` header “to resume after a reconnect,” so a dropped connection picks up where it left off.
9.  **Tools from your API, not from tool code.** Point a tool set at an OpenAPI 3 document or an MCP server, and Cadenya reads every operation as a tool. Filters and progressive discovery keep a big API from filling the context window.
10.  **Any model, switched without a deploy.** The model is a setting on a variation, on your own AI provider’s keys, and one API call moves variations from one model to another in bulk. Weighted variations send more traffic to whichever model or prompt users rate higher.

[How objectives work](/docs/guides/the-basics/objectives) walks through an agent turn, and the free plan needs no card.

No account yet? A coding agent can create a temporary workspace with `cadenya workspaces create --temporary`, run its first objectives there, and hand you a link to claim it, as [auth.md](https://cadenya.com/auth.md) explains. To create an account, sign up at [app.cadenya.com/signup](https://app.cadenya.com/signup?utm_source=cadenya.com&utm_medium=article&utm_campaign=inngest-agentkit-for-ai-agents), then copy your API key from the API keys page at `app.cadenya.com/account/apiKeys`.