Guides & field notes

Queue and recover research in Laravel

Store a Run before dispatch, observe it by Run ID, and recover in-progress research without duplicate submissions.

Prepare shared storage

Follow installation, configure Exa, and choose a durable supported store. Your application owns workers, authorization, retention, and domain records.

Before dispatch Requirement
Store Shared durable storage, not memory or ArrayStore
Worker Process the configured queue; default research
Other runtimes MCP or JavaScript can resume stored deep research, not Laravel jobs

Preview before dispatch

use Jkudish\LaravelAiLibrarium\Facades\Librarium;

$question = 'Compare PostgreSQL pooling for workers';
$plan = Librarium::research($question)
    ->deep()->only(['exa'])->maxCost('0.50')
    ->dryRun();

Dry-run is offline and stores nothing; inspect estimates, selected sources, skips, and notices. Keep your cap when reviewing an empty preview (budget rules).

Queue the research

$queued = Librarium::research($question)
    ->deep()->only(['exa'])->maxCost('0.50')
    ->queue()->onQueue('research');

$id = $queued->id();
// In a later authorized request:
$run = Librarium::find($id)?->refresh();
$payload = $run?->toArray();

Authorize the Run ID before reading it; refresh() observes existing work, not a new submission. Persist only needed domain facts and keep status, failures, citations, and uncertainty visible; package storage is not your evidence model.

Recover without duplicate spend

The encrypted job has one attempt; worker loss can leave paid upstream work running. Inspect the stored Run and use refresh() before considering another submission (recovery reference).

Failure Recovery boundary
Calling process stops Inline work depends on that process staying alive
Saved state or signing key lost Recovery needs valid state and stable private keys
Local writer crashes Remove its marker only after proving it cannot resume; age is not enough

Test without provider calls

config()->set('librarium.sources.exa.key', 'testing-only');
$fake = Librarium::fake()->preventStrayQueries();

Librarium::research('Produce a report')
    ->deep()->only(['exa'])->queue();
$fake->assertQueued('Produce a report');
$fake->assertNeverQueried();

Queued fakes record requests without dispatching jobs; assertion closures receive request arrays. Use Laravel’s queue fake and disposable stores for infrastructure tests (testing reference).