Documentation
AssayConnecting your apps
Updated
An application reports to Assay through the artisan-build/assay-client Composer package. The package listens to laravel/ai, turns what it sees into telemetry records, and ships them to Assay from a queued job. Scalpels can wire this connection up for a Laravel Cloud environment or Laravel Forge site and open the client-install pull request for you.
Requirements
- Laravel 13 in the reporting application.
laravel/ai1.x. The client does not requirelaravel/ai, but without it the client registers no listeners and records nothing.- A queue worker in the reporting application. Telemetry is shipped from queued jobs, so without a worker it stays pending.
Attach the app
Follow Attach to an existing app and choose your Assay deployment as the provider. For Assay, attaching does the following.
Scalpels mints a new assay.ingest credential on your Assay deployment for that one application and writes these values into the application's Laravel Cloud environment or Forge .env:
| Key | Value |
|---|---|
ASSAY_URL |
Your Assay deployment's full ingest URL, ending in /ingest. |
ASSAY_TOKEN |
The application's ingest credential. |
BFC_CLIENT_IDENTITY |
The id of the connection Scalpels recorded. |
Scalpels then opens a draft pull request on the branch scalpels/connect-assay that:
- adds
artisan-build/assay-client(^1.0) tocomposer.json; - adds
ASSAY_URLandASSAY_TOKENto.env.example, with the token left blank.
Check out the branch, run the composer update command shown in the pull request, commit composer.lock, then review, merge and deploy. Scalpels never merges the pull request for you. Until the package is deployed, the application sends nothing.
Package discovery registers the client's service provider. You do not need to publish its configuration unless you want per-agent sampling rates; for those, run php artisan vendor:publish --tag=assay-config in the reporting application and configure config/assay.php.
For an application that runs somewhere Scalpels cannot write to, the provider's connected-apps screen in Scalpels can generate a credential by hand. It shows the composer require line and the environment lines once, ready to paste. Scalpels does not keep the token.
Set a subject (optional)
To break usage down by user, tenant or anything else, and to be able to erase one later, put an opaque identifier in Laravel Context before the AI call starts:
use Illuminate\Support\Facades\Context;
Context::add('assay.subject', 'user:123');
The client reads the subject once when a run starts and applies it to the whole run tree. Context set before a job is dispatched travels into that queued job. Assay never resolves the value, so use something that means nothing on its own. Runs without a subject are stored as unknown.
Verify the connection
- Trigger an AI call in the reporting application.
- Make sure its queue worker processes the
ShipEnvelopejob. - Open
/assay/dashboardin Assay. The application appears in Pipeline Health under the subject reference you chose, and its usage appears in Usage Over Time for today.
Pipeline Health also shows two cumulative counters reported by the client: transport drops (deliveries that failed for good) and hook drops (records your payload filter dropped). A rising transport-drop count with no data means the client cannot deliver; see Troubleshooting.
How delivery works
The client never sends telemetry during your request. It projects each event to plain data, runs your payload filter, and queues an encrypted ShipEnvelope job. The job posts the batch to Assay, retrying every 60 seconds for up to 24 hours by default. A delivery that still fails is deleted and counted as a transport drop; its payload is never left in the reporting application's failed_jobs table. If Assay answers that a batch is too large, the client splits it and retries the halves. A broken telemetry path never throws into your application.