Concept 2 of 10

The model doesn't hold a tool list. It follows links.

You gave a model a bag of tools and hoped it would call them in the right order. Flowgate hands it only the legal next moves — as links it follows, one at a time.

A flat tool list is a bag of loaded guns

Register your tools with a model and it can fire any of them, any time, in any order — deploy before tests, delete before backup, skip the approval entirely. A flat list encodes no order and no preconditions. You're trusting the model to remember the rules every single call.

Flowgate doesn't hand the model a list. It hands the model the current legal moves — and nothing else.

Every response carries its own next steps

The model searches once, then follows the links the server hands back. Each response tells it what's legal next — it never memorizes a catalog, it carries one current response and follows its links. (If you want the lineage: this is HATEOAS, the oldest idea in web APIs, pointed at agents.)

wire.jsonl
→ flowgate.command  { "definitionId": "ship_guard", "input": {...} }

← { "state": "tests_green",
    "version": 7,
    "links": [
      { "rel": "open_pr", "method": "flowgate.command",
        "args": { /* prefilled */ } }
    ] }

One state, one set of legal moves. The model follows a link; it doesn't guess from a menu.

A wrong move doesn't crash the run

If the model tries an illegal transition, it doesn't get a dead end. It gets the current legal links back and recovers in place — and the rejection is still recorded as a transition.rejected audit event, so you see it even when the model fixes itself silently.

wire.jsonl
→ flowgate.command  { "transition": "deploy", ... }

← { "error": { "code": "INVALID_TRANSITION",
               "message": "Transition 'deploy' is not valid from state 'tests_green'." },
    "state": "tests_green",
    "links": [ { "rel": "open_pr", ... } ] }   // here's what you CAN do

Concept 2 of 10

Next concept →

Building blocks, approved once

Your agent composes approved scripts, skills, and calls. It never gets a shell.

See all concepts