A focused behavior-tree engine
Bonsai is not an AI model or a robot framework. It is the decision-structure layer between an application's world state and the actions that application already knows how to perform. A tree is built from actions and control nodes. Each tick walks the structure and returns success, failure, or running, allowing the caller to resume work on the next update. This model suits game characters, robot autonomy, simulations, and workflow-like agents whose priorities and failure paths become hard to read as nested conditionals.
The Rust API keeps the declarative behavior separate from the state of one execution. Multiple agents can share or clone the same compact behavior while each BT instance tracks its own progress and blackboard. Actions are an application-defined type, so the library does not force commands into strings. The blackboard is generic as well: it can be a map, a domain struct, or another context chosen by the caller.
The basic vocabulary covers more than sequence and selector. If, Invert, waits, loops, and an always-succeed decorator handle common control flow. Sequences and selectors can retain their running child or be made memoryless, which restarts evaluation at the first child every tick. That memoryless mode enables priority preemption, such as stopping a chase when a higher-priority attack or safety condition becomes true.
Timing is explicit and deterministic
Bonsai models execution as a discrete event loop. The caller supplies a delta-time update, and an action can return unused time when it finishes. The next node can consume the remainder during the same tick. This is a thoughtful detail for games and simulations because a completed wait does not have to throw away the rest of a frame's time. The library warns that instant actions inside loops can run forever unless a node eventually consumes time.
Its parallel nodes are logical rather than a thread scheduler. WhenAll waits for all children to succeed, WhenAny accepts the first success, Race returns the first completed result, and After requires children to succeed in order. The concepts guide explains that these behaviors are evaluated on a single-threaded discrete update. Two tasks completing within one delta interval are resolved by traversal order, even if a separate physical simulation would consider the other task first.
Long-running actions must return quickly so tree traversal stays responsive. The recommended pattern is to dispatch blocking or asynchronous work to a background thread, communicate through a channel, and let the action report running until a result arrives. The async drone and timeout examples demonstrate that integration. This keeps Bonsai small and runtime-neutral, but an application still owns cancellation, thread safety, resource cleanup, and mapping job failures back into tree status.
Good inspection, limited authoring tools
Version 0.12 introduced a live web inspector. With the optional visualization feature enabled, an application can attach telemetry to a tree, open a local browser view, and watch node statuses and the active path change. The example includes reconnection plus pan and zoom. Bonsai can also produce Graphviz output, which is useful for documentation and tests.
This is inspection, not a graphical editor. Trees are normally composed in Rust or Python, and Rust behaviors can be serialized through Serde. A request to add BehaviorTree.CPP-style XML was closed because the maintainer considers JSON sufficient and allows callers to define another configuration layer around their action type. That decision is sensible for a code-first library, but it rules out a familiar workflow for teams whose designers edit and compose trees outside the application.
The current data model is similarly simple. One generic blackboard is shared through the tree. An open request asks for typed input and output ports on individual nodes because the present monolithic context couples nodes through common state. Other open requests cover preconditions and postconditions, N-of-M success thresholds for parallel children, and decorators such as timeout, retry, repeat, force-failure, and keep-running-until-failure. Some behavior can be assembled from existing nodes, but the missing names affect readability and lifecycle handling.
Rust is the mature path
The main crate has the strongest documentation and examples. The concepts guide explains traversal, state, event timing, parallel behavior, and finite-state-machine tradeoffs. Runnable samples cover a game NPC, memoryless priority behavior, boids, a threaded drone, race timeouts, Graphviz, a 3D animation, and the live visualizer. The examples page also points to uses in a lunar rover project and two game-server projects, evidence that the library has escaped its own demos.
Rust setup is one dependency, with optional Serde and visualization pieces kept out of the default core. Pin the release you test rather than using the wildcard shown in the README. The README also advertises Rust 1.72 or newer while the current crate manifest requires 1.80, so automated minimum-version testing should follow the manifest. Graphical examples may need libudev, pkg-config, and ALSA development packages on Linux.
Python support is a thin wrapper over the Rust semantics. pip install bonsai-bt provides the package for Python 3.10 or newer, and the side-by-side greeting example makes the API translation clear. The Python package reached version 0.13.0 on June 21, 2026, the same day as the current Rust package. Its docs are much smaller, and a JSON serialization example remains open, so Python users should expect to read Rust-oriented concepts and test binding coverage for their intended nodes.
Healthy development, modest scale
The repository's last push was June 21, 2026. The current Rust and Python packages are 0.13.0, while GitHub's latest formal release entry is v0.12.0 from May 14. Issues continued receiving activity in August. All nine open tracker items are issues rather than pull requests, and the recent history shows merged work on Python bindings, live visualization, pan and zoom, real-world examples, and memoryless composites.