Skip to content

Cost tracking

Record Cloudflare neurons per call with the WorkersAiUsageReported event or the raw response.

Updated

Cloudflare meters Workers AI in neurons, not tokens. Every model call returns a neuron figure, in usage.neurons or a cf-ai-neurons header. A cost model built on token counts gives the wrong number.

The Laravel AI usage objects (Usage, TextUsage) and Meta have no field for neurons. The package gives you two ways to read them: an event and the raw response.

Listen for the event

The package dispatches Meirdick\WorkersAi\Events\WorkersAiUsageReported once per model call. This covers chat, embeddings, Clef, Clairic, images, speech, transcription and reranking. A tool loop with two steps dispatches two events.

use Illuminate\Support\Facades\Event;
use Meirdick\WorkersAi\Events\WorkersAiUsageReported;

Event::listen(WorkersAiUsageReported::class, function (WorkersAiUsageReported $event) {
    Spend::record($event->model, $event->neurons);
});

The event has these public properties:

Property Type Description
provider string The provider name from your config.
model string The model name sent to Cloudflare. On /compat it has the workers-ai/ prefix.
neurons float The neuron count for this call.
promptTokens int Uncached prompt tokens on chat, on both laravel/ai lines. The reported input count on run API calls.
completionTokens int Completion tokens.
reasoningTokens int Reasoning tokens.

The package dispatches nothing when the reply has no neuron figure, or the figure is 0.

Streamed requests

The event fires for streamed requests too (since 1.0.1). It fires once per model call, after the last chunk, with the call total. Cloudflare sends usage.neurons on every stream chunk. Early chunks hold a per-chunk figure and the last chunk holds the total. The package uses the last figure and does not add the chunks. A streamed tool loop dispatches one event per step.

$response->raw is not set on a stream. Use the event.

Read the raw response

The HTTP response is on the Laravel AI response, and on each step of a tool loop:

$response = agent('You are a helpful assistant.')->prompt('...', provider: 'workers-ai');

$neurons = $response->raw?->json('usage.neurons');
$latency = $response->raw?->transferStats?->getTransferTime();

This needs a laravel/ai version where StepResponse has withRawResponse(). On laravel/ai 0.9, raw is null. Use the event there.

Token counts by laravel/ai line

The usage object on the response differs by version. The event does not.

// laravel/ai 0.9 to 0.11: promptTokens excludes cached tokens
$response->usage->promptTokens;
$response->usage->completionTokens;
$response->usage->cacheReadInputTokens;

// laravel/ai 1.x: inputTokens includes cached tokens
$response->usage->inputTokens;
$response->usage->outputTokens;
$response->usage->cacheReadInputTokens; // null when absent

See AI Gateway for a measured example.

Calls on the run API

Clef, Clairic, images, speech, transcription and reranking use /ai/run. They dispatch the same event, with provider, model and neurons. promptTokens and completionTokens hold the counts the model reports, as Cloudflare sends them. Speech and binary images report no tokens, so those fields are 0.

A $response->raw is not available on these calls. Use the event. Token counts are on the response where the model reports them:

$response->usage->inputTokens;   // laravel/ai 1.x
$response->usage->promptTokens;  // laravel/ai 0.9 to 0.11

Cloudflare prices Clef and Clairic per input token, with no charge for output. See the pricing page below.

Order of magnitude

Reasoning costs neurons. Measured on 2026-09-09 on one account: on @cf/openai/gpt-oss-120b, one two-sentence prompt cost 9.6 neurons at reasoning_effort: low and 31.4 at high. A 16-token completion on @cf/meta/llama-3.3-70b-instruct-fp8-fast cost 4.48 neurons.

Pricing

For the price per neuron and the free allowance, see the Cloudflare Workers AI pricing page.

Type to search…

↑↓ navigate↵ selectEsc close