A windswept bonsai on a floating island

Get to know Cadenya

We’re developers who love to build. We set out to create a yes-code platform that makes building agents feel like the best parts of building software.

Inngest AgentKit: durable agents, streaming and Go support (2026)

Inngest

By Cadenya

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 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.

AgentKitDurable agent loopstep.ai.infer and step.ai.wrapDurable EndpointsCadenya
What it isAgents, networks, routers, and state in “a TypeScript library”Your own loop: each model call and each tool call is a step.runOne model call as one stepAn HTTP handler whose steps are durableA hosted agent loop: Cadenya calls the model and runs the tools
LanguagesTypeScript (@inngest/agent-kit)TypeScript, Python, Goinfer in TypeScript, Python, Go. wrap in TypeScriptTypeScript and GoSDKs for Go, TypeScript, Python, Ruby, plus an HTTP API
Human in the loopA tool that calls step.waitForEvent()step.waitForEvent(), or step.waitForSignal() in TypeScript and GoThe surrounding function’s wait stepsstep.waitForEvent() makes the run async and redirects the clientA tool marked as needing approval parks the loop
Streaming to your UIuseAgent and useChat over Inngest RealtimeRealtime publish from the functionProvider streaming is listed as “coming soon”Server-sent events, TypeScript onlyThe React widget’s ConversationsPanel, resumed with Last-Event-ID
LicenseApache-2.0SDKs Apache-2.0SDKs Apache-2.0SDKs Apache-2.0SDKs 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 and Inngest vs Restate 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 planPriceExecutions includedRealtime connections
Free$0, “No credit card required”50,000 a month50
ProFrom $99 a month1 million, then from $0.000050 down to $0.000015 each1,000
BusinessFrom $499 a month10 million5,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 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 explains. To create an account, sign up at app.cadenya.com/signup, then copy your API key from the API keys page at app.cadenya.com/account/apiKeys.

Grow wherever AI goes next.

Start shipping agents that are equipped to evolve.

A pine bonsai overlooking a mountain lake