Getting started
A five-minute walkthrough: install abtree, hand a tree to your agent, and watch it drive.
Install
curl -fsSL https://github.com/flying-dice/abtree/releases/latest/download/install.sh | shirm https://github.com/flying-dice/abtree/releases/latest/download/install.ps1 | iexVerify:
abtree --versionYou'll see a version number. If you don't, restart your terminal so the new PATH takes effect.
Concepts in 60 seconds
Three words worth knowing:
- Tree — a YAML file describing a workflow. Lives in
.abtree/trees/. - Flow — one execution of a tree, bound to a piece of work. Persists as JSON in
.abtree/flows/. - Step — the smallest unit. Either an
evaluate(a precondition the agent confirms) or aninstruct(work the agent performs).
abtree is a CLI for agents. You don't drive flows yourself — you hand a brief to your agent and it runs the loop. Three commands carry the whole protocol: abtree next to ask "what now?", abtree eval to answer a precondition, abtree submit to report an outcome. JSON in, JSON out.
1. Set up a workspace
mkdir my-abtree-demo && cd my-abtree-demo
mkdir -p .abtree/trees
curl -fsSL https://raw.githubusercontent.com/flying-dice/abtree/main/.abtree/trees/hello-world.yaml \
-o .abtree/trees/hello-world.yamlhello-world is a small tree: greet a user based on the time of day, then enrich the greeting with weather and news. It exercises all four behaviour-tree primitives in fifteen lines.
2. Hand it off to your agent
In Claude Code, ChatGPT, or any agent that can run shell commands, send:
Run the abtree hello-world flow end-to-end. Start by running
'abtree --help' to learn the execution protocol, then create a
flow with 'abtree flow create hello-world "first run"' and drive
it through every step until you see status: done.That is the entire human-side interaction. The agent reads the protocol from --help, creates a flow, and runs the loop autonomously.
3. What the agent does under the hood
Each turn, the agent calls one command and reads its JSON response.
abtree next first-run__hello-world__1 returns the next step:
{
"type": "instruct",
"name": "Determine_Time",
"instruction": "Check the system clock to get the current hour..."
}The agent does the work — checks the clock, classifies the hour as morning — then writes the result and submits:
abtree local write first-run__hello-world__1 time_of_day "morning"
abtree submit first-run__hello-world__1 successThe next call returns an evaluate:
{
"type": "evaluate",
"name": "Morning_Greeting",
"expression": "$LOCAL.time_of_day is \"morning\""
}The agent reads the expression, decides it holds, and answers:
abtree eval first-run__hello-world__1 trueThe loop repeats — next → do the work or judge the precondition → submit or eval — until:
{ "status": "done" }The agent never sees the rest of the tree. Just the next request.
4. The execution diagram
abtree regenerates a Mermaid diagram at .abtree/flows/first-run__hello-world__1.mermaid after every state change. Here's what a completed hello-world run looks like — green nodes succeeded, uncoloured ones were skipped.
---
title: "hello-world (complete)"
---
flowchart TD
Hello_World{{"Hello World\n[sequence]"}}
0_Determine_Time["Determine Time\n[action]"]
Hello_World --> 0_Determine_Time
style 0_Determine_Time fill:#4ade80,stroke:#16a34a,color:#052e16
0_Choose_Greeting{{"Choose Greeting\n[selector]"}}
Hello_World --> 0_Choose_Greeting
style 0_Choose_Greeting fill:#4ade80,stroke:#16a34a,color:#052e16
0_1_Morning_Greeting["Morning Greeting\n[action]"]
0_Choose_Greeting --> 0_1_Morning_Greeting
style 0_1_Morning_Greeting fill:#4ade80,stroke:#16a34a,color:#052e16
0_1_Afternoon_Greeting["Afternoon Greeting\n[action]"]
0_Choose_Greeting --> 0_1_Afternoon_Greeting
0_1_Evening_Greeting["Evening Greeting\n[action]"]
0_Choose_Greeting --> 0_1_Evening_Greeting
0_1_Default_Greeting["Default Greeting\n[action]"]
0_Choose_Greeting --> 0_1_Default_Greeting
0_Gather_Context{{"Gather Context\n[parallel]"}}
Hello_World --> 0_Gather_Context
style 0_Gather_Context fill:#4ade80,stroke:#16a34a,color:#052e16
0_2_Check_Weather["Check Weather\n[action]"]
0_Gather_Context --> 0_2_Check_Weather
style 0_2_Check_Weather fill:#4ade80,stroke:#16a34a,color:#052e16
0_2_Check_News["Check News\n[action]"]
0_Gather_Context --> 0_2_Check_News
style 0_2_Check_News fill:#4ade80,stroke:#16a34a,color:#052e16
0_Compose_Response["Compose Response\n[action]"]
Hello_World --> 0_Compose_Response
style 0_Compose_Response fill:#4ade80,stroke:#16a34a,color:#052e16The cursor advanced through the sequence. The selector chose Morning Greeting and stopped — the afternoon, evening, and default branches were never entered. Both context-gathering actions ran in parallel. Every action passed its evaluate invariant before its instruct ran.
What just happened
Your agent drove a structured workflow without you writing a system prompt, without a JSON schema in its context, without chain-of-thought. The tree handed it exactly one task at a time, and only let it advance when it proved the task was complete.
That's the core idea: deterministic structure for non-deterministic agents.
Next
- Why behaviour trees? — the problem they solve
- State, branches, and actions — how the building blocks fit together
- Writing your own trees — YAML structure walkthrough
- CLI reference — every command, every flag