Two programming models on one runtime
Motus gives you two ways to write an agent, and both run on the same underlying runtime. You pick the one that matches your problem, and the two can be combined when you need to.ReActAgent
For exploratory, open-ended problems. The model decides what to do next. You hand
ReActAgent a client, a set of tools, and a system prompt. It calls the model, runs any tool calls the model asks for, feeds the results back, and loops until the model returns a final answer.Workflow
For stable control over a known-good procedure. You decide what to do next. Decorate plain Python functions with
@agent_task, call them, and Motus turns the data flow between them into a parallel task graph. No DAG wiring, no YAML.ReActAgent
Workflow
When to reach for which
Reach forReActAgent when the problem is open-ended and you want the agent to discover the right steps on its own. Research, debugging, triage, coding agents, customer support, anything where you cannot write down the plan in advance. You give it tools and let the model explore.
Reach for Workflow when the procedure is already a solved problem and you want stable, repeatable control over it. ETL pipelines, evaluation harnesses, content processing, batch LLM jobs, anything where the steps are well understood and you mostly want parallelism, retries, and observability around them.
The two compose. A workflow step can call a ReActAgent when part of an otherwise stable pipeline needs exploration. An agent can delegate to another agent via as_tool() when one exploratory loop should hand off to a more specialized one.
The runtime underneath both
Both programming models run on the same task scheduler. When aReActAgent calls the model or runs a tool, that call is submitted as an @agent_task under the hood, which is the same path you are using directly when you decorate Workflow steps. Independent tasks run in parallel, each returns an AgentFuture that carries its result and its dependencies, and retries, timeouts, and cancellation all live at this level. This is what makes a ReActAgent’s parallel tool calls actually parallel, and what lets you mix both styles in one project without adopting a second execution system.
The pieces
ReActAgent
- Model clients: OpenAI, Anthropic, Gemini, OpenRouter, and local models via
base_url - Tools:
@tool,@tools, function tools, class tools, Docker sandboxes - MCP tools: wrap any MCP server with
get_mcp() - Memory:
BasicMemoryandCompactionMemory - Guardrails: input, output, and per-tool validation hooks
- Reasoning and cache policy: extended thinking and prompt caching
- Multi-agent:
as_tool()andfork() - Human in the loop: pause mid-turn for approval or clarification
- Skills: load extra instructions and examples on demand
Workflow
@agent_task: decorate any sync or async Python functionAgentFuture: dependency tracking through function arguments, non-blocking operatorsresolve(): block on or await a future- Retries, timeouts, and policy overrides: per-task and per-call
- Multi-return and per-task hooks:
num_returns,on_start,on_end
Runtime, serving, and tracing
- Runtime: the task scheduler underneath both programming models (
GraphScheduler, thread pool, event loop) - Serving:
motus servelocally,motus deployto Motus Cloud, session-based REST API - Tracing: opt-in via one environment variable, lifecycle hooks, HTML viewer, OpenTelemetry export
Where to go next
Pick a starting point based on what you want to build.- A single LLM-driven assistant. Start with Agents, then Tools, then Memory.
- A parallel pipeline or batch job. Start with Workflow. Circle back to Agents if any step needs an LLM.
- A team of agents. See Multi-agent for how
as_tool()turns one agent into a tool for another. - An agent that needs external tools. See MCP Integration to plug in any MCP server.
- An existing agent from another framework. See the Integrations tab for OpenAI Agents SDK, Anthropic SDK, and Google ADK adapters.
- Shipping any of the above. See Serving for the REST API and Deployment for the cloud workflow.

