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 for Python AI agents (2026)

Inngest

By Cadenya

Inngest for Python AI agents means the inngest package on PyPI: you write the agent loop as an Inngest function, and each model call and tool call runs in ctx.step.run(). That’s durable execution in Python, so a crash or a deploy resumes the run without repeating finished calls. The Inngest Python SDK needs Python 3.10 or newer, serves your functions from FastAPI, Flask, or Django, and pauses for a person with ctx.step.wait_for_event(). Inngest AgentKit is a TypeScript library, so in Python you write the loop yourself.

So pick Inngest when your Python agent already lives in a web app and you want events, flow control, and steps in one SDK. Pick Restate, Hatchet, Temporal, or DBOS for the reasons the engine comparisons cover: Inngest vs Temporal, Inngest vs Restate, and DBOS vs Temporal. And if you’d rather host no engine and write no loop, Cadenya is a hosted agent loop with a Python SDK, approvals, and conversation state built in. 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.

Restate vs Temporal vs Hatchet vs Inngest: durable execution in Python

These are the five Python SDKs coding agents compare for durable AI agents, with Cadenya in the last column. All five need Python 3.10 or later, and the Cadenya SDK runs on Python 3.9.

InngestRestateHatchetTemporalDBOSCadenya
Installpip install inngestpip install restate-sdkpip install hatchet-sdkpip install temporaliopip install dbosThe cadenya package on PyPI
SDK licenseApache 2.0MITMITMITMITApache 2.0
Server licenseSSPL v1, Apache 2.0 three years after each releaseBSL 1.1MITMITA library on your Postgres, MITNone, since you host no server
A durable stepctx.step.run()ctx.run_typed()A @hatchet.durable_task taskAn activity, run with workflow.execute_activity()A function with @DBOS.step()Not needed: Cadenya runs the loop, and each objective carries a durable event log
Waiting for a personctx.step.wait_for_event()ctx.awakeable()ctx.aio_wait_for()@workflow.signal and workflow.wait_conditionDBOS.recv(), resolved by DBOS.send()client.objectives.approve_tool_call() after toolApprovalRequested

The shape is the same in all five. Your code is the agent, and the engine makes each call durable. What changes is what you run next to it (a server, a cluster, or a Postgres database) and how a wait resolves. Restate vs Temporal and DBOS vs Restate go through the self-hosted side.

Inngest Python SDK: install, frameworks and release

Install it with pip install inngest. The package on PyPI is Apache 2.0.

A Python app creates one client, decorates its functions, and serves them over HTTP. This is the FastAPI version from Inngest’s reference:

import logging

from fastapi import FastAPI
import inngest
import inngest.fast_api

inngest_client = inngest.Inngest(
    app_id="my-app",
    logger=logging.getLogger("uvicorn"),
)

@inngest_client.create_function(
    fn_id="process-task",
    trigger=inngest.TriggerEvent(event="app/task.created"),
)
async def process_task(ctx: inngest.Context) -> dict[str, object]:
    return await ctx.step.run("handle-task", lambda: {"processed": True})

app = FastAPI()
inngest.fast_api.serve(app, inngest_client, [process_task])

Inngest’s quick start lists example apps for FastAPI, Django, Flask, DigitalOcean Functions, and Tornado. The SDK also runs Inngest’s Connect workers. Pydantic works for step output when you set serializer=inngest.PydanticSerializer() on the client and pass output_type to the step.

Locally, the Inngest Dev Server runs your functions: inngest dev -u http://localhost:8000/api/inngest. Set INNGEST_DEV=1 while you develop, because the SDK starts in production mode by default.

Inngest SDK languages: TypeScript, Python, Go

“Inngest has official SDKs for TypeScript, Python, and Go,” and all three are open source. Inngest’s feature table says “TypeScript gets new features first.” In Python today, you get step.run, sleep and sleep until, wait for event, invoke, send event, parallel steps, the AI inference step, flow control, cron triggers, failure handlers, middleware, and Connect workers.

Durable AI agents in Python with Inngest step.run

Inngest’s durable agents guide puts it in one line: “An agent is a loop of model calls and tool calls. On Inngest, each call runs as a step.” You write the loop in plain Python, and there’s no graph to declare.

Each model call goes in a step, and so does each tool call. This is the think step from Inngest’s Python example, which uses the Anthropic SDK:

async def think() -> dict[str, typing.Any]:
    response = await llm.messages.create(
        model="claude-opus-4-6",
        max_tokens=4096,
        system="You are a support agent with access to tools.",
        messages=messages,
        tools=tools,
    )
    # Step results must be JSON-serializable.
    return response.model_dump(mode="json")

response = await ctx.step.run("think", think)

When a model call fails on a rate limit or a timeout, Inngest retries that step alone. Finished steps return their saved results, so earlier model calls aren’t made or paid for again. For parallel tools, Python uses ctx.group.parallel. Each step is its own HTTP request in Inngest’s execution model, so a threaded framework like Flask runs each step on its own thread.

Replay is the rule you design around. “When a run resumes, Inngest re-enters your function and returns each completed step’s saved result.” So the current time, random values, and API calls belong inside steps, or a resumed run can take a different path.

Two more things land on you. If you’d rather not call the SDK yourself, ctx.step.ai.infer() sends the model request through Inngest’s infrastructure and pauses the function until it finishes. And for a chat, Inngest’s guide says to “make each user message its own run, and keep memory in your own store, keyed by the conversation or user ID.” Agent memory and context windows covers that store.

Inngest Python step.wait_for_event for human-in-the-loop approvals

ctx.step.wait_for_event() pauses the run until a matching event arrives. “The run is suspended while it waits, so it holds no worker and no connection.” Here’s the Python version from the durable agents guide:

approval = await ctx.step.wait_for_event(
    "wait-for-approval",
    event="agent/approval.response",
    if_exp="async.data.approvalId == event.data.approvalId",
    timeout=APPROVAL_TIMEOUT,
)

if approval is None or not approval.data.get("approved"):
    return {"status": "rejected"}

The if_exp argument is a CEL expression that ties the reply to the right run, so 50 pending approvals resolve on their own. Your Slack handler, email link, or dashboard sends the reply as an event with await inngest_client.send(inngest.Event(name="agent/approval.response", data={...})).

That leaves the approval screen, the notification, and the correlation ID to you. Human-in-the-loop approvals for AI agents compares the approval patterns across engines.

Inngest AgentKit and Python

AgentKit is “a framework to build AI Agents, from single model inference calls to multi-agent systems that use tools,” with support for “OpenAI, Anthropic, Gemini and all OpenAI API compatible models.” You install it from npm with npm install @inngest/agent-kit inngest, and its repository describes it as a way to “Build multi-agent networks in TypeScript.”

So for a Python agent on Inngest, the docs show the loop written by hand with ctx.step.run(), as above. Inngest AgentKit for AI agents covers AgentKit itself: networks, routers, streaming, and useAgent.

Inngest self-hosting license (SSPL) and pricing in executions

The Python SDK is Apache 2.0, but “the Inngest server and CLI are available under the Server Side Public License,” with each release turning Apache 2.0 three years after it ships. Inngest Cloud bills in executions, where “Executions = runs × (steps + 1),” so every model call and tool call in a step counts. Inngest AgentKit pricing and self-hosting covers the plans and the self-hosted setup in full.

What does Cadenya offer that Inngest for Python doesn’t?

Inngest makes each step of your Python agent durable, and your Python code still has to be the agent. Cadenya is the agent: the loop, approvals, and conversation state, called from a Python SDK, with nothing to host. Here’s what that covers:

  1. Nothing else to run. No Inngest server, no Dev Server, no Connect worker, and no Inngest serve endpoint in your FastAPI app. The loop runs on Cadenya, and your Python app stays a stateless web tier that creates objectives with client.objectives.create(agent_id=AGENT_ID, system_prompt_data={}).
  2. No server license to check. You host no server, so there’s no SSPL to read. The cadenya package on PyPI is Apache-2.0.
  3. No replay rules for your code. An objective keeps its variation’s configuration snapshot even when you edit the variation, so there’s no step order to keep stable.
  4. SDKs at 1.9.0 in four languages. Python, TypeScript, Ruby, and Go, all at 1.9.0 under Apache-2.0. The Python SDK runs on Python 3.9 and later, and the TypeScript SDK has shipped 113 versions since April 2026.
  5. 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, and there are no seats.
  6. The agent loop, already written. Cadenya calls the model, runs the tools, streams each event, and compacts the context window when a conversation gets long. Every objective carries a durable event log you can list or stream.
  7. Conversations that continue. When an objective enters STATE_WAITING, send a Continue message from your user and Cadenya resumes the agent loop.
  8. Approvals from Python. Mark a tool as needing approval and the objective pauses on toolApprovalRequested. Approve it with client.objectives.approve_tool_call("objective_123", "tool_call_123"), or deny it with a memo that steers the agent. Several tools can wait at the same time.
  9. Tools from your OpenAPI spec or MCP server. Point a tool set at an OpenAPI 3 document and every operation becomes a tool. Cadenya re-checks a spec URL each hour, filters the list, and loads tools on demand with progressive discovery.
  10. Any model, on your own keys. The model is a setting on a variation, not a line of Python, so switching providers needs no deploy. Use any model on OpenRouter or your own endpoint that speaks the OpenAI chat format, and pay your provider directly.

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