A CLI tool that helps agents keep long-running work on a predefined path.
Donna exists because agent work has a control-flow problem:
- Most development work is repetitive on the meta level: "run this tool, do something with the output, run another tool" or "implement function A, implement tests for function A, implement function B, …".
- Some parts of that work require advanced reasoning, others do not.
- Agents are
almostgood at reasoning, but not so good at keeping the whole process in mind, remembering what they did, etc. - Therefore, we should separate the reasoning part from the control flow part — let agents focus on what they are good at, and keep the control flow to traditional automation tools.
Donna runs predefined workflows as deterministic state machines, so the agent can focus on reasoning, code generation, and other agentic work.
You define a workflow in a single readable Markdown file. The agent asks Donna to guide it through the workflow, and Donna keeps the session state, chooses the next operation, and tells the agent what to do or report next.
Workflows can start child workflows, be generated on the fly, or be modified while executing. For example, you can have a workflow that guides the agent through the planning process, and at the final step, the agent can generate a new workflow with a detailed plan to execute and run it immediately.
As a bonus, Donna saves tokens because the agent does not need to reason about control flow or how to execute particular CLI commands and other automation tools.
- Pure CLI tool — No API keys, hosted services, or separate agent instances required.
- Deterministic control flow — Donna follows explicit workflow transitions instead of relying on the agent's memory.
- Agent-aware automation — Scripted steps run automatically; agent work is requested when needed.
- Nested workflows — Workflows can start child workflows, generate new ones, or delegate workflow selection to the agent.
- Readable workflow sources — Each workflow is a single Markdown file with a clear structure.
- Built-in help for agents — Your agent can run
donna skillto get detailed docs written for agents. - Local session state — Workflow progress stays inspectable and resumable inside the project.
- Progress journaling — Workflow progress can be logged through a configured external command.
I use Donna to develop Donna itself — you can find real examples of workflows in the ./workflows folder of this repository. You can start with ./workflows/polish.donna.md that loops over fixing issues found by formatters, linters, type checkers and tests until the codebase is polished.
Below you'll find a simplified workflow that checks the current time, asks the agent whether it is time to drink tea, and branches according to the agent's answer.
Here is its schema:
[Get Current Time]
|
v
[Ask About Tea]
|
+----+----+
| |
yes no
| |
v |
[Turn On |
Kettle] |
| |
+----+----+
|
v
[Finish]
Actual workflow code:
# Is it time to drink tea?
This workflow checks the current time, asks the agent whether it is tea time,
and branches on the answer.
## Get Current Time
```toml donna
id = "get_current_time"
kind = "donna.lib.run_script"
save_stdout_to = "current_time"
goto_on_success = "ask_about_tea"
goto_on_failure = "finish"
```
```bash donna script
#!/usr/bin/env bash
date +%H:%M
```
## Ask About Tea
```toml donna
id = "ask_about_tea"
kind = "donna.lib.request_action"
```
The current time is:
```text
{{ donna.lib.task_variable("current_time") }}
```
Is it time to drink tea?
1. If yes, `{{ donna.lib.goto("turn_on_kettle") }}`.
2. If no, `{{ donna.lib.goto("finish") }}`.
## Turn On Kettle
```toml donna
id = "turn_on_kettle"
kind = "donna.lib.request_action"
```
Turn on the kettle, then `{{ donna.lib.goto("finish") }}`.
## Finish
```toml donna
id = "finish"
kind = "donna.lib.finish"
```
The workflow is complete. You are a good butler.How it works
How to read workflow's source:
- The H1 section is the workflow section. It gives Donna the workflow title and summary that appear in
donna list. - Each H2 section is an operation section. Donna runs operations in the order selected by the workflow state machine.
toml donnablocks configure section id, type and behavior. Here, the operation types aredonna.lib.run_script,donna.lib.request_action, anddonna.lib.finish.Get Current Timeis arun_scriptoperation. Donna runs the shell script from the project root, saves stdout ascurrent_time, and moves toask_about_teaon success. No agent interaction required here, because it is pure deterministic work.Ask About Teais arequest_actionoperation. The agent will see a request for action with the rendered current time, the question, and the two allowed transitions:turn_on_kettleorfinish.donna.lib.task_variable("current_time")is rendered as the value captured from the script output.donna.lib.goto(...)is rendered as a concrete CLI command to execute.Turn On Kettleis anotherrequest_actionoperation. The agent will see the instruction to turn on the kettle and then complete the action request with thefinishtransition.Finishis afinishoperation. The agent will see the final workflow message, and Donna will complete the workflow task.
Here is an example of action request for the Get Current Time operation:
--DONNA-CELL OuP2T9brQYmvESMHsbrDlw BEGIN--
kind=session_state_status
media_type=text/markdown
pending_action_requests=1
queued_work_units=0
tasks=1
The session is AWAITING YOUR ACTION. You have pending action requests to address.
- If the developer asked you to start working on a new task, you MUST ask if you should start a new session
or continue working on the current action requests.
- Otherwise, you MUST address the pending action requests before proceeding.
--DONNA-CELL OuP2T9brQYmvESMHsbrDlw END--
--DONNA-CELL fxh3PDZ1Qy-c3zvai_T5Qw BEGIN--
kind=action_request
media_type=text/markdown
action_request_id=AR-11-l
**This is an action request for the agent. You MUST follow the instructions below.**
The current time is:
```text
19:31
```
Is it time to drink tea?
1. If yes, `donna -p llm --config '/home/tiendil/repos/mine/donna/.session/readme-example-test/donna.toml' complete-action-request <action-request-id> '@/workflows/tea.donna.md:turn_on_kettle'`.
1. If no, `donna -p llm --config '/home/tiendil/repos/mine/donna/.session/readme-example-test/donna.toml' complete-action-request <action-request-id> '@/workflows/tea.donna.md:finish'`.
--DONNA-CELL fxh3PDZ1Qy-c3zvai_T5Qw END--
Since Donna is a CLI tool, you can run the workflow manually in the terminal.
uv tool install donna
# Example workflow is a part of Donna repository
# git clone git@github.com:Tiendil/donna.git
# cd donna
donna run @/workflows/examples/time_to_drink_tea.donna.md
# Follow Donna commands to finish the workflow.uv tool install donna
# or
# python -m pip install donnaAsk your agent to initialize Donna in the project:
1. Run `donna skill`
2. Initialize Donna in this project.
3. Add instructions on when and how to use Donna to the AGENTS.md file.
Or install Donna manually:
# from the root of your project
donna initdonna init will create a configuration file donna.toml, review it and edit if needed.
You can get detailed documentation by running donna skill configuration or asking your agent to do that.
A Donna project is configured by a TOML file named donna.toml. If --config is omitted, Donna searches upward from the current working directory until it finds donna.toml; the directory containing that file is the project root.
Minimal configuration:
version = 1The starter configuration generated by donna init includes the default session directory and workflow discovery directories:
version = 1
session_dir = ".session/donna"
workflow_dirs = [
"./workflows",
"./.session/donna",
]A coding agent can help create or adapt workflow files after the project layout and desired workflows are clear.
The session directory stores Donna runtime state. Workflow directories are scanned recursively for .donna.md files; missing workflow directories are ignored.
Detailed configuration behavior is specified in ./specs/behavior/config.md. Command behavior is specified in ./specs/behavior/cli.md.
Project agent instructions can include a short Donna rule like this:
Use Donna only when explicitly instructed by a developer, by project instructions, or by Donna itself.
Before using Donna in a session, read `donna -p llm skill usage`.
Use `donna -p llm ...` for agent-facing command output.In most cases your agent should be capable of using Donna by itself without your intervention.
You can get detailed documentation by running donna skill usage or asking your agent to do that.
Detailed CLI interface is described in ./specs/behavior/cli.md.
Create a starter configuration:
donna initList discovered workflow artifacts:
donna listStart a new session:
donna new-sessionStart a workflow in the current session:
donna run @/workflows/polish.donna.mdInspect the current session:
donna statusContinue queued workflow execution:
donna continueComplete an action request with the id and next operation printed by Donna:
donna complete-action-request <action-request-id> @/workflows/example.donna.md:next_operationRead the built-in usage documentation:
donna skill usageIn most cases your agent should be capable of creating and managing workflows by itself without your intervention.
You can get detailed documentation by running donna skill workflows or asking your agent to do that.
Donna workflow artifacts are Markdown files ending with .donna.md. Donna discovers them by recursively scanning the configured workflow_dirs.
A workflow file has one H1 section for the workflow and H2 sections for operations. Section config is written in fenced toml donna code blocks. Transitions are declared in operation config or request text, depending on the operation kind, and validated before execution.
Common built-in operation kinds:
donna.lib.request_actionpauses and asks the agent to perform work.donna.lib.run_scriptruns a deterministic shell script from the project root.donna.lib.outputprints information and continues.donna.lib.finishfinishes the workflow task.
Workflow text can use directives such as donna.lib.goto(...) for transitions, donna.lib.task_variable(...) for captured script output, and donna.lib.path(...) for normalized project paths.
Project behavior and architecture are specified in ./specs. Start with ./specs/intro.md for the index.
Development commands are run through Docker-backed project scripts.
Run the full test suite:
./bin/dev-tests.shRun a specific development command inside the project container:
./bin/dev.sh uv run pytestRun Donna from the current development checkout:
./bin/dev.sh uv run donna --helpThe repository also uses Donna itself. Its local workflows live in ./workflows, and the current project configuration is donna.toml.
Check AGENTS.md for the list of additional tools that agents will expect to be installed.