Skip to main content

DoDo - A stateful agentic framework

Project description

dodo

PyPI version License: MIT

An AI workflow automation engine for browser automation, RPA, testing, and more.

Built for frameworks like webtask.

Installation

pip install dodoai
pip install dodoai[gemini]  # With Gemini support

Overview

from dodo import Agent, Gemini

agent = Agent(llm=Gemini(), tools=[...])

# First time - LLM figures out the workflow
run = await agent.do("add item to cart")

# Later - replay without LLM (fast & cheap)
await agent.redo(run)
verdict = await agent.verify("cart has 1 item")

if not verdict.passed:
    # Fallback to LLM if replay fails
    run = await agent.do("add item to cart")

Core Concepts

Three simple methods for workflow automation:

  • do(task) - Execute workflow steps with LLM reasoning
  • verify(condition) - Check if conditions are met
  • redo(run) - Replay recorded workflows without LLM

Features

Stateful workflows

Agent remembers context across multiple steps:

# Multi-step workflow with context
await agent.do("search for laptop on Amazon")
await agent.do("add the first result to cart")
await agent.do("proceed to checkout")

verdict = await agent.verify("item is in cart")

Efficient replay

Record once, replay when environment is similar:

# First time - LLM figures out the workflow (expensive)
run = await agent.do("add laptop to cart and checkout")

# Later - replay the same workflow (cheap)
await agent.redo(run)
verdict = await agent.verify("order placed successfully")

if not verdict.passed:
    # Environment changed, use LLM to adapt
    run = await agent.do("add laptop to cart and checkout")

Structured output

Get typed results using Pydantic models:

from pydantic import BaseModel

class ProductInfo(BaseModel):
    name: str
    price: float
    in_stock: bool

run = await agent.do("extract product information", output_schema=ProductInfo)
product = run.output  # Typed ProductInfo object

Verification with feedback

Check conditions with detailed reasoning:

verdict = await agent.verify("cart total is less than $100")
if verdict.passed:
    print("Success!")
else:
    print(f"Failed: {verdict.reason}")

Use Cases

Browser automation:

# Automate web workflows
await agent.do("go to linkedin.com")
await agent.do("search for software engineers in SF")
await agent.do("message the first 5 results")

RPA (Robotic Process Automation):

# Automate repetitive workflows
await agent.do("login to portal")
await agent.do("navigate to reports section")
await agent.do("download monthly report")

Testing & QA:

# Record test cases, replay for regression
run = await agent.do("complete checkout flow")
await agent.verify("order confirmation displayed")

# Regression test
await agent.redo(run)

Building Workflows

1. Define tools

Tools are the actions your agent can perform:

from dodo import tool

@tool
async def click_button(element_id: str) -> str:
    """Click a button on the page.

    Args:
        element_id (str): ID of button to click
    """
    # Your automation logic
    return "Button clicked"

@tool
class DatabaseTool:
    """Query the database."""

    def __init__(self, db_connection):
        self.db = db_connection

    async def run(self, query: str) -> str:
        """
        Args:
            query (str): SQL query to execute
        """
        return self.db.execute(query)

2. Define observation

Observation provides context to the agent:

async def observe():
    """Return current state for the agent to see."""
    return [
        f"Current page: {browser.current_url}",
        f"Visible elements: {browser.get_elements()}",
    ]

3. Create and run agent

from dodo import Agent, Gemini

agent = Agent(
    llm=Gemini(),
    tools=[click_button, DatabaseTool(db)],
    observe=observe
)

# Execute workflows
run = await agent.do("click login button and verify")
if run.output:
    print("Workflow succeeded!")

4. Handle errors

from dodo import TaskAbortedError

try:
    await agent.do("impossible task")
except TaskAbortedError as e:
    print(f"Workflow aborted: {e}")

Run Objects

Every do() call returns a Run object with full execution details:

run = await agent.do("complete checkout")

run.output       # Structured output (if output_schema provided)
run.feedback     # Brief summary: "Checkout completed successfully"
run.action_log   # Detailed trace of all actions taken
run.messages     # Full conversation history
run.steps_used   # Number of LLM calls made

Supported LLMs

from dodo import Gemini

# Gemini models
agent = Agent(llm=Gemini(model="gemini-2.0-flash-exp"))
agent = Agent(llm=Gemini(model="gemini-2.5-pro"))

Custom LLM:

from dodo import LLM

class MyLLM(LLM):
    async def call_tools(self, messages, tools):
        # Your LLM implementation
        pass

Examples

  • webtask - Browser automation framework built on dodo

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dodoai-0.1.2.tar.gz (23.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dodoai-0.1.2-py3-none-any.whl (28.2 kB view details)

Uploaded Python 3

File details

Details for the file dodoai-0.1.2.tar.gz.

File metadata

  • Download URL: dodoai-0.1.2.tar.gz
  • Upload date:
  • Size: 23.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for dodoai-0.1.2.tar.gz
Algorithm Hash digest
SHA256 83e9741ac9ec12a517d18120c87751d920feea018397b937bcbb601ba356cee4
MD5 5c05348ff3e190ff97c34dfc04a77519
BLAKE2b-256 39e69af0b7819779b6191e942462b95f35082955274074cdcf4844bf6bf309b7

See more details on using hashes here.

Provenance

The following attestation bundles were made for dodoai-0.1.2.tar.gz:

Publisher: publish.yml on steve-z-wang/dodo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dodoai-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: dodoai-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 28.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for dodoai-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 317a95e11989391dd9067bcc5844aa50094648d7123d9aa3dcdab68b07571f1a
MD5 b6f5901cda6048df080af2ecefbbc3af
BLAKE2b-256 0635ef201c27d25f2a666d2a6e79838cbb6aa81751e9ff74229a3a1e25a1b0d7

See more details on using hashes here.

Provenance

The following attestation bundles were made for dodoai-0.1.2-py3-none-any.whl:

Publisher: publish.yml on steve-z-wang/dodo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page