Managed durable agents
Managed agent methods require SDK 0.7.0 or later. Availability depends on account admission and deployment qualification.
Managed agents require both a qualified tools environment and account admission
on the deployment. They are a gated CPU capability. Their presence in the SDK
does not establish production qualification or general CPU workload support.
Authenticate with nodus login or provide NODUS_API_KEY through your secret
manager. Never put that account key in the uploaded project.
Deploy and submit
Save this synchronous entrypoint as agent.py in your project:
import nodus
@nodus.step(name="calculate", version="1", effect="pure")
def calculate(values):
return sum(values)
def main(event):
total = calculate(event["values"], _step_id="calculate")
return {"total": total}
Deploy the project and submit input from your authenticated client:
import nodus
with nodus.Client() as client:
agent = client.agents.create(
name="calculator",
project=".",
entrypoint="agent:main",
budget=20,
max_workers=4,
idempotency_key="calculator-deployment-001",
)
run = agent.submit(
{"values": [1, 2, 3]},
idempotency_key="calculation-001",
)
print(agent.id, agent.url, run.id, run.status)
The $20 limit is an explicit authorization across the agent's workers. The server controls cost accounting and reserved exposure. Defaults are supplied by the server. Omitted scaling settings use zero minimum workers and four maximum workers. Deployment acceptance does not mean a worker is ready.
Use setup to persist a dependency installation command with the revision.
The CLI provides --setup. Enable the matching package network permissions.
Advanced deployments can supply policy with explicit network allowlists.
Use agent.revisions(after=...) and agent.revision(number) to inspect
immutable definitions. agent.update(expected_revision=..., ...) admits a
new definition only if the observed current revision still matches.
Read client.agents.get(agent_id) and agent.runs.get(run_id) to observe
progress and the returned result. Use .list_page(after=...) or .iterate()
on client.agents and agent.runs to traverse history. agent.pause() stops
new dispatch and agent.resume() allows it again. run.cancel() requests
cancellation. Each mutation accepts an idempotency key. Run submission and
signals require an explicit key so uncertain responses can be retried safely.
When the server reports exhausted retries, run.retry() explicitly requests
another attempt within the existing authorization. It does not resolve an
unknown external effect or raise the spending limit.
The CLI exposes the same operations. nodus agent deploy NAME --budget USD
uploads the current directory. Add --project PATH to select another project
or --source-asset-id ID to reuse one already uploaded. Use nodus agent list,
detail, submit, runs, signal, pause, resume and cancel to operate
the deployment. submit accepts JSON through --input or --input-file and
requires --idempotency-key.
Connect GitHub in the console and grant access to deploy from a public or private repository. This uses the existing connection without passing GitHub credentials to the CLI:
nodus agent deploy worker \
--github-repo your-org/private-agent \
--github-ref main \
--budget 20
Omit --github-ref to use the repository default branch. The CLI adds the GitHub
network permission and runs --setup after checkout when provided. Choose one
of --github-repo, --project or --source-asset-id. Repository subdirectory
selection is not supported. Use a dotted Python module in --entrypoint when
your agent is inside a package.
Inputs can include session="customer-42" to request ordered processing for
that session. A timezone-aware deadline is optional. Use a new event key for
new input. Retrying the same event key with changed input is a conflict.
AsyncClient.agents exposes the same operations. Await methods that perform
requests and use async for with .iterate().
Wait without keeping a worker busy
Inside main, call nodus.agent.wait_for_event("approval", wait_id="approval:1")
to durably wait for an event. Deliver it with
run.signal("approval", {"accepted": True}, idempotency_key="approval-event-1").
The wait replays the recorded input when the driver resumes.
Use nodus.agent.sleep_until(when, wait_id="wake:1") with a timezone-aware
datetime for a timer. Keep the time and wait ID stable across replay.
nodus.agent.continue_as_new(next_input, continuation_id="page:2") commits
the next segment's input and ends the current execution. Do not catch these
execution yields with except BaseException.
The managed runtime starts the assigned entrypoint and connects the scoped
durable session automatically. Application code does not call resume or
select sandbox IDs. Waits and continuations run outside decorated steps.
Keep code outside steps deterministic. Record model calls and external effects
with the effect contracts in durable steps.
Recovery boundaries
New deployments admitted with qualified application-state recovery use
checkpoint-v1. Check run.recovery_policy to see the accepted policy. Existing
deployments retain their recovery policy when updated, and each run retains its
accepted code revision.
With checkpoint-v1, Nodus saves the files in NODUS_CHECKPOINT_DIR before
recording a completed step, entering a durable wait, continuing as new or
finishing the run. The step result and its verified state version commit
together. On a replacement attempt, Nodus restores that exact committed state
before starting the entrypoint. Completed steps replay their recorded results.
Uncommitted changes in the state folder are discarded before retrying.
Your application must serialize its in-memory state into that folder and load those files on restart. Finish, flush and close every state writer before a step returns or the driver calls a durable wait or continuation. Join background writers first. Nodus checks for changed files during capture but does not freeze background processes or provide an atomic filesystem snapshot. If a save fails, let the driver exit so recovery can restore committed state before another attempt. An empty baseline does not claim saved progress, and an empty folder cannot replace an earlier useful recovery point.
Inspect run.checkpoint_id and run.last_checkpoint_at for committed state.
run.checkpoint_status and run.checkpoint_error describe the latest capture.
The ready status means files are verified but the associated step or wait has
not committed yet. Empty baselines have no last_checkpoint_at. The console
shows the last useful save separately from pending saves and gives a next action
when a capture fails. CLI run output includes the same fields.
Project files, recovery state and downloadable outputs serve different purposes.
Files outside NODUS_CHECKPOINT_DIR are not part of these state commits. Rebuild
dependencies on replacement compute. Revisions without checkpoint-v1 retain
explicit file recovery, with file saves separate from step completion. Neither
file restoration nor replay restores arbitrary process memory.
JSON inputs and results are bounded. Inside the managed driver,
nodus.agent.put_blob(data) commits up to 32 MiB of bytes and returns an immutable
reference suitable for a step result. nodus.agent.get_blob(reference) checks
the complete content hash and length before returning bytes. Blobs are scoped
to the logical run and remain usable across worker replacement and continuations.
Run and account storage limits still apply. Blob operations commit independently.
Record their verified references in step results when they are needed for replay.
Unknown external effects remain blocked for explicit resolution. File recovery
cannot determine whether a remote API call succeeded when its response was lost.
Inspect run.steps() and independently verify the remote effect, then use
run.resolve() with the observed step revision, decision, reason and evidence
digest. With checkpoint-v1, a completed decision also requires an explicit
checkpoint_id whose files match the recorded result. Choose the run's current
committed checkpoint or the verified candidate returned for that uncertain step.
Step entries expose the candidate's checkpoint_id and checkpoint_status.
Do not select an older checkpoint that would discard other completed progress.
Omit checkpoint_id for no_effect or cancelled decisions, which retain the
current committed state.
The CLI provides nodus agent steps and nodus agent resolve --checkpoint-id
with the same evidence requirements. The console requires an explicit saved-state
selection and confirmation for completed effects. Finite tests do not guarantee
completion of every run.