SequentialWorkflow coordinates three agents — planner, executor, and monitor — in a fixed order. The planner breaks the task into steps, then the executor and monitor iterate over each step in sequence. If a step fails, it retries up to max_retries times before aborting the pipeline.
Prerequisites
Install the project dependencies usinguv or pip:
.env.example to .env and fill in your credentials before running.
Building a sequential workflow
Initialize an LLM
Choose a local or cloud LLM. The agents accept any
BaseChatModel-compatible instance:- Local (Ollama)
- Cloud (OpenAI-compatible)
Create the agents
Instantiate each agent with the LLM. The
ExecutionAgent optionally accepts a list of tools:ExecutionAgent uses LangGraph’s create_react_agent to bind tools when tools is non-empty. Without tools the agent falls back to a plain LLM call.Build the agent dictionary
SequentialWorkflow requires exactly three keys: "planner", "executor", and "monitor".
The constructor asserts their presence at init time.Optionally attach tools to the workflow
Pass a list of tools to the workflow itself. The first tool in the list is used as a context compressor between steps. The workflow calls
.invoke() if available, otherwise ._run().Run the workflow
Call
.run() with your task string. max_retries controls how many times a failing step is retried before the whole pipeline is aborted.How retries work
For each step, the workflow runs an inner retry loop controlled bymax_retries:
- The executor runs the step with the current accumulated
context. - The monitor evaluates the result against the step objective and returns
{"success": bool, "feedback": str}. - If
successisFalse, the feedback string is appended tocontextand the executor is called again. - After
max_retries + 1total attempts without success,run()returnsstatus: "failed"immediately.
Context accumulation
Each successful step appends its result to a sharedcontext string:
tools[0]), the context is compressed before each execution call to keep prompt size manageable.
Full example
This mirrors the pattern frommain.py: