Laravel SDK

Report cost, latency, and quality for the AI agents in your Laravel app. If you use laravel/ai, every prompt, model step, tool call, failover, failure and embedding is captured automatically, no code changes. The SDK is non-blocking and never throws into your app.

Install

composer require agentping/laravel

Set your API key. The ingest region is read from the key, so there is nothing else to configure:

AGENTPING_API_KEY=apk_eu_...

Requires PHP 8.2+. The service provider is auto-discovered.

Already exporting OpenTelemetry? The same agents can reach Agent Ping over OTLP instead; see Laravel AI SDK with OpenTelemetry for the trade-offs.

Automatic instrumentation

With laravel/ai installed, the SDK listens to the framework's lifecycle events and turns each agent invocation into a run:

$reply = (new SalesCoach)->prompt('Score this email: ...');  // captured automatically

A prompt that calls a tool in the middle becomes a timeline of three events: the model call that asked for the tool, the tool call with its arguments and result, and the model call that produced the answer. Each model call carries its own tokens and is priced on the server, so the run's cost is the sum of what the provider billed.

laravel/ai event Agent Ping event What is recorded
StepCompleted llm_call Provider, model, input and output tokens (plus cached, cache-creation and reasoning tokens when non-zero), latency, step number, finish reason.
StepFailed llm_call with status: error The exception message and class. The run stays open; the prompt may retry or fail over.
ToolInvoked, ToolFailed tool_call Tool name, arguments, result, latency, and status: error with the exception when the tool threw.
ProviderFailedOver, AgentFailedOver step (provider_failover) The provider and model given up on and the reason. Not an error; the next llm_call shows who served the prompt.
AgentFailed error The exception that ended the invocation. The run finishes with status error.
AgentPrompted, AgentStreamed llm_call Only for single-step prompts with no step events, so tokens are never counted twice. Streams carry stream: true.
EmbeddingsGenerated llm_call Provider, model and input tokens.

Prompt and completion text are off by default; AGENTPING_CAPTURE_LLM_CONTENT=true adds the prompt as input, the system prompt as system_instructions and the response text as output to each llm_call, clipped at AGENTPING_LLM_CONTENT_MAX_CHARS. laravel/ai stream events carry whole-second timestamps, so this SDK cannot report ttft_ms. Tool arguments and results are sent by default, because they are what makes a tool call readable on the timeline; turn that off or cap it if your tools handle sensitive data:

AGENTPING_CAPTURE_TOOL_PAYLOADS=false
AGENTPING_TOOL_PAYLOAD_MAX_CHARS=4000

An agent that calls another agent through a tool attaches to the outer run, so one user request stays one run named after the outermost agent. When your code has opened a run with AgentPing::run(), every invocation inside it attaches there instead of starting its own.

Disable auto-instrumentation any time with AGENTPING_LISTEN_TO_AI_SDK=false.

Naming your agents

Runs are grouped by agent name in Spend and Pulse. The name is resolved in this order:

  1. An active run: AgentPing::run('name') or AgentPing::agent('name', fn () => ...).
  2. AgentPing::useAgent('name'): set once at the top of a request, job, or command; every auto-captured call in that scope uses it (reset automatically afterwards).
  3. A named Agent class: a laravel/ai Agent class like MorningBriefing is auto-named morning_briefing, no extra code.
  4. AGENTPING_DEFAULT_AGENT (default ai-agent).

The anonymous agent($prompt)->prompt(...) helper carries no name, so for those calls use one of the first two. Either name the whole scope once:

use AgentPing\Laravel\Facades\AgentPing;

AgentPing::useAgent('morning-briefing');
$summary = agent($systemPrompt)->prompt($userMessage, provider: 'anthropic');

or wrap a single call to also group it as one run:

$summary = AgentPing::agent('morning-briefing', fn () =>
    agent($systemPrompt)->prompt($userMessage, provider: 'anthropic')
);

If you define your agents as classes instead of the agent() helper, naming is automatic.

Manual tracking

For agents that do not use laravel/ai, track runs directly:

use AgentPing\Laravel\Facades\AgentPing;

$run = AgentPing::run('support-triage', customerId: 'acme', feature: 'ticket-routing');

$run->event('llm_call', [
    'provider' => 'anthropic',
    'model' => 'claude-sonnet-4-6',
    'input_tokens' => 1200,
    'output_tokens' => 480,
]);

$run->finish('success', scores: ['confidence' => 0.92]);

Nest sub-agents by passing parentRunId: (or set the AGENTPING_PARENT_RUN env var) to build a run tree.

Heartbeats

For cron jobs and scheduled tasks, report one completion per run:

AgentPing::heartbeat('daily-summary', status: 'ok', costUsd: 0.084, durationMs: 12_300);

Guard

Before a scheduled command or queued job starts, ask the control plane whether it should. guardCheck compares your real spend against the rules you set and honours the pause switch on the dashboard:

use AgentPing\Laravel\Exceptions\Paused;

try {
    AgentPing::guardCheck(customerRef: 'acme-corp', agent: 'nightly-summariser', function: 'run');
} catch (Paused $e) {
    return; // $e->verdict says which rule tripped
}

Pass mode: 'soft' to get the verdict back instead of an exception, and onUnreachable: 'allow' to run when the gate cannot be reached (the default is to block). Guard is on the Team and Business plans; see Guard.

Queue workers

Telemetry flushes automatically at the end of each web request, console command, and queued job. Restart Horizon and your queue workers after deploying so they load the new code and key. For a custom long-running loop, call AgentPing::flush().

Configuration

Variable Default Description
AGENTPING_API_KEY required Region-scoped team key (apk_...).
AGENTPING_DEFAULT_AGENT ai-agent Name for un-named auto-captured calls.
AGENTPING_LISTEN_TO_AI_SDK true Auto-instrument laravel/ai.
AGENTPING_CAPTURE_TOOL_PAYLOADS true Send tool arguments and results on tool_call events.
AGENTPING_TOOL_PAYLOAD_MAX_CHARS 4000 Truncate each tool argument list and result at this length.
AGENTPING_PARENT_RUN optional Parent run id for nesting.
AGENTPING_VERSION optional Build or prompt version label for every run; AgentPing::run(..., version: ...) overrides it per run.
AGENTPING_CAPTURE_LLM_CONTENT false Send the prompt, system prompt and response text on llm_call events.
AGENTPING_LLM_CONTENT_MAX_CHARS 4000 Truncate each captured piece at this length.

Run php artisan vendor:publish --tag=agentping-config for the full config (queue size, batch size, timeouts, control URL). Use a team key for the SDK; ping_... tokens are for URLs only.

Source on GitHub, changelog. Requires laravel/ai 0.11 or later for the step and tool events; older versions still report AgentPrompted.