← All text IRs

BTIR

Read as text Behavior Trees

A Behavior Tree is a graph of composites, tasks, decorators, and services fanning out from a hidden root node — the kind of structure you can normally only read by opening the Behavior Tree editor and tracing boxes and wires down the canvas. BTIR is that same tree flattened into compact, indented text: every node named and typed, its decorators and services nested underneath, blackboard keys listed, and the canvas @(x, y) positions preserved. It is the Behavior Tree sibling of BPIR — same text-IR philosophy, distinct opcodes — and it is decompile-only: you read the graph as text, you do not write the asset back through it.

Why it matters

Diffable in version control

An AI logic change becomes a handful of changed lines in a pull request instead of an opaque binary asset. The same text is written as a btir.txt sidecar in the asset-dump cache, so Behavior Tree history is greppable in git.

Reviewable like code

Structure is explicit: node role and kind (root composite, child task), decorators and services nested as a block, and non-implicit branch logic spelled out as a decorator_logic [Not:1, Test:0] line. You see what runs and in what order without following wires by eye.

A format an AI can actually read

One keyword-first text covering the whole tree — topology, root-level aux nodes, orphaned nodes, and the backing blackboard — so your assistant loads a tree's real behavior into context in a single call instead of a dozen blind graph-inspection RPCs.

Faithful and deterministic

BTIR walks the editor graph itself, so node positions, comments, disconnected nodes, decorators, services, and explicit FBTDecoratorLogic operations are all visible. Anything the walker can't reach from the root is emitted as an orphan with a matching warnings[] entry rather than silently dropped.

A taste

A behavior_tree block names the backing blackboard, then nests the tree from its root composite. Each line reads role kind type name followed by its canvas position; decorators and services sit inside their parent node's { } body:

behavior_tree /Game/AI/BT_Patrol.BT_Patrol {
  blackboard /Game/AI/BB_Patrol.BB_Patrol
  root composite Selector Root @(0, 0) () {
    child composite Sequence Chase @(-160, 180) () {
      decorator Blackboard IsTargetSet @(-160, 120) ()
      decorator_logic [Not:1, Test:0]
      child task MoveTo MoveToTarget @(-160, 320) (comment: "Move to current target")
    }
    child task Wait Patrol @(160, 180) ()
  }
}

How your assistant uses it

Your assistant decompiles the asset to BTIR with behavior_tree.decompile and reads it for context — to answer questions about the tree or to plan edits it then applies through the individual behavior_tree.* graph RPCs. This IR is read-only; it does not write the asset back.

You: What decides whether BT_Patrol chases instead of patrolling?

  call("behavior_tree.decompile", {assetPath:"/Game/AI/BT_Patrol.BT_Patrol"})
    → {assetPath:"/Game/AI/BT_Patrol.BT_Patrol",
       ir:"behavior_tree /Game/AI/BT_Patrol.BT_Patrol {\n  root composite Selector Root @(0, 0) () {\n    child composite Sequence Chase @(-160, 180) () {\n      decorator Blackboard IsTargetSet @(-160, 120) ()\n      child task MoveTo MoveToTarget @(-160, 320) ()\n    }\n    child task Wait Patrol @(160, 180) ()\n  }\n}",
       text:"behavior_tree /Game/AI/BT_Patrol.BT_Patrol { ... }",
       warnings:[]}

The root Selector tries Chase first: it runs only when the IsTargetSet
blackboard decorator passes, otherwise the tree falls through to the Wait patrol.
BTIR is decompile-only and early. It reads Behavior Tree and standalone Blackboard assets out as text for review and AI context; compiling BTIR text back into an asset is a planned follow-up, so today you make edits through the individual behavior_tree.* RPCs, not by writing BTIR. Decompile an existing tree to learn the exact shape before reasoning about an unfamiliar pattern.

← Back to all text IRs