Jido. BehaviorTree. Node behaviour
(Jido Behavior Tree v1.0.0)
View Source
Defines the behavior for all behavior tree nodes.
Every node in a behavior tree must implement this behavior to define how it responds to ticks and how it can be halted when necessary.
Node Types
There are three main categories of nodes:
Composite Nodes - Control the execution of multiple child nodes
- Sequence: Execute children in order until one fails
- Selector: Execute children in order until one succeeds
Decorator Nodes - Modify the behavior of a single child node
- Inverter: Invert the child's success/failure status
- Succeeder: Convert completion to success
- Failer: Convert completion to failure
- Repeat: Repeat the child a specified number of times
Leaf Nodes - Perform actual work or conditions
- Action: Execute a Jido action
- Wait: Pause execution for a duration
- SetBlackboard: Write values into the tick blackboard
Implementation
When implementing a node, you define a struct to hold the node's state and implement the two required callbacks:
defmodule MyNode do
@schema Zoi.struct(
__MODULE__,
%{
my_data: Zoi.any(description: "Custom node data") |> Zoi.optional()
},
coerce: true
)
@type t :: unquote(Zoi.type_spec(@schema))
@enforce_keys Zoi.Struct.enforce_keys(@schema)
defstruct Zoi.Struct.struct_fields(@schema)
def schema, do: @schema
@behaviour Jido.BehaviorTree.Node
@impl true
def tick(node_state, tick) do
# Your tick logic here
{:success, updated_node_state}
end
@impl true
def halt(node_state) do
# Your halt logic here
updated_node_state
end
endTelemetry
Behavior tree nodes emit telemetry events via Jido.Observe for observability.
Events use the [:jido, :bt, :node, ...] namespace to align with core Jido telemetry.
Node Tick Events
[:jido, :bt, :node, :tick, :start]- Node tick started[:jido, :bt, :node, :tick, :stop]- Node tick completed[:jido, :bt, :node, :tick, :exception]- Node tick raised an exception
Node Halt Events
[:jido, :bt, :node, :halt, :start]- Node halt started[:jido, :bt, :node, :halt, :stop]- Node halt completed[:jido, :bt, :node, :halt, :exception]- Node halt raised an exception
Metadata
All events include the following metadata:
:node- The node module being executed:sequence- The tick sequence number (for tick events)
When running as a Jido strategy, additional metadata is included from Tick.context:
:agent_id- The agent's unique identifier:agent_module- The agent module name:strategy- The strategy module name
Measurements
:duration- Execution time in nanoseconds (on:stopand:exception):system_time- Start timestamp in nanoseconds (on:start)
Summary
Functions
Halts the given node with telemetry.
Executes a tick on the given node with telemetry.
Executes a tick with context, threading tick through the node.
Checks if a value implements the Node behavior.
Types
@type t() :: struct()
Any struct that represents a behavior tree node
Callbacks
Halts the execution of the node.
This callback is called when the node needs to stop execution, typically when a parent node has completed or the entire tree is being stopped.
The node should clean up any resources, cancel any ongoing operations, and return to a clean state.
Parameters
node_state- The current state of this node
Returns
The updated node state after halting
Examples
def halt(node_state) do
# Cancel any timers, close connections, etc.
cancel_timer(node_state.timer)
%{node_state | timer: nil, status: :halted}
end
@callback tick(node_state :: t(), tick :: Jido.BehaviorTree.Tick.t()) :: {Jido.BehaviorTree.Status.t(), t()}
Executes a single tick of the node.
This callback is called when the behavior tree is executed and this node is reached. The node should perform its logic and return a status along with any updated state.
Parameters
node_state- The current state of this nodetick- The current tick context containing blackboard and timing info
Returns
A tuple containing:
- The status of the node execution (
:success,:failure,:running, or{:error, reason}) - The updated node state (which may be unchanged)
Examples
def tick(node_state, tick) do
case perform_work(node_state, tick) do
{:ok, result} ->
{:success, %{node_state | result: result}}
{:error, reason} ->
{{:error, reason}, node_state}
end
end
Functions
Halts the given node with telemetry.
This function wraps the node's halt callback with telemetry events
via Jido.Observe and error handling.
Examples
updated_node = Jido.BehaviorTree.Node.execute_halt(node)
@spec execute_tick(t(), Jido.BehaviorTree.Tick.t()) :: {Jido.BehaviorTree.Status.t(), t()}
Executes a tick on the given node with telemetry.
This function wraps the node's tick callback with telemetry events
via Jido.Observe and error handling.
Examples
{status, updated_node} = Jido.BehaviorTree.Node.execute_tick(node, tick)
@spec execute_tick_with_context(t(), Jido.BehaviorTree.Tick.t()) :: {Jido.BehaviorTree.Status.t(), t(), Jido.BehaviorTree.Tick.t()}
Executes a tick with context, threading tick through the node.
This variant is used by the BehaviorTree strategy to pass agent state and collect directives. It returns a 3-tuple including the updated tick.
For nodes that implement tick_with_context/2, that callback is used.
Otherwise, the standard tick/2 is called and tick is passed through unchanged.
Examples
{status, updated_node, updated_tick} = Node.execute_tick_with_context(node, tick)
Checks if a value implements the Node behavior.
Examples
iex> Jido.BehaviorTree.Node.node?(%Jido.BehaviorTree.Nodes.Action{})
true
iex> Jido.BehaviorTree.Node.node?("not a node")
false