SF
STS Forge

AI Systems

BehaviorTree and Blackboard verbs: bt-list, bt-add-node, bt-add-decorator, bb-add-key, and more.

Part of the BlueprintAIAssistant AI Reference.

Verbs for reading and editing BehaviorTree assets and their associated BlackboardData. BehaviorTrees define AI decision logic as composites (Selector, Sequence), tasks (MoveTo, Wait), decorators, and services. BlackboardData assets hold the key definitions that BT nodes read and write at runtime.

All verbs return JSON. On success: "success": true. On failure: "success": false with "error", "errorCode", "suggestion", and "details" fields.

Global optional flags: -compile, -save, -timing.


Table of Contents#

BehaviorTree (5 verbs)

  1. bt-list: List the node tree structure
  2. bt-add-node: Add a task or composite node
  3. bt-add-decorator: Add a decorator to a node
  4. bt-add-service: Add a service to a node
  5. bt-set-property: Set a property on a BT node

Blackboard (3 verbs) 6. bb-list-keys: List all keys in a BlackboardData asset 7. bb-add-key: Add a key to a BlackboardData asset 8. bb-remove-key: Remove a key from a BlackboardData asset


BehaviorTree verbs#

bt-list#

List the node tree structure of a BehaviorTree asset. Returns composites, tasks, decorators, and services in a hierarchical tree.

Category: Read

Args:

Arg Required Description
-asset= Yes BehaviorTree asset path (e.g., /Game/AI/BT_EnemyMain)

Examples:

# List the full tree structure
-verb=bt-list -asset=/Game/AI/BT_EnemyMain

HTTP:

curl -X POST http://localhost:7850/baa/v1/execute \
  -H "Content-Type: application/json" \
  -d '{"verb":"bt-list","args":{"asset":"/Game/AI/BT_EnemyMain"}}'

Output:

{
    "success": true,
    "asset": "/Game/AI/BT_EnemyMain",
    "root": {
        "index": 0,
        "type": "Selector",
        "decorators": [],
        "services": [],
        "children": [
            {
                "index": 1,
                "type": "Sequence",
                "decorators": [
                    {"type": "BTDecorator_Blackboard", "key": "TargetActor"}
                ],
                "services": [
                    {"type": "BTService_BlackboardBase"}
                ],
                "children": [
                    {"index": 2, "type": "BTTask_MoveTo"},
                    {"index": 3, "type": "BTTask_Wait"}
                ]
            }
        ]
    }
}

bt-add-node#

Add a task or composite node to a BehaviorTree.

Category: Write

Args:

Arg Required Description
-asset= Yes BehaviorTree asset path
-type= Yes Node type. Composites: Selector, Sequence, SimpleParallel. Tasks: MoveTo, Wait, RunBehavior, RunEQS, or any custom class name (e.g., BTTask_MyCustomTask)
-parent= No Parent composite index (defaults to 0 = root). Use indices from bt-list output
-index= No Insertion index within the parent's children. Omit to append at the end

Examples:

# Add a Sequence under the root Selector
-verb=bt-add-node -asset=/Game/AI/BT_EnemyMain -type=Sequence -parent=0

# Add a MoveTo task under composite index 1
-verb=bt-add-node -asset=/Game/AI/BT_EnemyMain -type=MoveTo -parent=1 -save

# Add a Wait task at a specific child position
-verb=bt-add-node -asset=/Game/AI/BT_EnemyMain -type=Wait -parent=1 -index=0 -save

# Add a custom task class
-verb=bt-add-node -asset=/Game/AI/BT_EnemyMain -type=BTTask_FindCover -parent=1 -save

HTTP:

curl -X POST http://localhost:7850/baa/v1/execute \
  -H "Content-Type: application/json" \
  -d '{"verb":"bt-add-node","args":{"asset":"/Game/AI/BT_EnemyMain","type":"Sequence","parent":"0"}}'

Output:

{
    "success": true,
    "action": "created",
    "node": {
        "index": 4,
        "type": "BTComposite_Sequence",
        "parentIndex": 0
    }
}

bt-add-decorator#

Add a decorator to a BehaviorTree node. Decorators are conditions or modifiers attached to a composite's child slot.

Category: Write

Args:

Arg Required Description
-asset= Yes BehaviorTree asset path
-node= Yes Composite index to decorate (from bt-list output)
-childIndex= Yes Which child slot to decorate (0-based)
-type= Yes Decorator type: Blackboard, ConeCheck, Cooldown, ForceSuccess, Loop, or any custom class name (e.g., BTDecorator_MyCondition)

Examples:

# Add a Blackboard decorator checking a key
-verb=bt-add-decorator -asset=/Game/AI/BT_EnemyMain -node=0 -childIndex=0 -type=Blackboard -save

# Add a Cooldown decorator
-verb=bt-add-decorator -asset=/Game/AI/BT_EnemyMain -node=1 -childIndex=1 -type=Cooldown -save

# Add a custom decorator
-verb=bt-add-decorator -asset=/Game/AI/BT_EnemyMain -node=0 -childIndex=0 -type=BTDecorator_IsInCombat -save

HTTP:

curl -X POST http://localhost:7850/baa/v1/execute \
  -H "Content-Type: application/json" \
  -d '{"verb":"bt-add-decorator","args":{"asset":"/Game/AI/BT_EnemyMain","node":"0","childIndex":"0","type":"Blackboard"}}'

Output:

{
    "success": true,
    "action": "created",
    "decorator": {
        "type": "BTDecorator_Blackboard",
        "nodeIndex": 0,
        "childIndex": 0
    }
}

bt-add-service#

Add a service to a BehaviorTree composite node. Services run periodically while their composite is active (e.g., updating the blackboard with perception data).

Category: Write

Args:

Arg Required Description
-asset= Yes BehaviorTree asset path
-node= Yes Composite index to attach the service to
-type= Yes Service type: BlackboardBase, DefaultFocus, or any custom class name (e.g., BTService_UpdateCombatInfo)

Examples:

# Add a BlackboardBase service to the root
-verb=bt-add-service -asset=/Game/AI/BT_EnemyMain -node=0 -type=BlackboardBase -save

# Add a DefaultFocus service
-verb=bt-add-service -asset=/Game/AI/BT_EnemyMain -node=1 -type=DefaultFocus -save

# Add a custom service
-verb=bt-add-service -asset=/Game/AI/BT_EnemyMain -node=0 -type=BTService_UpdateThreat -save

HTTP:

curl -X POST http://localhost:7850/baa/v1/execute \
  -H "Content-Type: application/json" \
  -d '{"verb":"bt-add-service","args":{"asset":"/Game/AI/BT_EnemyMain","node":"0","type":"BlackboardBase"}}'

Output:

{
    "success": true,
    "action": "created",
    "service": {
        "type": "BTService_BlackboardBase",
        "nodeIndex": 0
    }
}

bt-set-property#

Set a property on a BehaviorTree node via UE reflection. Supports dot notation for nested properties (e.g., BlackboardKey.SelectedKeyName).

Category: Write

Args:

Arg Required Description
-asset= Yes BehaviorTree asset path
-node= Yes Composite index or root
-property= Yes Property name. Supports dot notation for nested properties
-value= Yes Value as string (parsed by UE property import)

Examples:

# Set the WaitTime on a Wait task
-verb=bt-set-property -asset=/Game/AI/BT_EnemyMain -node=3 -property=WaitTime -value=2.5 -save

# Set the Blackboard key on a decorator (dot notation)
-verb=bt-set-property -asset=/Game/AI/BT_EnemyMain -node=1 -property=BlackboardKey.SelectedKeyName -value=TargetActor -save

# Set AcceptableRadius on a MoveTo task
-verb=bt-set-property -asset=/Game/AI/BT_EnemyMain -node=2 -property=AcceptableRadius -value=150.0 -save

# Set a boolean property
-verb=bt-set-property -asset=/Game/AI/BT_EnemyMain -node=2 -property=bAllowStrafe -value=true -save

HTTP:

curl -X POST http://localhost:7850/baa/v1/execute \
  -H "Content-Type: application/json" \
  -d '{"verb":"bt-set-property","args":{"asset":"/Game/AI/BT_EnemyMain","node":"3","property":"WaitTime","value":"2.5"}}'

Output:

{
    "success": true,
    "node": 3,
    "property": "WaitTime",
    "oldValue": "5.0",
    "newValue": "2.5"
}

Blackboard verbs#

bb-list-keys#

List all keys defined in a BlackboardData asset, including their types and any base class constraints.

Category: Read

Args:

Arg Required Description
-asset= Yes BlackboardData asset path (e.g., /Game/AI/BB_EnemyData)

Examples:

-verb=bb-list-keys -asset=/Game/AI/BB_EnemyData

HTTP:

curl -X POST http://localhost:7850/baa/v1/execute \
  -H "Content-Type: application/json" \
  -d '{"verb":"bb-list-keys","args":{"asset":"/Game/AI/BB_EnemyData"}}'

Output:

{
    "success": true,
    "asset": "/Game/AI/BB_EnemyData",
    "keys": [
        {"name": "TargetActor", "type": "Object", "baseClass": "Actor"},
        {"name": "TargetLocation", "type": "Vector"},
        {"name": "HasLineOfSight", "type": "Bool"},
        {"name": "DistanceToTarget", "type": "Float"}
    ]
}

bb-add-key#

Add a key to a BlackboardData asset. Idempotent: if a key with the same name already exists, the verb succeeds without modifying it.

Category: Write

Args:

Arg Required Description
-asset= Yes BlackboardData asset path
-name= Yes Key name
-type= Yes Key type: Bool, Float, Int, String, Name, Object, Class, Enum, Vector, Rotator
-baseClass= No Base class constraint for Object key type (e.g., Actor, Pawn). Ignored for non-Object types

Examples:

# Add a simple boolean key
-verb=bb-add-key -asset=/Game/AI/BB_EnemyData -name=IsAggressive -type=Bool -save

# Add an object key constrained to Actor
-verb=bb-add-key -asset=/Game/AI/BB_EnemyData -name=PatrolTarget -type=Object -baseClass=Actor -save

# Add a vector key for a location
-verb=bb-add-key -asset=/Game/AI/BB_EnemyData -name=LastKnownLocation -type=Vector -save

# Add a float key
-verb=bb-add-key -asset=/Game/AI/BB_EnemyData -name=AggroRadius -type=Float -save

HTTP:

curl -X POST http://localhost:7850/baa/v1/execute \
  -H "Content-Type: application/json" \
  -d '{"verb":"bb-add-key","args":{"asset":"/Game/AI/BB_EnemyData","name":"PatrolTarget","type":"Object","baseClass":"Actor"}}'

Output:

{
    "success": true,
    "action": "created",
    "key": {
        "name": "PatrolTarget",
        "type": "Object",
        "baseClass": "Actor"
    }
}

Output (already exists):

{
    "success": true,
    "action": "already_exists",
    "key": {
        "name": "PatrolTarget",
        "type": "Object",
        "baseClass": "Actor"
    }
}

bb-remove-key#

Remove a key from a BlackboardData asset. Idempotent: if the key does not exist, the verb succeeds without error.

Category: Write

Args:

Arg Required Description
-asset= Yes BlackboardData asset path
-name= Yes Key name to remove

Examples:

-verb=bb-remove-key -asset=/Game/AI/BB_EnemyData -name=OldUnusedKey -save

HTTP:

curl -X POST http://localhost:7850/baa/v1/execute \
  -H "Content-Type: application/json" \
  -d '{"verb":"bb-remove-key","args":{"asset":"/Game/AI/BB_EnemyData","name":"OldUnusedKey"}}'

Output:

{
    "success": true,
    "action": "removed",
    "key": "OldUnusedKey"
}

Common AI Workflows#

Workflow 1: Set up a new AI from scratch#

Create a Blackboard with keys, then build a BehaviorTree that uses them.

Step 1: Create the Blackboard keys (batch):

curl -X POST http://localhost:7850/baa/v1/batch \
  -H "Content-Type: application/json" \
  -d '{
    "defaultAsset": "/Game/AI/BB_PatrolGuard",
    "operations": [
        {"verb": "bb-add-key", "args": {"name": "TargetActor", "type": "Object", "baseClass": "Actor"}},
        {"verb": "bb-add-key", "args": {"name": "PatrolLocation", "type": "Vector"}},
        {"verb": "bb-add-key", "args": {"name": "HasLineOfSight", "type": "Bool"}},
        {"verb": "bb-add-key", "args": {"name": "DistanceToTarget", "type": "Float"}}
    ],
    "save": true
}'

Step 2: Build the BehaviorTree structure (batch):

curl -X POST http://localhost:7850/baa/v1/batch \
  -H "Content-Type: application/json" \
  -d '{
    "defaultAsset": "/Game/AI/BT_PatrolGuard",
    "operations": [
        {"verb": "bt-add-node", "args": {"type": "Sequence", "parent": "0"}},
        {"verb": "bt-add-node", "args": {"type": "MoveTo", "parent": "$1"}},
        {"verb": "bt-add-node", "args": {"type": "Wait", "parent": "$1"}},
        {"verb": "bt-set-property", "args": {"node": "$3", "property": "WaitTime", "value": "3.0"}},
        {"verb": "bt-add-decorator", "args": {"node": "0", "childIndex": "0", "type": "Blackboard"}},
        {"verb": "bt-set-property", "args": {"node": "$5", "property": "BlackboardKey.SelectedKeyName", "value": "HasLineOfSight"}}
    ],
    "save": true
}'

Workflow 2: Inspect and modify an existing BehaviorTree#

Read the tree, find the node you need, then change its properties.

# Step 1: List the tree to find node indices
curl -X POST http://localhost:7850/baa/v1/execute \
  -H "Content-Type: application/json" \
  -d '{"verb":"bt-list","args":{"asset":"/Game/AI/BT_EnemyMain"}}'

# Step 2: Change the MoveTo acceptable radius (suppose it is at index 2)
curl -X POST http://localhost:7850/baa/v1/execute \
  -H "Content-Type: application/json" \
  -d '{"verb":"bt-set-property","args":{"asset":"/Game/AI/BT_EnemyMain","node":"2","property":"AcceptableRadius","value":"200.0"}}'

# Step 3: Add a Cooldown decorator to prevent re-entry
curl -X POST http://localhost:7850/baa/v1/execute \
  -H "Content-Type: application/json" \
  -d '{"verb":"bt-add-decorator","args":{"asset":"/Game/AI/BT_EnemyMain","node":"0","childIndex":"0","type":"Cooldown"}}'

# Step 4: Save
curl -X POST http://localhost:7850/baa/v1/execute \
  -H "Content-Type: application/json" \
  -d '{"verb":"save","args":{"asset":"/Game/AI/BT_EnemyMain"}}'

Workflow 3: Add a new Blackboard key and wire it into the tree#

# Add a new key to the Blackboard
curl -X POST http://localhost:7850/baa/v1/execute \
  -H "Content-Type: application/json" \
  -d '{"verb":"bb-add-key","args":{"asset":"/Game/AI/BB_EnemyData","name":"CoverLocation","type":"Vector"}}'

# Add a service that updates the key (custom service class)
curl -X POST http://localhost:7850/baa/v1/execute \
  -H "Content-Type: application/json" \
  -d '{"verb":"bt-add-service","args":{"asset":"/Game/AI/BT_EnemyMain","node":"0","type":"BTService_FindCover"}}'

# Add a Blackboard decorator that checks the key
curl -X POST http://localhost:7850/baa/v1/batch \
  -H "Content-Type: application/json" \
  -d '{
    "defaultAsset": "/Game/AI/BT_EnemyMain",
    "operations": [
        {"verb": "bt-add-node", "args": {"type": "Sequence", "parent": "0"}},
        {"verb": "bt-add-decorator", "args": {"node": "0", "childIndex": "$1", "type": "Blackboard"}},
        {"verb": "bt-add-node", "args": {"type": "MoveTo", "parent": "$1"}}
    ],
    "save": true
}'

Workflow 4: Commandlet invocation (no HTTP server)#

When the editor and BAAServer are not running, use the one-shot commandlet:

# List a BehaviorTree
"C:\Unreal\UE571Source\Engine\Binaries\Win64\UnrealEditor-Cmd.exe" \
  "C:\Unreal\ProjectLeyline\CombatDemo\CombatDemo.uproject" \
  -run=BlueprintAIAssistant \
  -verb=bt-list \
  -asset=/Game/AI/BT_EnemyMain \
  -nullrhi -nosplash -nosound -unattended

# Add a Blackboard key and save
"C:\Unreal\UE571Source\Engine\Binaries\Win64\UnrealEditor-Cmd.exe" \
  "C:\Unreal\ProjectLeyline\CombatDemo\CombatDemo.uproject" \
  -run=BlueprintAIAssistant \
  -verb=bb-add-key \
  -asset=/Game/AI/BB_EnemyData \
  -name=AlertLevel -type=Float \
  -save \
  -nullrhi -nosplash -nosound -unattended

Error Codes#

Errors relevant to BehaviorTree and Blackboard verbs:

Code Description
ASSET_NOT_FOUND Asset path does not exist or could not be loaded
INVALID_ARGS Missing or malformed required arguments
NODE_NOT_FOUND Node index not found in the BehaviorTree
PROPERTY_NOT_FOUND Property name not found on the BT node class
SAVE_ERROR Package save to disk failed

All error responses include:

  • "error": human-readable message
  • "errorCode": one of the codes above
  • "suggestion": actionable fix hint
  • "details": structured data when applicable

Tips#

  • Always bt-list first. Before modifying a BehaviorTree, list its structure to get current node indices. Indices can shift when nodes are added or removed.
  • Use batch for multi-step operations. Each commandlet launch takes 30-60 seconds. Batching avoids repeated startup costs.
  • Dot notation for nested properties. Many BT node properties are nested structs (e.g., BlackboardKey.SelectedKeyName). Use dot notation to reach them.
  • Custom classes must be loaded. When using a custom class name (e.g., BTTask_FindCover), the module containing that class must be loaded by the engine. If the class is in a game module, it loads automatically. If it is in a plugin, ensure the plugin is enabled.
  • Blackboard keys are idempotent. bb-add-key and bb-remove-key are safe to call multiple times. They succeed silently if the key already exists or is already absent.