Skip to content

Why Noeta ​

Most agent libraries give you a loop that runs inside one process. That is enough for a chat window. It stops being enough when an agent runs for hours with nobody watching, has to wait for a person, or needs more than one machine. Noeta is built for those cases.

A crash is a pause, not a loss ​

Noeta never keeps task state in memory. Every model call, tool call and decision is appended to an event log, and state is rebuilt from that log whenever it is needed. A process that dies mid-task loses nothing: the next worker replays the log and carries on from the last recorded step. A step that was cut off halfway is re-run when that is safe; if re-running could repeat an action that needs approval, the task stops and waits for a person instead.

Worker AEvent logWorker Brunningkilled · lease expiresstep 1step 2step 3step 4step 5step 6replay logcarries on from step 4
python
from noeta.sdk import Client, HostConfig, Options
from noeta.sdk.providers import AnthropicProvider

options = Options(system_prompt="You are a careful release engineer.")
db = HostConfig(storage_path="./noeta.sqlite")   # or a postgresql:// DSN

with Client(options, provider=AnthropicProvider(), model="claude-sonnet-5",
            host_config=db) as client:
    task_id = client.start(goal="Draft the release notes.").task_id

# A different process, after a restart, reads the same task back.
with Client(options, provider=AnthropicProvider(), model="claude-sonnet-5",
            host_config=db) as client:
    for item in client.messages(task_id):
        print(item)

The log also answers "what did the agent do, and why?" after the fact: every tool call, approval, token count and compaction is on it, and nothing is overwritten. → Event log & recovery

Waiting is a state, not a blocked thread ​

A task can stop and wait for:

  • a human approval of a risky tool call, or an answer to a question
  • a timer
  • a subtask it spawned
  • an event from outside (a webhook, a CI result)
waits forApprovalTimerSubtaskExternal eventRunningWaitingno thread · no memory · no costseconds — or monthswoken exactly onceRunningDone

While it waits, nothing runs and nothing is held in memory. When the thing it is waiting for arrives, exactly one worker wakes it — once, even across crashes. A month-long approval uses the same mechanism as a five-second tool call.

python
turn = client.start(goal="Clean up the build directory.")
if turn.status == "suspended":          # e.g. waiting on approval of a Bash call
    print(turn.wake_handle)             # what it is waiting for
    # ...hours later, maybe from another process:
    client.approve(turn.task_id, call_id="...")

→ Tasks & waking

Grow without a rewrite ​

The agent is an Options value. How it runs is a separate choice, and you can change that choice without touching the agent.

The same agent — Options(...) — unchangedA scriptquery(options, goal=...)in memory or SQLiteA serviceclient.start_workers(4)SQLiteSeveral hostsstorage_path="postgresql://…"Postgres1 processW1W2W3W4host 1host 2host 3
StageWhat changes
A scriptquery(options, goal=...) — one call, one answer
A serviceClient(options, ...) plus client.start_workers(4) — a worker pool in your process
Several hostsHostConfig(storage_path="postgresql://...") — hosts share one database; a lease makes sure only one worker drives a task at a time

There is no daemon to operate and no extra service in the middle. You own the process and the database. → Deploy to production

Also ​

  • Everything is a plugin — including the built-ins. The kernel ships no capabilities. File tools, web, memory, MCP, sandboxes, storage backends and model adapters are plugins that reach the kernel through the same loader yours does; the build fails if anything takes a shortcut. A plugin declares what it contributes in a static manifest, so it can be listed and conflict-checked before any of its code runs. → Write a plugin
  • Any model. Anthropic, any OpenAI-compatible /chat/completions gateway, and the OpenAI Responses API. Switching is one line; the agent, its tools and its recorded history do not change. → Connect a model
  • Control before action. Permission modes decide which tool calls stop for approval. Guards can block a call before it runs; observers can only watch, so a broken observer can never break a task.

Compared with other tools ​

NoetaClaude Agent SDKLangGraphTemporal
What it isDurable agent runtime, as a libraryAgent loop library for ClaudeGraph-based agent frameworkDurable workflow platform
Control flowThe model decides each stepThe model decidesA graph you defineWorkflow code you write
What is savedEvery event; state is derived from itThe conversationCheckpoints of graph stateWorkflow history
Waiting for a human / timerBuilt in, woken exactly onceResume the conversationInterrupt, then the caller resumesBuilt in
Scaling outWorker pool; many hosts on PostgresOne processUp to you, or the hosted platformA Temporal cluster
ModelsAny, one line to switchClaudeAny—
Extra service to runNoneNoneNoneTemporal server

Claude Agent SDK gives your code an agent loop on Claude and manages the conversation for you. Noeta answers a different question: how to turn an agent's run into a record you can resume, audit and move between machines. If you want the lowest-friction way to call Claude with tools, use the SDK.

LangGraph models an agent as a graph and saves checkpoints of its state. Noeta has no graph — the model decides each step — and saves what happened rather than snapshots of what the state was. Scheduling (leases, workers, reclaiming stuck tasks) ships in the library. LangGraph has a much larger integration catalogue and community.

Temporal runs workflows whose shape you write in code ahead of time. Noeta is for work whose shape the model discovers as it goes. If you know the steps, Temporal is the better fit.

Pi and other terminal harnesses drive an agent interactively in your terminal. Noeta runs agents unattended on your own infrastructure. They combine well: a terminal front end can drive a task running on a Noeta worker pool.

When not to use Noeta ​

  • You don't want to run anything. You operate the process and the database. If "call a vendor API, no operations" is the requirement, a hosted client library is simpler.
  • You need a large integration catalogue today. The built-in tool set is small and there is no plugin marketplace.
  • One host is not enough and you can't run Postgres. SQLite and in-memory storage are single-host.

More detail: Known limitations.

Evidence ​

An agent built only on the public SDK — noeta-agent's main preset on Claude Opus 4.8 — scored 82.5% on a 40-task Terminal-Bench 2.1 sample (the public board spans 58.7%–83.8%) and 86.7% on a 15-instance SWE-bench Verified subset, run on the official harness. Both are samples, not full leaderboard runs. → Benchmarks

Next ​

Released under the Apache License 2.0.