← Back to Blog
Building AI Apps with PHP

Building AI Apps with PHP

You don't need Python. You need the right library.

PHP developers build ambitious applications with Laravel and Symfony every day. But the moment AI enters the picture, the conventional wisdom says: switch to Python.

Why? The hard part of AI — training models, running inference at scale — is handled by providers like Anthropic, OpenAI, and Google behind simple HTTP APIs. What's left is application-level work: calling those APIs, managing conversations, orchestrating tool use, streaming responses. That's web development. That's what PHP does every day.

PapiAI

PapiAI is an open-source PHP library for building AI agents. Zero runtime dependencies in its core. 10 LLM providers. A proper agentic runtime with tool calling, structured output, middleware, and streaming. It works in any PHP application — standalone scripts, Laravel, Symfony, or no framework at all.

The idea is simple: write your agent logic once, and swap the underlying model by changing a single constructor argument.

What it looks like

Here's a Laravel controller that streams AI responses with tool calling — a customer support agent that can look up orders in your database:

<?php

use PapiAI\Core\Agent;
use PapiAI\Core\Tool;
use PapiAI\Core\StreamEvent;
use App\AI\Tools\OrderLookup;

$agent = Agent::build()
    ->provider(app('papi'))
    ->model('claude-sonnet-4-20250514')
    ->instructions('You are a support agent for Acme Corp.')
    ->tools(Tool::fromClass(new OrderLookup()))
    ->maxTurns(8)
    ->create();

return response()->stream(function () use ($agent, $message) {
    foreach ($agent->streamEvents($message) as $event) {
        match ($event->type) {
            StreamEvent::TYPE_TEXT => $this->sendSSE('text', $event->text),
            StreamEvent::TYPE_TOOL_CALL => $this->sendSSE('tool', $event->tool),
            StreamEvent::TYPE_DONE => null,
            default => null,
        };
    }
}, headers: ['Content-Type' => 'text/event-stream']);

The OrderLookup tool is a plain PHP class. The agent decides when to call it based on the conversation. PapiAI executes the tool, feeds the result back to the LLM, and continues — all inside a single streamEvents() call.

Tools are defined with PHP attributes:

<?php

use PapiAI\Core\Attributes\Tool;
use PapiAI\Core\Attributes\Description;

class OrderLookup
{
    #[Tool('Find an order by its ID to check status and shipping')]
    public function find(
        #[Description('The order ID, e.g. ORD-12345')] string $orderId,
    ): string {
        $order = Order::where('order_id', $orderId)->first();

        return json_encode([
            'status' => $order->status,
            'shipped_at' => $order->shipped_at?->toDateString(),
        ]);
    }
}

No Python. No microservices. No language switching. Just PHP.

What's included

PapiAI ships with providers for Anthropic, OpenAI, Google Gemini, Ollama, Mistral, Groq, Grok, DeepSeek, Cohere, and Azure OpenAI. Plus ElevenLabs for text-to-speech.

The library includes a Zod-inspired schema system for structured output, a composable middleware pipeline (retry, rate limiting, caching, logging), conversation persistence, embeddings, and official bridges for both Laravel and Symfony.

The book

I've written a practical guide that walks through building two complete AI applications from scratch:

It covers everything from architecture and prompt design to security, testing, and deployment.

Read it on LeanPub →

Get started

composer require papi-ai/papi-core papi-ai/anthropic

That's all you need.

Documentation · GitHub · Book