/ai/set attaches an AiGoal; the ai_system
turns it into a desired Velocity every tick), and a behavior-tree library (euca-ai) you author in Rust.
This page sets a chase goal and reads the velocity the tick produces; every command is real and runnable
against a local server, with output captured from one.
“AI” here is never an LLM. The agents that drive Euca are external clients (your code or model, over
the API). This page is about the NPC AI that lives inside the world. Fully
headless.
Set a chase goal and step it
Spawn a chaser and a target at a distance (chasing a target at your own position gives a degenerate zero/NaN direction — keep them apart):chase goal to the chaser, pointing at the target, with a speed. Read it back before stepping —
the goal is set, but no velocity has been computed yet:
ai_system, which runs on a tick. Step once, then read again:
[3.0, 0.0, 0.0] — speed 3.0, aimed straight at the target on the +x axis.
patrol reads back as "patrol (3 waypoints)"; idle as "idle".
Behavior and gotchas
The things you only find out by running it:-
The goal sets immediately; the velocity computes on a tick.
/ai/setattaches theAiGoalat once (aireflects it right away), butvelocitystays[0,0,0]until the next/stepruns theai_system. Set, then step, then read the velocity. -
/ai/setaccepts onlyidle,chase, andpatrolover HTTP —flee(and any other string) falls through toidle. The response message echoes whatever you sent, so it looks accepted, but the stored goal is idle:AiBehavior::Fleeexists in the engine; it just has no HTTP path. Trust theaifield on read-back, not the message. -
ai_systemcomputes velocity, not position. It writes a desiredVelocitytoward the goal. Turning that velocity into movement needs a physics/character-controller step on the entity; a bare spawned unit holds the velocity but won’t necessarily advance itstransform. Spawn with aphysics_body(or run the relevant movement system) if you want the unit to actually travel. -
Setting AI on a missing entity returns
ok:false.{"entity_id":999,...}→{"ok":false,"message":"Entity 999 not found"}. Nothing is changed.
Behavior trees (euca-ai)
For richer NPC logic, the euca-ai crate is a full behavior-tree library, authored in Rust:
- Composites —
Sequence,Selector,Parallel { RequireAll | RequireOne } - Decorators —
Inverter,RepeatN,RepeatUntilFail,Cooldown,Guard - Leaves —
Action(MoveTo,Wait,SetBlackboard,Log,Custom) andCondition(HasKey,Compare,InRange,IsAlive,Custom) - Blackboard — a per-entity typed key-value store;
BtBuilderis a fluent construction DSL.
behavior_tree_system ticks every BehaviorTreeExecutor. Behavior trees have no HTTP surface — they’re
authored in Rust today; the only AI you can drive over HTTP is the /ai/set steering goal above.
Endpoints
Status
- Shipped — Steering goals (
idle/chase/patrolover HTTP;fleeexists in-engine but has no HTTP path), and the behavior-tree library (composites, decorators, leaves, blackboard, builder). No stubs.
AI endpoint
The
/ai/set endpoint with its request and response schema.