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

Blackboard

The Blackboard is Forester’s shared in-memory state store — a key-value store that nodes read from and write to across ticks. It is the primary mechanism for passing data between actions and tree nodes without tight coupling.

In AI agent workflows, the Blackboard acts as the agent’s working context: LLM responses, tool call results, and session state are written here and read by downstream nodes.


Data Format

The Blackboard stores pairs of String keys and BBValue values:

#![allow(unused)]
fn main() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub enum BBValue {
    Locked(RtValue),    // Key exists and is locked: read-only, no further writes
    Unlocked(RtValue),  // Key exists and is freely readable and writable
    Taken,              // Key slot exists but value has been consumed (taken)
}
}

Key States

StateDescription
Unlocked(RtValue)Normal state. The value can be read, overwritten, or taken by any node.
Locked(RtValue)The value is protected from modification. Other nodes can still read it, but cannot overwrite or take it.
TakenThe key slot exists but its value has been consumed by a take operation.

Accessing the Blackboard from DSL

Use the built-in std::actions to interact with the Blackboard directly from .tree files:

import "std::actions"

root main sequence {
    // Write a value
    store("agent_mode", "active")
    
    // Lock a key to prevent modification during critical section
    lock("agent_mode")
    
    // Read and compare
    equal("agent_mode", "active")
    
    // Unlock when done
    unlock("agent_mode")
}

Accessing the Blackboard from Rust

In Rust action implementations, the Blackboard is accessed through the TreeContextRef:

#![allow(unused)]
fn main() {
use forester_rs::runtime::context::TreeContextRef;
use forester_rs::runtime::action::{Impl, RtArgs, Tick, TickResult};

impl Impl for MyAction {
    fn tick(&self, args: RtArgs, ctx: TreeContextRef) -> Tick {
        let mut ctx = ctx.lock()?;
        
        // Read a value from the Blackboard
        let mode = ctx.bb().get("agent_mode")?.and_then(|v| v.as_string());
        
        // Write a value to the Blackboard
        ctx.bb().put("result", RtValue::String("done".to_string()))?;
        
        Ok(TickResult::success())
    }
}
}

Persistence: Load & Dump

The Blackboard supports JSON serialization for pre-loading initial state and dumping snapshots:

MethodDescription
bb_load(path)Loads initial Blackboard state from a JSON file at engine startup (via ForesterBuilder).
dump(path)Saves a snapshot of the full Blackboard to a JSON file.
print_dump()Prints the current Blackboard snapshot to stdout in JSON format.
text_dump()Returns the Blackboard snapshot as a JSON string.
#![allow(unused)]
fn main() {
// Pre-load state at startup
fb.bb_load("db/initial_state.json".to_string());
}

HTTP Access

When the engine’s built-in HTTP server is enabled, the Blackboard is also accessible over HTTP at runtime. See the Engine HTTP API for endpoint details.


Utilities

A set of helper utilities for common Blackboard operations is available in the blackboard::utils module, for example:

  • blackboard::utils::push_to_arr(key, value, ctx) — Appends a value to an array stored at a given key.