# How Flisk Routes Agent Traffic: A Sequence Diagram of One Turn

> Source: <https://dev.to/flisk/how-flisk-routes-agent-traffic-a-sequence-diagram-of-one-turn-5a4g>
> Published: 2026-10-24 11:07:34+00:00

The earlier articles covered the agent, the MCP resource, and the control plane. This one follows a single turn: one request from a client to an agent, through the gateway, the checkpoint store, and back.

The sequence follows the Flisk agent docs. The model call is a placeholder, since your `runTurn` decides what it looks like.

```
sequenceDiagram
    autonumber
    actor User as Client
    participant GW as Traefik gateway
    participant Agent as Agent service
    participant Store as Checkpoint volume
    participant Model as Model provider (your code)

    User->>GW: POST /api/bot/turn with x-session-id
    GW->>Agent: route by session header
    Agent->>Store: load checkpoint for the session
    alt no checkpoint yet
        Store-->>Agent: empty state
    else checkpoint exists
        Store-->>Agent: prior messages
    end
    Agent->>Agent: append the user's input
    Agent->>Model: runTurn(checkpoint, input)
    Model-->>Agent: reply and updated state
    Agent->>Store: commit the checkpoint atomically
    Store-->>Agent: committed
    Agent-->>GW: reply
    GW-->>User: reply

    Note over Agent,Store: On SIGTERM an in-flight turn finishes and checkpoints first
    Note over Store: The named volume survives flisk down
```

The session state sits in a checkpoint store, a file per session on a named Docker volume. The turn reads it first and writes it last. The write is atomic, so a crash partway through does not leave a half-saved conversation.

Because the volume outlives `flisk down`, a restarted agent loads the same state the next turn needs. The docs also say an explicit volume removal is the only way to lose it, which is a deliberate safeguard.

The gateway uses the `x-session-id` header to choose the session. Two conversations never share a checkpoint, even when they hit the same agent service. The header is also the one thing a client must get right: a missing or changed session ID starts a new conversation.

If the agent restarts between turns, the next turn loads the checkpoint and carries on. If it restarts during a turn, the drain on SIGTERM lets the in-flight turn finish and checkpoint first. The docs say live-update reloads use the same path.

A crash rather than a clean stop skips the drain. The atomic commit then protects the last saved state, and the turn in progress is lost. Plan for that in your client: retry the request with the same session ID, and check whether the turn was saved.

Send two turns with one session ID, restart the stack, and send a third turn. The third reply should reflect the first two. Then send a turn with a new session ID and confirm it starts fresh. Those two checks cover the parts that break quietly.

One turn goes through the gateway, which routes by session. The agent loads the checkpoint, calls your model code, commits the new state atomically, and replies. The state survives a restart because it lives on a volume, and a clean stop drains the turn in progress. Test the two-turn, restart, third-turn path before you depend on it.
