Clutch wraps Laravel AI instead of replacing it. Your agents, tools, and provider configuration stay exactly as they are.

flowchart LR
    Controller["Your controller"]
    Coordinator["RunCoordinator"]
    Worker["Queue worker"]
    Record[("sessions · runs · events<br/>approvals · checkpoints · ledger")]
    Agent["Your agent<br/>instructions + tools"]
    Conversation[("conversations")]
    Provider["Model provider"]
    Frontend["Frontend"]
    Approver["Approver"]

    Controller -->|queue a run| Coordinator
    Coordinator -->|after commit| Worker
    Worker -->|under a lease| Coordinator
    Coordinator --> Record
    Coordinator -->|run a turn| Agent
    Agent --> Conversation
    Agent --> Provider
    Record -->|replay, then live| Frontend
    Record -->|outlives the worker| Approver
    Approver -->|resumes the run| Coordinator

    classDef yours fill:#4f46e5,stroke:#3730a3,color:#ffffff
    classDef harness fill:#0f766e,stroke:#115e59,color:#ffffff
    classDef ai fill:#b45309,stroke:#92400e,color:#ffffff

    class Controller,Frontend,Approver yours
    class Coordinator,Worker,Record harness
    class Agent,Conversation,Provider ai

Indigo is yours. Teal is the harness. Amber is Laravel AI.

Laravel AI talks to the model, runs the tool loop, and remembers the conversation. The harness decides when a turn starts, what gets recorded, who may approve what, when to stop, and how to pick the work back up. Your application starts the work, renders progress, and decides who approves.

Durability comes from a few unglamorous rules. The queue job is dispatched only after the run’s state commits. Events are written before they are broadcast. An approval resolved in a completely separate process is what wakes the run back up.

What one turn does

   $session->prompt(…)
        │
        ├─ createRun ─────────────── run.created        ← one active run per session, held by a row lock
        ├─ acquire session lease ─────────────────────  ← one worker, or the job exits
        ├─ restore checkpoint ────────────────────────  ← the conversation the last turn left
        ├─ transition to running ── run.started
        │
        │   ┌─ driver: Laravel AI stream ──────────────┐
        │   │  step.started                            │
        │   │  text.delta × n                          │
        │   │  tool.call.requested   ← ledger checks   │  budgets checked at each
        │   │  tool.call.completed     idempotency     │  boundary; cancellation
        │   │  step.completed                          │  observed before a new step
        │   └──────────────────────────────────────────┘
        │
        ├─ store checkpoint ──────── checkpoint.created
        ├─ usage.updated
        └─ commit terminal state ── run.completed       ← state, result and event commit together;
                                                          the active-run slot clears in the same write

If the agent hits a tool that needs approval, the middle of that sequence ends at run.awaiting_approval, the worker exits, and everything resumes from the checkpoint once a decision arrives.


Back to top

A community package, not affiliated with or endorsed by Laravel. Released under the MIT licence.

This site uses Just the Docs, a documentation theme for Jekyll.