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
Agents
particle-academy/prism
claude-code
cursor
tools
error-handling
upstream
security-review
satellites
architecture

The core package: a unified shuttle to eighteen LLM provider APIs.

Install
php artisan boost:add-skill particle-academy/prism

Save this content to: AGENTS.md

# AGENTS.md — particle-academy/prism

The core package: a unified shuttle to eighteen LLM provider APIs.

> **Read [the shared guide](https://github.com/Particle-Academy/prism-parity/blob/main/docs/AGENTS.md)
> first.** It carries the boundary, the gates, the decisions that bind every
> repository here, and the review skills. This file is only what is true of
> *this* one.
>
> The model itself — pending requests, the provider contract, message value
> objects, request mapping, response parsing, errors — is documented **once**, in
> [`prism-parity/docs/patterns/`](https://github.com/Particle-Academy/prism-parity/tree/main/docs/patterns).
> Link there. Do not restate it here or in `docs/`.

## This is a fork, and that changes how you work

`origin` is `Particle-Academy/prism`. `upstream` is `prism-php/prism`. This is
the actively maintained fork, and a meaningful share of incoming work is
absorbed from upstream rather than authored here.

**Every upstream absorption goes through `pr-security-review` before it
merges** — not because upstream is hostile, but because an absorbed change
arrives with the reviewer's attention already spent on whether it merges
cleanly. Absorbed PRs have previously shipped large features with tests that
could never actually run.

```sh
git fetch upstream +refs/pull/N/head:refs/heads/pr-N
git diff main...pr-N          # workflows and composer FIRST, then source
```

## What must not land here

**Core is a shuttle, not an agent framework.** The rule and the satellite map
are in the shared guide; what matters at this end is that the pressure to break
it always arrives as a small, reasonable-looking convenience.

The test is not "is this useful" — it is **"do all eighteen providers now owe
this forever?"** If yes, and it is agentic, it belongs in a satellite. Sessions,
memory, workspaces, MCP brokering, telemetry export and retrieval all already
have homes, and none of those homes is here.

**Core depends on no satellite.** A `require` pointing outward from this
package is the boundary inverting.

## The two Tool behaviours that surprise integrators

Both are load-bearing, both have bitten, and neither is guessable from the
method name.

**`as()` is an instance method, not a static constructor.**

```php
(new Tool)->as('search')->for('…')->using(fn () => …);   // right
Tool::as('search')                                        // fatal
```

**`handle()` catches an exception from your handler and RETURNS a `ToolError`.**
It does not propagate. The signature says so —
`handle(): string|ToolOutput|ToolError` — and an integration that only catches
exceptions will treat that failure object as a successful result and hand it to
a model as data. `prism-mcp` and `prism-harness` both have explicit branches for
it; anything new that invokes tools needs one too.

## Unsupported means throw

A provider asked for a capability it does not have **raises**. It never returns
successfully having quietly done less.

This is not a style preference. A run that completes with a capability silently
dropped is indistinguishable, from the outside, from a model that chose not to
use it — and that ambiguity is precisely what the Perplexity `withTools()`
incident cost days to. Decision
[0011](https://github.com/Particle-Academy/prism-parity/blob/main/docs/decisions/0011-when-silence-is-allowed.md)
records when silence is nonetheless allowed; it is a short list.

## Changes the ports can see

`prism-ts` and `prism-py` mirror the text capability, and the shared corpus in
`prism-parity/suites/` is what notices when they stop matching. **PHP is the
reference implementation**: goldens are generated by executing this code, never
hand-authored.

So a change to request mapping, response parsing, error codes, or value-object
serialisation is not finished when this suite is green. It is finished when the
corpus is updated in the same breath. Otherwise the ports drift, and the only
mechanism that would have caught it is the one that was skipped.

## Gates

```sh
composer test      # pest --parallel
composer types     # phpstan
composer format    # pint --parallel, then rector
```

CI runs `tests`, `phpstan`, `formatting` and `require-checker` as four separate
jobs. All four, locally, before pushing.

## Documentation

`docs/` is the published user-facing site, and `docs/documentation-style-guide.md`
governs it. It is written for people **using** Prism.

It is not the place for ecosystem rules, decisions, or the shared model — those
live in `prism-parity` and are linked, so that there is one copy to keep true.

The **human** contribution process — branching, Conventional Commits, issue and
PR etiquette — is [`.github/CONTRIBUTING.md`](.github/CONTRIBUTING.md), and it
applies to you too. This file does not repeat it.

## Releasing

Complete the [release preflight](.github/RELEASING.md), including strict
factcheck CI on the exact candidate SHA, before pushing any tag.

Run **`prerelease-audit`** over the diff since the previous tag before you cut
one. It is a release gate, not a formality, and it has blocked releases before.

Sandbox dogfoods dev releases (`-alpha.N`) ahead of stable. Remember that
Composer will not resolve a prerelease from `minimum-stability` alone — the
constraint floor itself has to be a prerelease.

AGENTS.md — particle-academy/prism

The core package: a unified shuttle to eighteen LLM provider APIs.

Read the shared guide first. It carries the boundary, the gates, the decisions that bind every repository here, and the review skills. This file is only what is true of this one.

The model itself — pending requests, the provider contract, message value objects, request mapping, response parsing, errors — is documented once, in prism-parity/docs/patterns/. Link there. Do not restate it here or in docs/.

This is a fork, and that changes how you work

origin is Particle-Academy/prism. upstream is prism-php/prism. This is the actively maintained fork, and a meaningful share of incoming work is absorbed from upstream rather than authored here.

Every upstream absorption goes through pr-security-review before it merges — not because upstream is hostile, but because an absorbed change arrives with the reviewer's attention already spent on whether it merges cleanly. Absorbed PRs have previously shipped large features with tests that could never actually run.

git fetch upstream +refs/pull/N/head:refs/heads/pr-N
git diff main...pr-N          # workflows and composer FIRST, then source

What must not land here

Core is a shuttle, not an agent framework. The rule and the satellite map are in the shared guide; what matters at this end is that the pressure to break it always arrives as a small, reasonable-looking convenience.

The test is not "is this useful" — it is "do all eighteen providers now owe this forever?" If yes, and it is agentic, it belongs in a satellite. Sessions, memory, workspaces, MCP brokering, telemetry export and retrieval all already have homes, and none of those homes is here.

Core depends on no satellite. A require pointing outward from this package is the boundary inverting.

The two Tool behaviours that surprise integrators

Both are load-bearing, both have bitten, and neither is guessable from the method name.

as() is an instance method, not a static constructor.

(new Tool)->as('search')->for('…')->using(fn () => …);   // right
Tool::as('search')                                        // fatal

handle() catches an exception from your handler and RETURNS a ToolError. It does not propagate. The signature says so — handle(): string|ToolOutput|ToolError — and an integration that only catches exceptions will treat that failure object as a successful result and hand it to a model as data. prism-mcp and prism-harness both have explicit branches for it; anything new that invokes tools needs one too.

Unsupported means throw

A provider asked for a capability it does not have raises. It never returns successfully having quietly done less.

This is not a style preference. A run that completes with a capability silently dropped is indistinguishable, from the outside, from a model that chose not to use it — and that ambiguity is precisely what the Perplexity withTools() incident cost days to. Decision 0011 records when silence is nonetheless allowed; it is a short list.

Changes the ports can see

prism-ts and prism-py mirror the text capability, and the shared corpus in prism-parity/suites/ is what notices when they stop matching. PHP is the reference implementation: goldens are generated by executing this code, never hand-authored.

So a change to request mapping, response parsing, error codes, or value-object serialisation is not finished when this suite is green. It is finished when the corpus is updated in the same breath. Otherwise the ports drift, and the only mechanism that would have caught it is the one that was skipped.

Gates

composer test      # pest --parallel
composer types     # phpstan
composer format    # pint --parallel, then rector

CI runs tests, phpstan, formatting and require-checker as four separate jobs. All four, locally, before pushing.

Documentation

docs/ is the published user-facing site, and docs/documentation-style-guide.md governs it. It is written for people using Prism.

It is not the place for ecosystem rules, decisions, or the shared model — those live in prism-parity and are linked, so that there is one copy to keep true.

The human contribution process — branching, Conventional Commits, issue and PR etiquette — is .github/CONTRIBUTING.md, and it applies to you too. This file does not repeat it.

Releasing

Complete the release preflight, including strict factcheck CI on the exact candidate SHA, before pushing any tag.

Run prerelease-audit over the diff since the previous tag before you cut one. It is a release gate, not a formality, and it has blocked releases before.

Sandbox dogfoods dev releases (-alpha.N) ahead of stable. Remember that Composer will not resolve a prerelease from minimum-stability alone — the constraint floor itself has to be a prerelease.

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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route