Taos Engine · Agent Tutorials

Agent Tutorials · Step 1

Hello, Agents

▶ Live demo: run this tutorial in your browser — built from src/01_hello_agents.ts.

The AgentScript "hello world": a population of turtles that wander on a torus and render as little arrows pointing where they head. In AgentScript you'd write a setup() that creates turtles and a step() that calls turtle.right(...) and turtle.forward(1) on each. In Taos Engine you declare that step once and it runs for the whole population on the GPU.

By the end you'll have ~20,000 turtles wandering at a steady 60 fps, and you'll understand the three pieces every agent model has: a world, a step program written from agent.* verbs, and a renderer.

The mental model (if you know AgentScript)#

AgentScriptTaos Engine
class MyModel extends Modela function returning an AgentModelConfig
setup() — create turtlespopulation + spawn
step() — turtles.ask(t => …)the step: Action[] program (compiled to a GPU kernel)
turtle.right(d) / forward(d)agent.turn(d) / agent.moveForward(speed)
world.setTopology('torus')world.topology: 'torus'

The key difference: AgentScript's ask is sequential imperative JS per turtle; Taos Engine's step is a declarative expression program compiled to WGSL and run in parallel. Every agent reads the previous frame's state and writes the next — a consistent snapshot, like a well-behaved ask with no within-tick surprises.

The model#

TypeScript
import { agent, type AgentModelConfig } from 'taos/agents/index.js';

const WORLD = 100;
const HALF = WORLD / 2;

function helloAgents(): AgentModelConfig {
  return {
    world: { min: [-HALF, -HALF], size: [WORLD, WORLD], topology: 'torus' },
    population: 20_000,
    spawn: { color: [0.4, 0.8, 1.0, 1.0], size: 0.5 },
    step: [
      agent.turn(agent.randomTurn(0.3)),   // wiggle the heading a little each step
      agent.moveForward(8),                // 8 world-units/second along the heading
    ],
    render: { shape: 'arrow', blendMode: 'additive', sizeMul: 1.8 },
  };
}

That's the whole model. Notes:

That's the whole model — a plain AgentModelConfig. The harness lowers it for you in the next step.

Running it#

One call runs the model. runAgentModel (the engine's agent harness) wires the engine, a dim sun, a top-down fly camera with drag/WASD controls, the render-feature stack, and the frame loop — so the file is just the model plus a one-line HUD:

TypeScript
import { runAgentModel } from 'taos/agents/agent_app.js';

runAgentModel({
  params: {},
  model: helloAgents,
  // a camera looking down at the XZ plane the agents live on
  camera: { position: [0, 95, 55], pitch: 1.05, fov: 55, near: 0.5, far: 5000, speed: 40 },
  onReady: (app) => {
    const hud = makeHud();   // a small inline HUD helper — see the source file
    app.engine.afterFrame(() => hud(`FPS ${Math.round(app.ctx.fps)}  ·  20k turtles wandering`));
  },
});

Each tutorial is a single self-contained file — no shared scaffold — so the tiny makeHud text-overlay helper lives at the bottom of each one.

Under the hood the harness lowers the model with buildAgentConfig (to a ParticleGraphConfig that runs on the engine's stock ParticlePass) and adds three render features: a ForwardLitFeature, a ParticleFeature, and a TonemapFeature. Agents are additive HDR sprites, so they sit between the lit pass and tonemap. Every tutorial uses this same harness — what changes is the model. The full option set (patch-field ground views, control panels, seeding, extraFeatures) is in the run harness reference.

Shell
cd standalone/agent_tutorials && npm install && npm run dev

Open 01_hello_agents.html. Drag to look, WASD to fly.

Next#