Skip to main content
Workflows are deterministic, stateful, multi-agent programs that are built for production applications. They’re battle-tested, incredibly powerful and offer the following benefits:
  • Pure python: Build your workflow logic using standard python. Having built 100s of agentic systems, no framework or step based approach will give you the flexibility and reliability of pure-python. Want loops - use while/for, want conditionals - use if/else, want exceptional handling - use try/except.
  • Full control and flexibility: Because your workflow logic is a python function, you have full control over the process, like validating input before processing, spawning agents and running them in parallel, caching results as needed and correcting any intermediate errors. This level of control is critical for reliability.
  • Built-in storage and caching: Workflows come with built-in storage and state management. Use session_state to cache intermediate results. A big advantage of this approach is that you can trigger workflows in a separate process and ping for results later, meaning you don’t run into request timeout issues which are very common with long running workflows.
Because the workflow logic is a python function, AI code editors can write workflows for you. Just add https://docs-v1.agno.com as a document source.

The best part

There’s nothing new to learn! You already know python, you already know how to build Agents and Teams — now its just about putting them together using regular python code. No need to learn a new DSL or syntax. Here’s a simple workflow that caches the outputs. You see the level of control you have over the process, even the “storing state” happens after the response is yielded.
simple_cache_workflow.py

How to build a workflow

  1. Define your workflow as a class by inheriting the Workflow class.
  2. Add agents or teams as attributes on the workflow. These isn’t a strict requirement, just helps us map the session_id of the agent to the session_id of the workflow.
  3. Implement the workflow logic in the run() method. This is the main function that will be called when you run the workflow (the workflow entrypoint). This function gives us so much control over the process, some agents can stream, other’s can generate structured outputs, agents can be run in parallel using async.gather(), some agents can have validation logic that runs before returning the response.
You can also execute workflows asynchronously using the arun method. This allows for more efficient and non-blocking operations when calling agents. For a detailed example, please refer to the Async Workflows Example.

Full Example: Blog Post Generator

Let’s create a blog post generator that can search the web, read the top links and write a blog post for us. We’ll cache intermediate results in the database to improve performance.

Create the Workflow

  1. Define your workflow as a class by inheriting from the Workflow class.
blog_post_generator.py
  1. Add one or more agents to the workflow and implement the workflow logic in the run() method.
blog_post_generator.py

Run the workflow

Install libraries
Run the workflow
Now the results are cached in the database and can be re-used for future runs. Run the workflow again to view the cached results.
Checkout more usecases and examples related to workflows.

Design decisions

Why do we recommend writing your workflow logic as a python function instead of creating a custom abstraction like a Graph, Chain, or Flow?In our experience building AI products, the workflow logic needs to be dynamic (i.e. determined at runtime) and requires fine-grained control over parallelization, caching, state management, error handling, and issue resolution.A custom abstraction (Graph, Chain, Flow) with a new DSL would mean learning new concepts and write more code. We would end up spending more time learning and fighting the DSL.Every project we worked on, a simple python function always seems to do the trick. We also found that complex workflows can span multiple files, sometimes turning into modules in themselves. You know what works great here? Python.We keep coming back to the Unix Philosophy.If our workflow can’t be written in vanilla python, then we should simplify and re-organize our workflow, not the other way around.Another significant challenge with long-running workflows is managing request/response timeouts. We need workflows to trigger asynchronously, respond to the client confirming initiation, and then allow the client to poll for results later. Achieving this UX requires running workflows in background tasks and closely managing state so the latest updates are available to the client.For these reasons, we recommend building workflows as vanilla python functions, the level of control, flexibility and reliability is unmatched.