Topolog

The TOL language

Under the hood, every Topolog plan is a file written in TOL, the Topolog Orchestration Language. You almost never write TOL by hand (the IDE’s canvas, source, and parameters tabs all round-trip to it) but knowing the grammar makes the rest of the IDE legible.

A TOL file declares a goal, a registry of the things the plan produces, the outcomes the plan is uncertain about, the agents doing the work, and a network of tasks wired together by edges. That’s it. Everything you see in the IDE (the graph, the spectrum, the critical path, the money panel) is computed from this one source of truth.

The five node primitives

Every node on the canvas is one of five things.

Task

An atomic unit of work: what a human (or AI agent, or external counterparty) actually does. Tasks carry an estimate and a coefficient of variation.

task t_draft_menu "Draft the menu" {
  agent:    chef
  estimate: 2h cv 0.4
}

Milestone

A grouping node that contains tasks and edges. Milestones never run themselves; their status is derived from the work inside them. Useful for “Kitchen prep”, “Legal”, “Phase 1”.

milestone m_prep "Kitchen + FOH prep" {
  task t_inventory  "Kitchen inventory" { agent: sous;  estimate: 2h }
  task t_foh_setup  "Front of house"   { agent: foh;   estimate: 3h }
  edge e_prep t_inventory -> t_foh_setup { carries: null }
}

Iteration

A repeat-until block. Same template runs each round, gated by an outcome predicate; the loop exits when the gate fires or a cap is hit. Used for revision rounds, retries, sprints.

iteration revise_menu "Menu draft + revision loop" {
  type:      revision_round
  max_count: 4
  exit_gate: menu_signed_off = true
  template: milestone menu_round "Menu round" {
    task t_draft  "Draft / revise"      { agent: chef; estimate: 2h }
    task t_review "Review the draft"    { agent: chef; estimate: 1h
                                          produces: [menu_signed_off] }
  }
}

Sentinel

An end-state marker. Every causal path through the graph terminates at a sentinel: success, partial, failure, or any custom end-state you declare. The spectrum panel colours outcomes by which sentinel the plan ends on.

sentinel s_success { end_state: success }
sentinel s_partial { end_state: partial }
sentinel s_failure { end_state: failure }

Group

A bag of nodes that all execute under a shared rule. For example, three concept-sketch tasks that share an agent thread and therefore serialise rather than running in parallel. Groups are how TOL expresses resource contention without cluttering the dependency graph with bookkeeping edges.

Deliverables and state-sets

A plan’s deliverable_registry names the artefacts the plan produces: a Menu, a SupplierContract, a BuiltApp. Each deliverable has a chain type (it accumulates a history of states) and an associated state-set declaring which states are legal.

deliverable_registry {
  Menu      { chained_type: chain;     parent_id: null }
  MenuState { chained_type: state_set; parent_id: Menu
              predicates: [drafted, costed, signed_off] }
}

Tasks reference these state predicates: the only legal values for the gates that decide what runs next. You can’t gate on signed_offf by accident because the validator rejects predicate names not declared in the registry.

Outcomes

An outcome is an uncertain quantity the plan produces: a boolean (“was the menu signed off?”), a scalar (“what was the final food-cost percentage?”), or a categorical (“did the soft launch go well, mixed, bad?”). Outcomes carry a prior, get measured at runtime, and feed the gates that route downstream work.

outcome menu_signed_off:      boolean      { default_prior: 0.75 }
outcome final_food_cost_pct:  scalar       { default_prior: { distribution: normal, mean: 0.30, std: 0.05 } }
outcome soft_launch_result:   categorical  { good, mixed, bad }
                                           { default_prior: { good: 0.55, mixed: 0.30, bad: 0.15 } }

Edges and gates

Edges express ordering: what must finish before what. A plain edge carries nothing but the dependency. A gated edge is conditional on an outcome:

edge e_soft_to_hard t_soft_service -> m_hard_launch {
  gate: soft_launch_result == good
}

The hard launch only runs when the soft launch resolves to good. Gates on scalars work the same way: final_food_cost_pct <= 0.30.

A small full example

Here’s a heavily trimmed slice of the canonical pop-up-restaurant plan: goal, two milestones, one outcome, one gated edge, one sentinel. Every grammar feature on this page in 30 lines.

plan "Pop-up restaurant: minimal exemplar" {
  goal { name: "Launch the Tuesday pop-up by 2026-04-15" }

  outcome menu_signed_off: boolean { default_prior: 0.75 }

  agent chef "Head chef" { type: internal; kind: individual }

  milestone m_concept "Concept" {
    task t_sketch "Sketch the menu" { agent: chef; estimate: 3h }
  }

  milestone m_launch "Launch" {
    task t_prep    "Launch prep"    { agent: chef; estimate: 3h }
    task t_service "Launch service" { agent: chef; estimate: 3h }
    edge e_p2s t_prep -> t_service { carries: null }
  }

  edge e_gate m_concept -> m_launch {
    gate: menu_signed_off == true
  }

  sentinel s_success { end_state: success }
  edge e_done m_launch -> s_success { carries: null }
}

Open this on the canvas, mark menu_signed_off true, and the launch milestone unblocks. Mark the launch tasks done and the plan terminates at s_success.

Power-user features

Beyond the core grammar above, TOL carries a handful of advanced features used in detailed plans. The IDE exposes all of them — either through structured forms in the Inspector and Add-Node modal, or via Expert Mode (Shift+E) for inline TOL editing.

  • Universe agents — exogenous clocks like concrete cure, paint dry, or weather windows that run in parallel to your work without consuming scheduler capacity. A single universe agent can declare multiple independent threads (one per physical process).
  • Multi-law evolution + shareability on deliverables — declare continuous-time evolution laws (linear or exponential growth/decay on a named property) and a shareability cap that bounds concurrent in-flight pickups of the same deliverable type.
  • Arrival processes + schedules on iteration blocks — model stochastic arrivals (Poisson-style rate pieces) or deterministic schedules (every N minutes from a start date) instead of a fixed max_count.
  • Edge cardinality [N,M] — edges carrying a deliverable can declare an exact range of expected pickups, e.g. [2,5] for “between two and five of this type”. Replaces the binary one-vs-many shorthand for cases where the range matters.
  • Layer-2 script bodies on tasks — an optional script body for tasks that are scripted programs (an AI prompt template, a shell command, a SQL query). Layer-1 scheduling ignores them; Layer-2 execution picks them up.
  • AI-agent cost & latency — AI agents can declare a per-call cost (in your currency) and an inference latency the scheduler adds to each task they touch. Surfaces a realistic cost + time estimate for AI-heavy plans.

What’s next

TOL is normally invisible: you draw on the canvas, the IDE round-trips to the source view, and you only open the Source tab when you want a copy-paste diffable snapshot of the plan. The grammar above is the entirety of what Topolog needs to build a schedule: see how the scheduler turns it into a calendar, or how the graph itself works.

Ready to plan in graphs?

7-day free trial · 250 credits · No card required

Get Started →