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/. - Execution — one run of a tree, bound to a piece of work. Persists as JSON in
.abtree/executions/. - 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 executions 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 tree end-to-end. Start by running
'abtree --help' to learn the execution protocol, then create an
execution with 'abtree execution 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 an execution, 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/executions/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