Stop juggling AI SDKs in PHP — meet Prisma Prisma is a lightweight, MIT-licensed PHP package (version 0.4) that provides a unified API for integrating over 25 AI providers across text, image, audio, and video domains, eliminating the need for multiple separate SDKs. It uses a consistent fluent interface—`Prisma::{domain}()->using(provider, config)->{method}()`—allowing developers to switch providers by changing a single string, and supports features like structured output, tool calling, and runtime capability checks. The package requires PHP 8.2+ and relies on Guzzle under the hood, with no framework coupling. If you've ever integrated an AI provider into a PHP application, you know the drill. You pull in the OpenAI SDK. Then the client wants image generation, so you add StabilityAI — different SDK, different request format, different error handling. Then they want audio transcription — enter Deepgram, yet another integration. Before you know it, you're maintaining three separate API integrations, each with their own quirks, response formats, and retry logic. Prisma fixes this. One package. One API. 25+ providers. Text, image, audio, and video. composer require aimeos/prisma Prisma is a light-weight, MIT-licensed PHP package that provides a unified interface for working with AI providers across four media domains. No framework coupling. Just Guzzle under the hood, PHP 8.2+, and a clean fluent API. Here's the core idea — every provider works through the same interface: use Aimeos\Prisma\Prisma; // Generate text with OpenAI $text = Prisma::text - using 'openai', 'api key' = '...' - write 'Summarize the benefits of renewable energy' - text ; // Generate an image with StabilityAI $image = Prisma::image - using 'stabilityai', 'api key' = '...' - imagine 'a mountain landscape at sunset' - binary ; // Transcribe audio with Deepgram $transcript = Prisma::audio - using 'deepgram', 'api key' = '...' - transcribe $audioFile - text ; // Describe a video with Gemini $description = Prisma::video - using 'gemini', 'api key' = '...' - describe $videoFile - text ; Same pattern everywhere: Prisma::{domain} - using provider, config - {method} . Switch providers by changing a single string. Your application code stays the same. Imagine you're building a product listing tool. You need to: Without Prisma, that's three different SDK integrations. With Prisma: use Aimeos\Prisma\Prisma; use Aimeos\Prisma\Schema\Schema; // 1. Describe a product image $description = Prisma::image - using 'openai', 'api key' = '...' - describe $productPhoto - text ; // 2. Extract structured data $schema = Schema::for 'product', 'name' = Schema::string - required , 'price' = Schema::number , 'category' = Schema::string - enum 'electronics', 'clothing', 'food', 'other' , ; $product = Prisma::text - using 'gemini', 'api key' = '...' - structured "Extract product info from: {$description}", $schema - structured ; // 'name' = 'Wireless Headphones', 'price' = 79.99, 'category' = 'electronics' // 3. Generate a product image $image = Prisma::image - using 'stabilityai', 'api key' = '...' - imagine "Professional illustration of {$product 'name' }" - binary ; Three providers, three media types, one consistent API. And if tomorrow you want to swap Gemini for Anthropic, you change one line. You can also check provider capabilities at runtime: $provider = Prisma::image - using 'clipdrop', 'api key' = '...' ; if $provider- has 'upscale' { $image = $provider- upscale $lowResImage - binary ; } // Or throw if the capability is missing $provider- ensure 'upscale' ; // throws NotImplementedException if not supported Version 0.4 is a major release that adds text generation, structured output, tool calling, and a lot more. Here's what landed. The write method brings text generation to Prisma with support for OpenAI, Anthropic, Gemini, Bedrock, Mistral, Groq, Cohere, Deepseek, Alibaba, xAI, Perplexity, OpenRouter, Ollama, and Deepseek. All multimodal — pass images, audio, or documents alongside your prompt: use Aimeos\Prisma\Base\File; $response = Prisma::text - using 'anthropic', 'api key' = '...' - withSystemPrompt 'You are a helpful assistant' - write 'Describe this image', File::from 'photo.jpg' ; echo $response- text ; Get typed JSON responses from LLMs using a fluent Schema builder. Prisma uses each provider's native structured output API — no prompt engineering hacks: use Aimeos\Prisma\Schema\Schema; $schema = Schema::for 'event', 'title' = Schema::string - required , 'date' = Schema::string - format 'date' - required , 'attendees' = Schema::array - items Schema::string , 'location' = Schema::object 'city' = Schema::string - required , 'country' = Schema::string , , ; $response = Prisma::text - using 'openai', 'api key' = '...' - structured 'Parse: Team meetup on June 15 in Berlin with Alice and Bob', $schema ; $event = $response- structured ; // // 'title' = 'Team meetup', // 'date' = '2026-06-15', // 'attendees' = 'Alice', 'Bob' , // 'location' = 'city' = 'Berlin', 'country' = 'Germany' , // The Schema builder supports strings, integers, numbers, booleans, arrays, objects, enums including PHP BackedEnum , nested objects, required , nullable , min /max , regex pattern , and more. You can also pass raw JSON Schema arrays via Schema::fromArray . This is where things get interesting. Prisma supports full agentic tool calling with an automatic execution loop. You define tools, the model calls them, Prisma executes the handlers and feeds results back — all automatically: use Aimeos\Prisma\Tools; use Aimeos\Prisma\Schema\Schema; $searchTool = Tools::make 'search products', 'Search the product database', Schema::for 'search', 'query' = Schema::string - description 'Search query' - required , 'limit' = Schema::integer - description 'Max results' - min 1 - max 50 , , function array $args : string { $results = ProductSearch::query $args 'query' , $args 'limit' ?? 10 ; return json encode $results ; } ; $response = Prisma::text - using 'openai', 'api key' = '...' - withTools $searchTool - withMaxSteps 5 - write 'Find me the top 3 wireless headphones under $100' ; echo $response- text ; // The model searched, got results, and wrote a summary You can inspect what happened during the tool loop: foreach $response- steps as $step { echo $step- name ; // 'search products' echo $step- arguments ; // 'query' = 'wireless headphones', 'limit' = 3 echo $step- result ; // ' ... search results ... ' } Tools also support: Tools::make ... - max 3 — the tool can only be called 3 times- failed fn $e, $args = 'Fallback message' — catch exceptions gracefully- concurrent — tools run in parallel via pcntl fork - withToolChoice Provider::REQ to force tool useSome providers offer built-in server-side tools like web search and code execution. Prisma normalizes these too: use Aimeos\Prisma\Tools; $response = Prisma::text - using 'anthropic', 'api key' = '...' - withTools Tools::provider 'web search' , Tools::provider 'code execution' , - write 'Search for the latest PHP version and verify it' ; Available provider tools include web search , code execution , file search , web fetch , image generation , and document library — each mapped to the providers that support them. You can mix custom and provider tools in the same request. Already have tools built for Laravel AI or Symfony? Reuse them directly: // Laravel AI / Prism tools $tool = Tools::laravel new MyLaravelTool ; // Symfony AsTool classes $tool = Tools::symfony MySymfonyTool::class ; Enable extended reasoning for models that support it. Prisma automatically maps token counts to each provider's native format: $response = Prisma::text - using 'anthropic', 'api key' = '...' - withThinkingBudget 5000 - withMaxTokens 4096 - write 'Solve this step by step: ...' ; // Access the model's reasoning $thinking = $response- meta 'thinking' ?? null; Normalized citation objects across providers that support them Anthropic, OpenAI, Gemini, Perplexity, xAI : foreach $response- citations as $citation { $citation- title ; // source title $citation- url ; // source URL $citation- text ; // output text that cites this source $citation- source ; // verbatim quote from the source } // Automatic retry with exponential backoff $response = Prisma::text - using 'openai', 'api key' = '...' - withClientRetry 3, fn $attempt, $resp = 100 pow 2, $attempt - write '...' ; // Inspect rate limit headers $limit = $response- rateLimit ; $limit- remaining ; // requests left $limit- retryAfter ; // seconds until reset Here's what's supported for text providers in 0.4: And that's just text. Prisma also covers 9 audio providers speak, transcribe, demix, denoise, revoice, describe , 14 image providers imagine, inpaint, upscale, vectorize, background, erase, and more , and video description via Gemini. composer require aimeos/prisma Minimal example: