Jido Behavior Tree

Hex.pmHex DocsCILicenseWebsiteEcosystemDiscord

An Elixir behavior tree implementation designed for Jido agents with integrated action support and AI compatibility.

Features

Installation

Add to your mix.exs:

def deps do
[
{:jido_behaviortree, "~> 1.0"}
]
end

Quick Start

Building a Tree with Actions

alias Jido.BehaviorTree
alias Jido.BehaviorTree.Nodes.{Sequence, Action}
# Define your actions
defmodule MyApp.Actions.ValidateInput do
use Jido.Action,
name: "validate_input",
description: "Validates user input"
def run(params, _context) do
if params[:input] && String.length(params[:input]) > 0 do
{:ok, %{validated: true}}
else
{:error, "Input is required"}
end
end
end
defmodule MyApp.Actions.ProcessData do
use Jido.Action,
name: "process_data",
description: "Processes validated data"
def run(params, _context) do
{:ok, %{processed: String.upcase(params[:input])}}
end
end
# Build the tree
tree = BehaviorTree.new(
Sequence.new([
Action.new(MyApp.Actions.ValidateInput, %{input: "hello"}),
Action.new(MyApp.Actions.ProcessData, %{input: "hello"})
])
)
# Execute
tick = BehaviorTree.tick()
{status, _updated_tree} = BehaviorTree.tick(tree, tick)
# => {:success, %BehaviorTree.Tree{...}}

Agent-based Execution

For stateful execution across multiple ticks:

{:ok, agent} = BehaviorTree.start_agent(
tree: tree,
blackboard: %{user_id: 123},
mode: :manual
)
# Execute ticks
status = BehaviorTree.Agent.tick(agent)
# Access blackboard
BehaviorTree.Agent.put(agent, :result, "success")
value = BehaviorTree.Agent.get(agent, :result)
# Switch to auto mode for continuous execution
BehaviorTree.Agent.set_mode(agent, :auto)

Jido AgentServer Strategy Integration

For full Jido signal routing and directive execution, use the strategy with a Jido.Agent module and run it through Jido.AgentServer:

defmodule MyApp.BTAgent do
use Jido.Agent,
name: "my_bt_agent",
strategy: {Jido.Agent.Strategy.BehaviorTree, tree: tree}
end
{:ok, pid} = Jido.AgentServer.start_link(agent: MyApp.BTAgent)
# Route through strategy signal routes
signal = Jido.Signal.new!("jido.bt.tick", %{}, source: "/myapp")
{:ok, _agent} = Jido.AgentServer.call(pid, signal)

Built-in strategy signals:

Node Types

Composite Nodes

Control the execution flow of multiple children:

NodeBehavior
SequenceExecutes children in order. Fails if any child fails.
SelectorTries children in order until one succeeds.

Decorator Nodes

Modify the behavior of a single child:

NodeBehavior
InverterInverts success/failure of child
SucceederAlways returns success when child completes
FailerAlways returns failure when child completes
RepeatRepeats child N times

Leaf Nodes

Perform actual work:

NodeBehavior
ActionExecutes a Jido Action
WaitWaits for a specified duration
SetBlackboardSets values in the blackboard

The Blackboard

Shared data structure enabling communication between nodes:

# Reference blackboard values in actions
action = Action.new(MyApp.Actions.ProcessData, %{
data: {:from_blackboard, :input_data}
})
# Set values with SetBlackboard node
alias Jido.BehaviorTree.Nodes.SetBlackboard
SetBlackboard.new(:status, :ready)
SetBlackboard.new(%{status: :ready, count: 0})

Node Status

Every node returns one of these statuses:

Telemetry

The library emits telemetry events for monitoring:

Guides

Production Guarantees

Development

# Run tests
mix test
# Run quality checks
mix quality
# Generate docs
mix docs

Integration with Jido

This package integrates with the broader Jido ecosystem:

License

Apache 2.0 - See LICENSE.md


Part of the Jido ecosystem for building autonomous agent systems.