A run that takes twenty minutes will meet a queue worker timeout. Rather than being killed part-way through a step, a run can hand the turn back at a safe boundary and be re-queued to continue:

Clutch::agent(ResearchAgent::class)
    ->for($user)
    ->sliceAfterSeconds(240)   // below your worker's timeout
    ->create();

Each slice checkpoints, records a run.suspended event, and queues the continuation. Usage accumulates across slices, so a run cut into ten pieces still meets its budget as one run.

Workflows slice too, and for them the boundary is a step. The runtime hands the turn back at the first step (or wave) past the budget, the run suspends with everything finished already persisted, and the continuation re-enters handle() with those steps cached — so a workflow whose wall-clock exceeds any single worker’s timeout completes as a chain of sub-timeout jobs instead of being killed mid-flight:

ProduceReport::start()
    ->for($user)
    ->sliceAfterSeconds(1500)   // below a 1800s worker timeout
    ->dispatch(['report_id' => $id]);

Or set clutch.limits.max_seconds_per_slice once and every bounded driver inherits it. Two rules keep slicing safe: replayed steps never count toward a slice, so a resumed workflow cannot suspend without progressing; and a slice always completes at least one step, so a budget tighter than a single step still moves forward one step per job.

Slicing needs a driver that can park a turn and pick it up again. The bundled laravel-ai driver cannot: Laravel AI runs a turn to completion, and abandoning it part-way discards the work rather than parking it. Asking that driver to slice fails with CapabilityUnsupported before the run starts, which is the same promise the package makes everywhere else.


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.