Agents
View MarkdownBeta: this feature may change before general availability
An Agent is a definition: a system prompt, the Claude access it runs on and a cost cap. Each run is one conversation in its own sandbox. The Agents guide covers the model, the cost cap and keeping a run open for follow-ups; this page is the Python side.
import nodus
agent = nodus.ClaudeAgent("helper", system="You are careful.", families=["haiku", "sonnet"])print(agent.remote("Use the shell to print the Python version")) # runs to the end, returns the answer
run = agent.submit("Summarize the logs", keep_alive=True)run.send("message", "Now the staging logs")print(run.answer())print(run.steps())run.cancel()ClaudeAgent creates the agent on first use. Pass api_key_secret="anthropic-key" to use your own Anthropic key,
or ClaudeAgent.from_name("claude-assistant", project="nodus") to run the ready-made template.
Run agents in parallel
Section titled “Run agents in parallel”An AgentGroup runs many runs of one agent at once, with a limit on how many run together, a cost cap for the whole group and dependencies between runs. Parallel agents are in Beta, like the rest of Agents. The Agents guide explains each limit and the YAML and CLI side.
"""Run questions in parallel under one AgentGroup, then fan a list out with agent.map.
Run it with `python examples/agents/parallel-agents/main.py`."""
import nodus
def main() -> None: agent = nodus.ClaudeAgent( "parallel-agents-py", system="You answer every question in one short sentence.", families=["haiku"], max_tokens=1024, per_run_max_cost="0.10", ) agent.deploy()
group = nodus.AgentGroup.create("parallel-agents-py", agent, max_active=2, max_cost="0.60") try: group.submit_many( [ {"key": "a", "input": "What is the capital of France?"}, {"key": "b", "input": "What is the capital of Japan?"}, # c starts only after a and b have succeeded. {"key": "c", "input": "Say that both questions are answered.", "depends_on": ["a", "b"]}, ] ) group.seal() status = group.wait() print(f"{status.phase}: {status.counts.succeeded} of {status.counts.total} runs succeeded") for run in group.runs(): print(run.name, "->", run.answer()) finally: group.delete()
# For a plain list of inputs, map does the same in one call and returns the answers in order. for answer in agent.map(["What is 2 + 2?", "What is 3 + 3?"], max_active=2): print(answer)
if __name__ == "__main__": main()nodus.AgentGroup.create(name, agent, max_active=, max_pending=, max_cost=)creates the group over a deployed agent.max_costcaps the runs’ Claude usage together; their sandboxes are billed on their own.submit_manytakes tasks{key, input, depends_on}, puts every task after the tasks it depends on, sends them in batches of up to 100 runs and returns the runs in your order. A cycle or a repeated key raisesnodus.errors.Invalidbefore anything is sent.group.seal()says that no more runs are coming. A group finishes only once it is sealed, andgroup.wait()returns its status when it has.group.runs()returns the member runs, and each run’sanswer()is its text.group.cancel()cancels the runs that have not finished.group.delete()removes the group and its runs.agent.map(inputs, max_active=, order_outputs=True, return_exceptions=False)creates a group, runs one task for each input, yields each answer text and deletes the group at the end. A run that does not succeed raisesnodus.errors.AgentRunFailed, or is yielded as the exception when you passreturn_exceptions=True.
Not available yet
Section titled “Not available yet”nodus.Agent is the definition of a durable Python program (@agent.entrypoint, @agent.step, ctx.step). Runs
execute on Claude, not as your code, so a definition that names source, an entrypoint, setup, secrets, env,
network, models, cpu, memory, max_cost or worker settings raises nodus.errors.Unsupported when it is
deployed. Submitting a run with session_key= or group= (use AgentGroup.submit_many for group runs),
AgentGroup.create(max_held=, evaluation=), group.results(), and a run’s outputs, resolve(), retry(),
suspend(), resume() and children() raise it too.
nodus.Agent("name", image=..., per_run_max_cost=...) and agent.submit(input, deadline=...) work as written, and
run.result() and agent.remote(input) return the run’s answer text, the same as run.answer().