unleash the power of behavior trees!
41
stars
92
commits
Rust
primary language
Aug 27, 2026
updated
A functionally-oriented language and a fast, typed runtime for behavior trees — built to orchestrate robots and AI agents alike.
Forester is a language and a Rust runtime for describing and executing behavior trees. If you are orchestrating LLM-based agents or reactive hardware, standard DAGs (Directed Acyclic Graphs) and state machines quickly degrade into unmaintainable spaghetti code when handling fallbacks, retries, and error recovery. Behavior trees give you a small, well-understood set of composable primitives (sequence, fallback, decorator) with clean modularity.
A behavior tree separates what your system should decide from how each step gets done. Forester makes that separation cheap: you write the decision logic once in a real language with types and reusable abstractions, and you plug in whatever does the work (a motor controller, a REST call, or an LLM completion).
Tasks run sync or async, local or remote, sequentially or in parallel. Forester handles the scheduling, retries, timeouts, and distribution, keeping your orchestration logic about the logic, not the plumbing.
Add the runtime to your Rust project:
cargo add forester-rs
Install the CLI tool for analysis, simulation, and tracing:
cargo install f-tree
The same core engine and DSL are already used for two quite different jobs, and that's deliberate:
🤖 Robotics & industrial systems Deterministic, safety-critical control flow with real hardware in the loop. Forester ticks reactively, exports to ROS Nav2, and integrates with simulators like Webots, so you can validate a tree against a simulated robot before it ever touches hardware.
🧠 AI agents Structured, inspectable orchestration for LLM-driven systems as an alternative to hand-rolled if/else chains. A tool call or LLM response lands on the Blackboard, and the next node reads it by reference. Because the tree is a real artifact, you get retries, fallbacks, and tracing for free.
Python developers: You do not need to write Rust to use Forester. Use the forester-http-ra-py client to execute your Python LangChain/LlamaIndex tools via HTTP while Forester handles the state and orchestration.
import "std::actions"
root main sequence {
// 1. Check preconditions
fallback {
battery_ok()
navigate_to_charger()
}
// 2. Execute complex logic using a higher-order tree
retryer(
call_llm({"prompt": "analyze_scene"}),
alert_operator()
)
}
// Write the fallback/retry pattern once, reuse it everywhere.
fallback retryer(t: tree, default: tree) {
retry(3) t(..)
default(..)
}
// Define the signatures of the actions executed by your runtime
impl battery_ok();
impl navigate_to_charger();
impl call_llm(config: object);
impl alert_operator();
A few things that aren't typical for a behavior-tree DSL:
You define the logic in .tree files, but you execute the actions in your application language. Here is how you bind the call_llm action to the Rust runtime and tick the tree:
use forester_rs::runtime::action::Action;
use forester_rs::runtime::builder::ForesterBuilder;
// 1. Define your action execution
struct CallLlm;
impl Action for CallLlm {
fn tick(&self, args: ActionArgs) -> TickResult {
// Execute your LLM API call here
TickResult::Success
}
}
fn main() {
// 2. Build the runtime and register the action
let mut runtime = ForesterBuilder::new()
.main_file("main.tree")
.register_sync_action("call_llm", CallLlm)
.build()
.unwrap();
// 3. Run the orchestration
runtime.run().unwrap();
}
| Language | Sequences, fallbacks, parallel, decorators, higher-order trees, lambdas, a typed parameter system |
| Runtime | Sync/async and local/remote task execution, parallelization, retries and timeouts, a Blackboard for shared state |
| Analysis | Visualization, execution tracing, a simulator for testing trees before deployment |
| Integrations | ROS Nav2 export, Webots, remote-action clients (Rust, Python) |
| Tooling | f-tree CLI, IntelliJ plugin |
The full book lives at forester-bt.github.io/learn — language reference, runtime internals, analysis tools, and integrations.
If you are new to behavior trees:
The project is under active development again, and there's plenty of room to help — from language features to integrations to docs.
See CONTRIBUTING.md.
Apache License, Version 2.0. See LICENSE.
Logo by bunny on Freepik.
Rust
99.5%
unleash the power of behavior trees!
41
stars
92
commits
Rust
primary language
Aug 27, 2026
updated
A functionally-oriented language and a fast, typed runtime for behavior trees — built to orchestrate robots and AI agents alike.
Forester is a language and a Rust runtime for describing and executing behavior trees. If you are orchestrating LLM-based agents or reactive hardware, standard DAGs (Directed Acyclic Graphs) and state machines quickly degrade into unmaintainable spaghetti code when handling fallbacks, retries, and error recovery. Behavior trees give you a small, well-understood set of composable primitives (sequence, fallback, decorator) with clean modularity.
A behavior tree separates what your system should decide from how each step gets done. Forester makes that separation cheap: you write the decision logic once in a real language with types and reusable abstractions, and you plug in whatever does the work (a motor controller, a REST call, or an LLM completion).
Tasks run sync or async, local or remote, sequentially or in parallel. Forester handles the scheduling, retries, timeouts, and distribution, keeping your orchestration logic about the logic, not the plumbing.
Add the runtime to your Rust project:
cargo add forester-rs
Install the CLI tool for analysis, simulation, and tracing:
cargo install f-tree
The same core engine and DSL are already used for two quite different jobs, and that's deliberate:
🤖 Robotics & industrial systems Deterministic, safety-critical control flow with real hardware in the loop. Forester ticks reactively, exports to ROS Nav2, and integrates with simulators like Webots, so you can validate a tree against a simulated robot before it ever touches hardware.
🧠 AI agents Structured, inspectable orchestration for LLM-driven systems as an alternative to hand-rolled if/else chains. A tool call or LLM response lands on the Blackboard, and the next node reads it by reference. Because the tree is a real artifact, you get retries, fallbacks, and tracing for free.
Python developers: You do not need to write Rust to use Forester. Use the forester-http-ra-py client to execute your Python LangChain/LlamaIndex tools via HTTP while Forester handles the state and orchestration.
import "std::actions"
root main sequence {
// 1. Check preconditions
fallback {
battery_ok()
navigate_to_charger()
}
// 2. Execute complex logic using a higher-order tree
retryer(
call_llm({"prompt": "analyze_scene"}),
alert_operator()
)
}
// Write the fallback/retry pattern once, reuse it everywhere.
fallback retryer(t: tree, default: tree) {
retry(3) t(..)
default(..)
}
// Define the signatures of the actions executed by your runtime
impl battery_ok();
impl navigate_to_charger();
impl call_llm(config: object);
impl alert_operator();
A few things that aren't typical for a behavior-tree DSL:
You define the logic in .tree files, but you execute the actions in your application language. Here is how you bind the call_llm action to the Rust runtime and tick the tree:
use forester_rs::runtime::action::Action;
use forester_rs::runtime::builder::ForesterBuilder;
// 1. Define your action execution
struct CallLlm;
impl Action for CallLlm {
fn tick(&self, args: ActionArgs) -> TickResult {
// Execute your LLM API call here
TickResult::Success
}
}
fn main() {
// 2. Build the runtime and register the action
let mut runtime = ForesterBuilder::new()
.main_file("main.tree")
.register_sync_action("call_llm", CallLlm)
.build()
.unwrap();
// 3. Run the orchestration
runtime.run().unwrap();
}
| Language | Sequences, fallbacks, parallel, decorators, higher-order trees, lambdas, a typed parameter system |
| Runtime | Sync/async and local/remote task execution, parallelization, retries and timeouts, a Blackboard for shared state |
| Analysis | Visualization, execution tracing, a simulator for testing trees before deployment |
| Integrations | ROS Nav2 export, Webots, remote-action clients (Rust, Python) |
| Tooling | f-tree CLI, IntelliJ plugin |
The full book lives at forester-bt.github.io/learn — language reference, runtime internals, analysis tools, and integrations.
If you are new to behavior trees:
The project is under active development again, and there's plenty of room to help — from language features to integrations to docs.
See CONTRIBUTING.md.
Apache License, Version 2.0. See LICENSE.
Logo by bunny on Freepik.
Rust
99.5%