AshForge Sentinel · the whole tool, one course
Build a patrol, read the run,
and know that dead is not broken.
Sentinel authors behaviour trees and then lets you watch them run. The authoring half is small; the debugging half is where the tool earns its keep, and it rewards knowing which of its four instruments answers which question.
What it is
A behaviour-tree editor with a live runner. You compose regions and selectors, then scrub through a recorded run.
Modules 1–5 are building one, 6–9 are the contract, 10–14 are diagnosis.
The one that saves an evening
Dead is not broken. A node that never fires is usually correct — and telling that apart from a real fault is what the four instruments are for.
Modules 10–14, and the worked diagnosis at the end is the fastest way in.
Sentinel is a focused tool. Its content is 14 things worth knowing, not three escalating tiers — the old split implied the later material needed the earlier, and it does not. Read straight through, or jump to the module that matches your problem.
Getting oriented
Three regions
Once the welcome panel is out of the way, the window settles into three areas. You will spend this tutorial in two of them.
Look at01
What is on screen
- The node palette runs down the left, with a search box at the top.
- The canvas sits in the middle, holding a single
Rootnode. - The Blackboard is on the right.
Done whenYou can name all three without looking.
Leave alone01b
The Blackboard, for now
It is the most interesting panel in Sentinel and it is also the one most likely to mislead you on day one, because what it appears to promise and what it actually does are two different things.
Tutorial two is about exactly that. Until then you can build a complete, working guard without touching it.
Reading a tree
Selector means or
Building a tree from an empty canvas is a poor first exercise, because the interesting part of a behaviour tree is not the nodes themselves but the order in which they are tried. It is far easier to read a working one first.
Load the Patrol Guard template
- Open the Templates menu in the toolbar. There are five: Aggressive, Defensive, Pack Hunter, Patrol Guard and Elite Combatant. they run roughly in order of complexity
- Choose Patrol Guard, which is five nodes built around a single idea. the smallest template that still has something to teach
- Check the status line under the toolbar. It should read “Loaded the 'Patrol Guard' template — tweak it, then Save or Test in Crucible.” Sentinel confirms most actions there and nowhere else
Figure 01 — Patrol Guard Five nodes as Sentinel draws them, and the whole lesson sits in the Selector.
A Selector tries its children in order and stops at the first one that succeeds. So
this guard asks whether it can see the player. If it can, the Sequence carries on to
Investigate and the Selector is satisfied, which means it never reaches Patrol. If
it cannot, the Sequence fails and the Selector falls through to Patrol instead.
The five node types
| Node type | Succeeds when | Use it for |
|---|---|---|
| Selector | any one child succeeds | Fallbacks. Try this, otherwise that. |
| Sequence | every child succeeds | Steps that must all happen, in order. |
| Parallel | according to its policy | Doing two things at once. |
| Condition | the world says so | Gates, such as CanSeePlayer or HealthLow. |
| Action | the behaviour finishes | Doing something: Patrol, Attack, Wait. |
Your first edit
Change one thing
At the moment the guard investigates the instant it sees anyone, which reads as slightly inhuman. Making it hesitate first is a small change, and it is a good excuse to use the palette and the connection system for the first time.
Drill03
Add a Wait node
- Type
waitinto the palette's Search nodes… box. - Drag + Wait onto the canvas.
- Connect it by dragging from a node's right-hand slot into another node's left-hand slot.
- Place it between
CanSeePlayerandInvestigate, inside the Sequence.
Done whenThe Sequence reads: see the player, pause, then investigate.
Now read it back03b
What you just changed
See the player, and pause, and investigate. Otherwise, patrol.
That is a different character from the one you loaded a few minutes ago, and it took a single node. Most of the personality in a behaviour tree lives in decisions this small.
Crucible and the debug bar
Watch it run
Reading a tree tells you what it should do. Running it tells you what it does, and the two part company more often than you would like.
Drill04
Test in Crucible
- Set Agents in the toolbar to
3. - Press Test in Crucible, the suite's testing lab. It drops live 3D agents into an arena and drives them with your tree.
- Watch for the fallback firing: agents who cannot see anyone should patrol, and the ones who spot the player should stop, pause for your Wait, then investigate.
Done whenYou have seen both branches happen at least once.
Drill04b
Read the trace
- Back in Sentinel, find the debug bar along the bottom: Stats, Heatmap and Analytics, plus a timeline scrubber.
- Open Stats to see how often each node fired.
- Drag the scrubber to step through the run tick by tick.
Done whenYou can point at the node that fired least and say why.
Export
Ship it
Two steps, and the order matters more than it looks.
Set a version, then export
- Open Info… and set a version number. the version is written into the exported file, so it has to exist first
- Press Export…, which writes a versioned
.behavior.json. this is the file the game actually loads
What actually gets exported
Four fields, and nothing else
Export a behaviour and open the file in a text editor. Every node in it looks like this, and only like this.
{
"id": "n7",
"kind": "Condition",
"task": "CanSeePlayer",
"children": null
}
Four fields: an identity, a structural kind, the name of a task, and its children.
There is no radius here, no target, and nothing describing how far this guard can see.
CanSeePlayer is a word the game already knows. Sentinel is choosing which words to
say and in what order, and the game decides what they mean.
Figure 01 — the division of labour Everything you can do in Sentinel lives in the left panel. Everything that makes a character behave lives in the right one.
The panel you were told to ignore
The Blackboard declares
Open a behaviour and look at the Blackboard on the right. Press
+ Add variable and you get a row: a name, a type dropdown, a default value, and a cross to
remove it. Five types are available — Bool, Int,
Float, String and Vector3.
This is the part that trips everyone up. Nothing in the editor connects a variable
to a node. You cannot make a Condition test alarmRaised, and no Action can write
to it. Declaring a variable does not change what your tree does inside Sentinel, and it never
will.
That is not a missing feature so much as the wrong side of the line. Which line becomes clear as soon as you ask what the declaration is for.
It is the state half of the contract. When your behaviour ships, the game needs to know which
variables this tree expects to exist, what type each one is, and what value it starts at.
Declaring alarmRaised : Bool = false tells the runtime to allocate that variable,
initialise it to false, and let the tasks use it.
The most useful way to read the panel is as a function signature. You are not writing the body; you are declaring what the body will be handed.
Declare the guard's state
- Load Templates → Patrol Guard again, then add three variables:
alarmRaisedas aBooldefaulting tofalse,lastSeenAtas aVector3defaulting to0,0,0, andpatrolSpeedas aFloatdefaulting to1.5. one of each shape, so you can see how the types survive export - Save, then export, then open the
.behavior.jsonin a text editor. the file is the only place the declaration becomes visible - Find your three variables in the
blackboardarray, names, types and defaults intact, sitting alongside the tree rather than inside it. that separation is the shape of the handoff
Control flow
What you really own
If the meaning of every task lives in the game, what genuine authoring power is left to you? Control flow. Selector and Sequence from tutorial one, and two more worth knowing.
Drill03
Decorator, and the Inverter
- Drag + Decorator from the palette. It defaults to Inverter.
- Note that it takes exactly one child. Try to give it two and the second connection will not take.
- An Inverter flips its child's result: success becomes failure, and failure becomes success.
Done whenYou can explain why that is more useful than it sounds.
Why it matters03b
Building a condition you weren't given
There is no CannotSeePlayer in the palette. The conditions available are
CanSeePlayer, HealthLow, HasTarget and
IsInRange, and that is the whole list.
Wrap CanSeePlayer in an Inverter and you have just built its opposite,
without anyone having to add it to the vocabulary.
CanSeePlayer, then a Wait. The guard now pauses when it cannot
see anyone, which reads as a nervous sentry rather than a metronome.Parallel, and why to be sparing with it
+ Parallel runs its children simultaneously rather than in order. It is the right choice when a behaviour genuinely overlaps — walking a route while scanning — rather than forcing two things into an artificial sequence.
Use it sparingly all the same. A Selector or a Sequence tells a reader exactly what happens next, whereas a Parallel says “several things, and the outcome depends on a policy”. It is the node most likely to make your tree hard to debug when you reach tutorial three.
Versioning
Two version numbers
Every exported behaviour carries two version fields. They do quite different jobs, and only one of them is yours.
| Field | What it means | Who sets it |
|---|---|---|
behaviorVersion |
Your version of this particular behaviour. Bump it when you change the tree. | You, under Info… |
primitiveSetVersion |
The version of the vocabulary itself — the set of task names Sentinel knows about. | Stamped for you at export |
The second one is doing real work. When Crucible loads a behaviour whose primitive set is newer than the one it supports, it says so out loud:
Primitive set v2 is newer than supported v1; unknown tasks will no-op.
That warning is the difference between a bug you can see and a bug you cannot. Without it, a tree using a task the runtime does not recognise would simply do nothing — in one branch, intermittently — and you would go looking at your tree structure, which would be perfectly fine.
When you see that warning, stop and check versions before you debug anything else.
behaviorVersion under Info… before exporting rather than
after. The value is written into the file at export time, so bumping it afterwards leaves you
with a file whose contents disagree with what you intended.Setup
Something worth debugging
A five-node tree cannot teach you to debug, because you can hold all of it in your head at once. Sixteen nodes and three agents is the point at which you have to start measuring instead of reading.
Drill01
Load Elite Combatant and read its shape
- Open Templates → Elite Combatant. Sixteen nodes.
- Notice that its composites have names:
Brain,Survive,Engage,Close or Strike,Search. - You can rename any node, and at this size that is the difference between a diagram and a wall.
Done whenYou can describe the tree without scrolling it.
The shape01b
Child order is a priority list
Brain is a Selector, and its children run in order: Survive, then Engage, then
Search, then a fallback. Fleeing outranks fighting, and fighting outranks looking.
That ordering is the personality. Move Survive below
Engage and you have written a fanatic, without touching a single task
name.
Run it with a swarm
- Set Agents to
3and press Test in Crucible. one agent shows you a path; three show you a distribution - Crucible opens and Sentinel connects to it over a local debug socket. the connection is what makes the capture automatic
- Wait for the status line to report the capture. the run is not reviewable until it says so
[INFO] (LiveDebug) Connected to Crucible live debug on 127.0.0.1:45599. Live run finished — 53 tick(s) captured. Scrub or Play to review.
You now have a trace: every tick, for every agent, the status of every node, plus the blackboard values as they stood at that moment.
The debug bar
Four instruments, in order
Numbers first, then shape, then summary, then the moment. Reaching for them in that order saves you from forming a theory before you have any evidence.
Stats — the numbers, on the nodes
Press Stats. Every node gains a line showing evaluations, successes, failures and running ticks.
Survive 53× ✓0 ✗53 ↻0 HasTarget 53× ✓53 ✗0 ↻0 Brain 53× ✓18 ✗0 ↻35 Flee · not reached
Those four rows already tell you the story of the run. Survive was checked on
every tick and failed on every one, which means nobody got hurt. HasTarget
succeeded every tick, so the enemy was visible throughout. Brain spent two-thirds
of its life running rather than finishing, which is exactly what a Selector does while
its chosen child is mid-action.
Heatmap — where the pressure is
Press Heatmap and node headers tint by evaluation count, relative to the busiest node in the run. Because the scale is relative there is always something hot, so the brightness itself tells you little. What you are looking for is the shape: which spine of the tree the agent actually lived in, and which limbs stayed cold.
Analytics — the summary that names suspects
| Reading | This run |
|---|---|
| Final outcomes | 3 success · 0 failure |
| Ticks and duration | 53 · 5.5 s |
| Nodes | 16 |
| Dead branches | 6, never reached |
| Busiest node | Brain, 53 evaluations |
Below that sits a per-node table with success, failure and running percentages. The agent dropdown in the debug bar switches which agent you are inspecting, and when one agent out of three behaves differently, that dropdown is where you find it.
A correction to tutorial one
Dead is not broken
Tutorial one told you that a node which never fired is a wiring bug. That was a useful simplification for a five-node tree. Here is what is actually true.
This run reported six dead branches out of sixteen nodes — in the template that
ships with the tool, on a run where all three agents succeeded. Flee was never
reached because nobody's health ever dropped. Search and Investigate
were never reached because the target stayed visible the whole time.
None of those branches is broken. They are insurance that this particular run did not need.
Figure 01 — diagnosing a silent branch The whole flow hinges on the second box, and that is the one question the tool cannot answer for you.
The scrubber
Scrubbing to the moment
This is where tutorial two pays off, and it is the only place in Sentinel where the contract you declared becomes something you can watch.
Drill04
Step through the run
- Drag the scrubber to walk the run tick by tick, or press Play to animate it.
- As you move, the graph shows each node's status at that instant.
- Watch the status bar, which shows the blackboard as it stood on that tick.
Done whenYou can stop on any tick and say what the agent believed.
The technique04b
Find the tick, then read the variables
Find the tick where behaviour diverged from what you wanted, then read the blackboard at that tick rather than at the end.
Most complaints of the form “the AI is being stupid” turn out to be a variable that was not what you assumed it was.
Tick 54/54 · Success BB: distance=1.8 health=100 tar…
That is the contract from tutorial two, filled in. You declared distance and
health, the game wrote them, and the trace recorded them. Nowhere else in Sentinel
do blackboard variables carry live values, which is the practical reason declaring them
carefully is worth the effort.
Putting it together
A worked diagnosis
Suppose your guards refuse to flee, however badly hurt they get. Work it in this order.
From the silent node upward
- Open Stats and ask whether
Fleeis reached at all. If it reads not reached, the branch never ran. there is no point examining a node that never executed - Look at its gate.
HealthLowshows53× ✓0 ✗53: evaluated on every tick and never once successful. a gate that never opens explains everything beneath it - Take the fork. Either health genuinely never dropped, which is a scenario problem and means you fix the test rather than the tree; or it did drop and the condition disagreed, which is a contract problem, because the game's definition of “low” is not yours. these two look identical from the canvas and completely different in the data
- Scrub to a tick where the agent was hurt and read
healthin the blackboard. that single number tells you which of the two you have
Root itself reports not reached with zero evaluations, in every run
without exception. The trace records the nodes that Root drives rather than Root itself, so
there is nothing wrong. Do not chase it.Course complete
What you now know
Check yourself
- Selector is or and Sequence is and. Everything else composes from those two.
- Templates are the fastest way into a new tree, so read a working one before building your own.
- Connections run out of a right slot and into a left slot, parent to child.
- A node with zero fires in Stats usually means a wiring mistake — provided the run you watched should have reached it.
- Save manually and often, because nothing in the tool will remind you.
- Set the version before exporting, since it is written into the file.
- A node compiles to four fields —
id,kind,taskandchildren— and nothing else travels with it. - Task names are vocabulary the game implements. Sentinel chooses the words; the game defines what they mean.
- The Blackboard declares state for the runtime. It has no effect inside the editor, and that is by design rather than by omission.
- An Inverter gives you conditions the palette does not ship, and takes exactly one child.
- Parallel is powerful and costs you legibility, so reach for it last.
primitiveSetVersionis checked on load. Heed the warning before you start debugging your tree.- Name your composites. At sixteen nodes it stops being optional.
- A Selector's child order is a priority list, and that ordering is the character.
- Stats, then Heatmap, then Analytics, then the scrubber: numbers, shape, summary, moment.
- Each node reads
N× ✓a ✗b ↻c, and not reached means zero evaluations. - Dead branches are only bugs if the run should have reached them. Six of sixteen were dead here and every agent still succeeded.
- Blackboard values are live in the scrub bar, which is the one place the contract becomes visible.
- Diagnose upward from the silent node to its gate, and check the gate's success count before you touch anything.
That is Sentinel. It is the smallest tool in the suite with the richest debugging story — most of the value is in modules 10 onward, and they are worth revisiting the first time a tree does something you did not expect.
