Library / SDK
BehaviorTree/BehaviorTree.CPP avatar
BehaviorTree/BehaviorTree.CPP

BehaviorTree.CPP: XML-Defined Behavior Trees for C++ Robotics and Game AI

Behavior Trees Library in C++. Batteries included.

4,206 stars856 forksC++MIT

At a glance

What is it?
BehaviorTree.CPP is a C++17 library that separates tree structure from node implementation, loading XML trees at run time and treating asynchronous actions as first-class. It fits robotics and game AI teams that need reactive coordination, not a quick scripting fix.
Who is it for?
Adopt BehaviorTree.CPP if your team already writes C++17 and needs trees that change without recompiling, especially on ROS2 where colcon and ament are supported. Skip it if you want a small header-only state machine or a Python-first workflow, since the build pulls in conan, CMake 3.23 or newer, and a plugin toolchain.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 18 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 17, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem: coordination logic that keeps changing

A robot arm that must pick a part, retry on a failed grasp, and abort if the operator opens a safety door is not hard to write once. It is hard to keep correct after the twentieth revision, when the retry policy moves, a new sensor check is inserted, and the abort condition has to win over everything else. Finite state machines express this as transitions, and the transition table grows faster than the behavior does.

BehaviorTree.CPP targets that maintenance problem. The README states the library was designed to be flexible, easy to use, reactive and fast, and that its main use case is robotics, though it also names AI for games and replacing finite state machines. The intended user is a C++ developer on a team where the control policy is edited by more than one person, and where the edit should not require a rebuild of the whole application.

That last point is the design bet. Trees are defined in an XML-based scripting language and loaded at run time, so the morphology of the tree is not hard-coded even though the nodes are C++. A behavior change becomes a file change plus a reload, and the C++ side only grows when a genuinely new capability appears.

How the tree, the blackboard and the plugins fit together

The architecture has three visible layers. At the bottom are TreeNodes written in C++, either statically linked or built as plugins and loaded at run time. Above them sits the XML description, which names the node types, arranges them into control-flow structures, and passes parameters. Between the two is the blackboard, a type-safe mechanism for dataflow between nodes, which the README lists as a distinct feature.

The README also calls asynchronous, non-blocking actions a first-class citizen. That matters because a real action, such as moving a base or waiting on a sensor, does not finish inside one tick. A node returns a running state, the tree continues ticking, and other branches can make progress. The README describes this as reactive behavior that executes multiple actions concurrently, which it calls orthogonality.

Control flow comes from the standard node vocabulary. A Sequence runs children in order and stops on the first failure. A Fallback tries children until one succeeds, which is how retry and recovery branches are usually expressed. Decorators wrap a single child and modify its result. The examples directory shows the range of the API: t04_reactive_sequence.cpp for reactivity, t06_subtree_port_remapping.cpp for subtree ports, t16_global_blackboard.cpp for shared state, and t18_waypoints.cpp for a longer worked case.

Two supporting tools sit outside the core. Groot2 is the graphical editor the README points to for people who do not want to hand-edit XML. The logging and profiling infrastructure is described as allowing a user to visualize, record, replay, and analyze state transitions, and one example, ex03_sqlite_log.cpp, shows a SQLite-backed logger.

Building BehaviorTree.CPP from source with conan

The library requires a compiler that supports C++17. The README lists three supported build systems: colcon with ament if you use ROS2, conan otherwise on Linux and Windows, and straight CMake if you accept responsibility for dependencies yourself. Conan builds need CMake 3.23 or newer, which the README marks with a note.

Assuming you are in the root directory of the repository, the conan path is three commands. The first resolves and builds dependencies, the second configures the preset that conan generated, and the third compiles.

bash
conan install . -s build_type=Release --build=missing
cmake --preset conan-release
cmake --build --preset conan-release

If ZeroMQ and SQLite are already installed on your system and you would rather not involve conan, the README gives a plain CMake route. Note that this path expects those dependencies to be present before you start.

bash
mkdir build_release
cmake -S . -B build_release
cmake --build build_release --parallel

There is also a pixi route for a conda virtual environment. The README shows a single command, and the repository carries both pixi.toml and pixi.lock, so the environment is pinned.

bash
pixi run build

For consuming the library in your own application rather than building the repository, the README points at a separate sample project, https://github.com/BehaviorTree/btcpp_sample. That is the place to look for the CMake integration, not the main README.

Installing BehaviorTree.CPP with vcpkg

If you already use vcpkg as a dependency manager, the README documents an alternative install path that avoids building the repository by hand. The port is named behaviortree-cpp. The README notes that the port is kept up to date by Microsoft team members and community contributors, and asks users to file an issue or pull request on the vcpkg repository if the version is out of date.

bash
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install behaviortree-cpp

After this, the package is available to your build through vcpkg's integration. The practical consequence is that the version you get is whatever the port pins, which may lag the 4.9.0 release from 2026-02-11. If you need a specific release, the conan or CMake paths build from the source tree you checked out.

A first tree: what the examples actually demonstrate

The tutorials are numbered and each one isolates a single concept, which is a sensible way to learn the API. t01_build_your_first_tree.cpp is the starting point. t02_basic_ports.cpp and t03_generic_ports.cpp cover how values move in and out of nodes. t05_crossdoor.cpp is the classic recovery example, where a door that will not open triggers a fallback branch.

The sequence worth following in order is t01, then t04_reactive_sequence.cpp, then t16_global_blackboard.cpp. The first teaches the node registration and tick loop, the second shows why a running action does not block the rest of the tree, and the third shows how shared state is read across branches. After that, t06_subtree_port_remapping.cpp explains how a subtree's ports are bound from the parent, which is the part most teams get wrong on the first attempt.

Two examples exist purely for testing. t15_nodes_mocking.cpp and t15_nodes_mocking_strict_failure.cpp show how to substitute node behavior in tests. That is a genuine advantage over hand-rolled state machines, where testing a transition usually means running the whole system. The mocking examples are the ones to read if you care about unit-testing control logic.

For a graphical view, t11_groot_howto.cpp is the bridge to Groot2. The README's own position is that editing XML in a text editor is sufficient, and Groot2 is optional. Teams that expect a visual editor to be part of the workflow should confirm the Groot2 licensing terms separately, since the README only links to it.

Where BehaviorTree.CPP is the wrong choice

The build cost is real. A C++17 toolchain, a dependency manager, and a plugin loading path are a lot of machinery if your coordination logic is a dozen states that rarely change. A plain switch statement or a small state machine library will be easier to review and to hand to a new engineer.

The XML layer is also a second language to maintain. Node types are registered in C++ and referenced by name in XML, so a rename has to be consistent in both places. Nothing in the README describes a compile-time check that catches a typo in a node name before the tree is loaded, which means malformed trees surface at load or run time. The 4.8.4 release notes explicitly warn that the new validation rules might be a breaking change, so teams upgrading across that boundary should expect existing XML to be rejected.

Version 3.8 lives on a separate branch. The README states that branch might receive bug fixes but that new features go only to master, and the repository ships a convert_v3_to_v4.py script, which tells you the migration is non-trivial enough to need tooling. If you are starting fresh, start on 4.x. If you have a large 3.8 tree, budget for the conversion.

Finally, the library is C++. If your team is Python-first, the integration cost is the whole build chain, not just an import. The README documents no Python binding, and the pyproject.toml in the repository only configures codespell.

Alternatives and how they differ

The most direct comparison is a finite state machine, which the README itself names as the thing BehaviorTree.CPP can replace. The difference is structural. An FSM encodes transitions, so adding a condition that must preempt everything means touching many transitions. A behavior tree encodes priority in the tree shape, so a high-priority abort branch is a new node near the root. The cost is that a tree can hide which states are reachable, and reading a large XML file top to bottom is not the same as reading a transition diagram.

A second alternative is writing the coordination logic directly in C++ with coroutines or a hand-rolled scheduler. That gives full control and no XML, but you lose run-time reloading and the logging infrastructure. The README's claim that tree morphology is not hard-coded is exactly what this approach gives up.

Within the behavior tree space, the README positions this implementation around asynchronous actions, reactive concurrency, run-time XML loading, plugin-based nodes, typed dataflow, and logging. If those six properties are not all needed, a smaller tree library with only synchronous nodes will be less to learn. The distinguishing feature to test first is the async action model, because that is what shapes the rest of the API.

Maintenance, licensing and what to check before upgrading

The repository is not archived, and the last push was on 2026-08-31. Releases in the recent sequence are 4.9.0 on 2026-02-11, 4.8.4 on 2026-01-09, and 4.8.3 on 2025-12-30. The 4.9.0 notes mention 60 issues fixed and a new TryCatch node. The 4.8.4 notes flag the new validation rules as a possible breaking change, and 4.8.3 is described as a linting release. The cadence suggests the project is being maintained, though the README does not publish a support window or a deprecation policy.

The licence is MIT, with copyright held by Davide Faconti and earlier contributors including Eurecat and Michele Colledanchise. MIT permits use, modification, distribution and sublicensing provided the copyright notice and permission notice are included. That is permissive enough for closed-source products, but the repository does not state a contributor licence agreement, so if you plan to upstream patches, check CONTRIBUTORS_GUIDE.md for the process. This is a description of the licence text, not legal advice.

Commercial support is available. The README directs commercial users to contact the primary author at dfaconti@aurynrobotics.com to discuss technical support or consulting. That is worth noting because the community forum is the GitHub Discussions link, and there is no stated response-time commitment there.

For upgrades, the concrete risks are the 4.8.4 validation rules and the 3.8 to 4.x conversion. Run the convert_v3_to_v4.py script if you are coming from 3.8, and load every tree in your test suite against the target version before merging, since validation failures appear at load time rather than at compile time.

Editorial conclusion

Adopt BehaviorTree.CPP if your team already writes C++17 and needs trees that change without recompiling, especially on ROS2 where colcon and ament are supported. Skip it if you want a small header-only state machine or a Python-first workflow, since the build pulls in conan, CMake 3.23 or newer, and a plugin toolchain. Before committing, verify that the 4.8.4 validation rules do not reject your existing XML, and check whether the vcpkg port carries the 4.9.0 release.

Frequently asked questions

How do I install BehaviorTree.CPP?

The README documents three build systems: colcon with ament for ROS2, conan for Linux and Windows, and plain CMake if you manage dependencies yourself. Conan builds need CMake 3.23 or newer. A vcpkg port named behaviortree-cpp is also documented.

Does BehaviorTree.CPP work with ROS2?

Yes. The README lists colcon with ament as one of the three supported build systems and links a ROS2 continuous integration workflow badge. The package.xml file in the repository root is consistent with a ROS package layout.

What is the blackboard in BehaviorTree.CPP?

The README describes it as a type-safe and flexible mechanism to do dataflow between nodes of the tree. It is listed as one of the features that distinguish this implementation. A global blackboard variant appears in examples/t16_global_blackboard.cpp.

Do I need Groot2 to edit BehaviorTree.CPP trees?

No. The README states that editing a behavior tree is as simple as editing an XML file in a text editor, and points to Groot2 only if you want a graphical interface. Groot2 is a separate download linked from the project homepage.

Can I still use BehaviorTree.CPP version 3.8?

The README says version 3.8 can be found on the v3.8 branch, and that branch might receive bug fixes while new features go only to master. The repository includes a convert_v3_to_v4.py script for migrating trees.

Official sources

  1. BehaviorTree/BehaviorTree.CPP on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Community notes

Community notes