Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Prism Laravel Package

particle-academy/prism

A Laravel package for rendering beautifully highlighted code blocks with Prism.js. Use Blade components to add fast, accessible, zero-config syntax highlighting to docs, blogs, and apps, with support for many languages and themes.

View on GitHub
Deep Wiki
Context7

Getting Started

Prism is the LLM integration layer for Laravel: one fluent API in front of OpenAI, Anthropic, Gemini, Ollama, and others, with first-class support for streaming, tool calling, and structured output.

composer require prism-php/prism
php artisan vendor:publish --tag=prism-config

Add the credentials for the provider(s) you actually use to .env (e.g. OPENAI_API_KEY, ANTHROPIC_API_KEY) and confirm the defaults in config/prism.php. Nothing else is required to make a first call.

Where to look first:

  1. config/prism.php — provider list, default models, timeouts, retry behaviour.
  2. The Prism\Prism\Facades\Prism facade — the entry point for every request (Prism::text(), Prism::structured(), Prism::embeddings()).
  3. Prism\Prism\Streaming\* — the event objects and helpers you will touch the moment a feature needs streaming.

First use case — a controller action that answers a prompt:

use Prism\Prism\Facades\Prism;
use Prism\Prism\Enums\Provider;

$response = Prism::text()
    ->using(Provider::OpenAI, 'gpt-4o-mini')
    ->withSystemPrompt('You are a terse assistant.')
    ->withPrompt($request->string('question'))
    ->asText();

return $response->text;

Once that works, the second thing to build is the streaming variant, because that is where this package's shape (and its churn) becomes visible.

Implementation Patterns

Wrap Prism calls in a small application service. Controllers should not know about providers or model names. Put model selection and system prompts behind a class like App\Services\Assistant, inject it, and keep Prism:: calls in one layer. Swapping gpt-4o-mini for a cheaper model or a local Ollama driver then becomes a config change rather than a grep.

Stream to the browser over SSE. The usual Laravel shape is a route returning text/event-stream, iterating the stream, and flushing each chunk:

return response()->stream(function () use ($prompt) {
    $stream = Prism::text()
        ->using(Provider::Anthropic, 'claude-sonnet-4-5')
        ->withPrompt($prompt)
        ->asStream();

    foreach ($stream as $event) {
        echo "data: " . json_encode($event->toArray()) . "\n\n";
        ob_flush(); flush();
    }

    echo "data: [DONE]\n\n";
}, 200, [
    'Content-Type' => 'text/event-stream',
    'X-Accel-Buffering' => 'no',
    'Cache-Control' => 'no-cache',
]);

Aggregate streamed events on the server when you need a persisted message. This is the case that StreamCollector existed for, and the release under review restores it. Use StreamedMessages::fromEvents() as the forward-looking path:

use Prism\Prism\Streaming\StreamedMessages;

$events   = iterator_to_array($stream);
$messages = StreamedMessages::fromEvents($events);

// persist $messages to a conversations/messages table

The collector is still available and signature-compatible with pre-v0.132.0 code — same constructor, same collect(), same callback — so existing integrations do not have to change today. It now builds messages via StreamedMessages, so it emits the current stream shape: one StepFinishEvent per step (not per token) and one StreamEndEvent at the end, with each step's replay metadata preserved. That matters if you were persisting raw events and replaying them later — the step boundaries are what make tool-call steps reconstructable.

Migrate to StreamedMessages::fromEvents() when convenient, not in a panic. StreamCollector is deprecated, not removed. A sensible sequence: keep shipping, add a test that exercises your streaming aggregation path, then swap the class in a dedicated PR. Because both produce the same message shape today, the swap is mechanical.

Tool calling as a normal workflow. Define tools as classes, attach them with ->withTools([...]), and let Prism run the loop with ->withMaxSteps(n). Because each step now surfaces its own StepFinishEvent, you can log per-step token usage and tool inputs without post-processing the whole blob.

Fake it in tests. Do not hit real providers in the suite. Assert on the fluent builder arguments and stub the response objects; for streaming tests, feed a hand-built array of events into StreamedMessages::fromEvents() / StreamCollector and assert on the resulting messages. This is exactly the pattern that caught the v0.132.0 regression — prism-harness's streaming tests were the signal.

Gotchas and Tips

Silent removals happen; pin and read changelogs. v0.132.0 dropped Prism\Prism\Streaming\StreamCollector via an upstream merge without mentioning it in the release notes. Any project on a floating ^0.x constraint that ran composer update broke at runtime with Class "Prism\Prism\Streaming\StreamCollector" not found — not at install time, which is the dangerous part. For a 0.x package, either pin exact-ish ("prism-php/prism": "0.133.*") or make composer update a reviewed step with a smoke test that exercises streaming. A Class not found after a routine update is the signature of this class of problem, so check the diff before debugging your own code.

v0.133.1 is a safe upgrade. No breaking changes; StreamCollector is back with identical constructor, collect(), and callback signatures, and its output is now aligned with the current stream shape. If you were pinned below v0.132.0 and skipped it, you can move to v0.133.1 directly and get the newer per-step event semantics for free — but test your aggregation, since your previously persisted event sequences will look different (more StepFinishEvents, one terminal StreamEndEvent).

Do not build new code against StreamCollector. It exists for compatibility and is explicitly deprecated in favour of StreamedMessages::fromEvents(). New work should use the latter; treat the collector as a shim with a removal date you cannot see.

Debug streams by dumping events, not strings. Streaming bugs are almost always event-shape bugs. Log the event class names in order for a single request and compare against expectations (text deltas, tool call events, one step-finish per step, one stream end). If you see multiple StreamEndEvents or a StepFinishEvent per delta, you are on an older shape.

Watch the buffering layers. SSE in Laravel behind nginx/Octane needs X-Accel-Buffering: no, disabled output buffering, and no response middleware that tries to inspect the body. Symptom: everything works locally and arrives in one lump in production.

Budgets and retries belong in config, not in the codebase. Set timeouts and retry counts per provider in config/prism.php; wrap long-running calls in queued jobs with an explicit max-steps cap so a runaway tool loop cannot burn through a monthly quota.

Extension points to remember: custom providers/drivers if you need a self-hosted endpoint, tool classes for anything with side effects (validate inputs before they hit your DB), and the event objects themselves if you need to post-process usage or cost per step.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource