Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Engine Internals

The Forester engine is the central execution runtime. It drives the tick loop, manages node state, dispatches actions, and coordinates the Blackboard, ActionKeeper, and optional tracer.


Internal Components

ComponentDescription
Engine CoreManages the tree node graph, drives the tick loop, and handles state transitions (Running, Success, Failure).
BlackboardIn-memory shared key-value store for passing state between nodes.
ActionKeeperRegistry mapping impl action names to Rust handlers or remote action clients.
TracerOptional execution logger that records tick-by-tick node evaluations for debugging and replay.

Tick Loop

On each tick, the engine traverses the tree from the root node down, evaluating each node according to its type (sequence, fallback, parallel, decorator, or action). The tick loop continues until the root node returns Success or Failure.

Bounded Execution

To prevent infinite loops and enable time-boxed execution (useful for simulation or testing), the tick count can be capped:

#![allow(unused)]
fn main() {
// Run for a maximum of 100 ticks
forester.run_until(Some(100)).unwrap();

// Run until the root returns Success or Failure (unbounded)
forester.run().unwrap();
}

Runtime Environment

The engine uses Tokio as its async runtime to schedule and parallelize async action execution.

By default, the engine creates its own Tokio runtime. If the engine is embedded in an application that already has a Tokio runtime, it can be provided via ForesterBuilder:

use forester_rs::runtime::builder::ForesterBuilder;
use forester_rs::tracer::Tracer;
use forester_rs::runtime::action::Action;
use forester_rs::runtime::action::builtin::data::StoreData;

fn main() {
    let mut fb = ForesterBuilder::from_file_system();
    fb.main_file("main.tree".to_string());
    fb.register_action("store", Action::sync(StoreData));
    fb.tracer(Tracer::default());
    fb.bb_load("db/initial_state.json".to_string());

    let mut forester = fb.build().unwrap();

    // Unbounded run
    let result = forester.run().unwrap();
    println!("Result: {:?}", result);
}

Built-In HTTP Server

The engine optionally exposes an HTTP server during tree execution. This enables external processes — including remote action servers and monitoring tools — to interact with the Blackboard and tracer at runtime.

Enable it by specifying a port in ForesterBuilder:

#![allow(unused)]
fn main() {
fb.http_serv(10000);
}

Note: The HTTP server shuts down automatically when the root tree finishes execution.

HTTP API Endpoints

MethodEndpointDescription
GET/Health check. Returns Ok.
GET/tracer/printPrints current tracer output.
POST/tracer/customAppends a custom event to the tracer log (body: CustomEvent JSON).
GET/bb/:keyReads value at key from the Blackboard.
POST/bb/:keyWrites a value to key in the Blackboard (body: RtValue JSON).
GET/bb/:key/takeReads and removes key from the Blackboard.
GET/bb/:key/lockLocks key to prevent concurrent writes.
GET/bb/:key/unlockUnlocks key.
GET/bb/:key/lockedReturns whether key is currently locked.
GET/bb/:key/containsReturns whether key exists in the Blackboard.