{"slug": "adding-an-ai-chatbot-to-your-laravel-app-with-the-openai-api", "title": "Adding an AI Chatbot to Your Laravel App with the OpenAI API", "summary": "A Laravel developer demonstrates how to integrate an AI chatbot into a Laravel application using the OpenAI API and the openai-php/laravel package. The tutorial covers setting up the package, creating a ChatService to handle LLM logic, storing conversation history in the session, and implementing rate limiting. The approach avoids external microservices and relies solely on Laravel and an HTTP API.", "body_md": "Every product I've worked on in the last two years has eventually gotten the same request: *\"Can we add an AI assistant to this?\"* As a Laravel developer, the good news is that shipping a production-ready chatbot takes an afternoon — no Python microservice, no LangChain, just Laravel and an HTTP API.\n\nIn this tutorial we'll build a chatbot that:\n\nThe community-maintained [ openai-php/laravel](https://github.com/openai-php/laravel) package is the de-facto standard:\n\n```\ncomposer require openai-php/laravel\nphp artisan openai:install\n```\n\nAdd your key to `.env`\n\n:\n\n```\nOPENAI_API_KEY=sk-your-key-here\n```\n\n💡 Never commit the key. Use your host's secret manager in production.\n\nKeep the LLM logic out of your controller. Create `app/Services/ChatService.php`\n\n:\n\n``` php\n<?php\n\nnamespace App\\Services;\n\nuse OpenAI\\Laravel\\Facades\\OpenAI;\n\nclass ChatService\n{\n    private const SYSTEM_PROMPT = <<<'PROMPT'\n        You are the helpful assistant for Acme Inc's customer portal.\n        Answer only questions about the product. Be concise.\n        If you don't know the answer, say so and suggest contacting support.\n        PROMPT;\n\n    /**\n     * @param array<int, array{role: string, content: string}> $history\n     */\n    public function reply(array $history, string $userMessage): string\n    {\n        $messages = [\n            ['role' => 'system', 'content' => self::SYSTEM_PROMPT],\n            ...$history,\n            ['role' => 'user', 'content' => $userMessage],\n        ];\n\n        $response = OpenAI::chat()->create([\n            'model' => 'gpt-4o-mini',\n            'messages' => $messages,\n            'max_tokens' => 500,\n        ]);\n\n        return $response->choices[0]->message->content;\n    }\n}\n```\n\nSession-based history keeps things simple — no migrations needed for v1:\n\n``` php\n<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Services\\ChatService;\nuse Illuminate\\Http\\JsonResponse;\nuse Illuminate\\Http\\Request;\n\nclass ChatController extends Controller\n{\n    public function __invoke(Request $request, ChatService $chat): JsonResponse\n    {\n        $validated = $request->validate([\n            'message' => ['required', 'string', 'max:2000'],\n        ]);\n\n        $history = $request->session()->get('chat_history', []);\n\n        $answer = $chat->reply($history, $validated['message']);\n\n        // keep the last 10 exchanges to control token costs\n        $history[] = ['role' => 'user', 'content' => $validated['message']];\n        $history[] = ['role' => 'assistant', 'content' => $answer];\n        $request->session()->put('chat_history', array_slice($history, -20));\n\n        return response()->json(['answer' => $answer]);\n    }\n}\n```\n\nRoute it — **with rate limiting**, because every request costs you money:\n\n``` php\n// routes/web.php\nuse App\\Http\\Controllers\\ChatController;\n\nRoute::post('/chat', ChatController::class)\n    ->middleware(['auth', 'throttle:20,1']); // 20 req/min per user\n```\n\nDrop this into any Blade view — no framework required:\n\n```\n<div id=\"chat\">\n    <div id=\"messages\"></div>\n    <form id=\"chat-form\">\n        <input id=\"chat-input\" type=\"text\" placeholder=\"Ask me anything…\" required />\n        <button type=\"submit\">Send</button>\n    </form>\n</div>\n\n<script>\ndocument.getElementById('chat-form').addEventListener('submit', async (e) => {\n    e.preventDefault();\n    const input = document.getElementById('chat-input');\n    const messages = document.getElementById('messages');\n\n    messages.insertAdjacentHTML('beforeend', `<p><b>You:</b> ${input.value}</p>`);\n\n    const res = await fetch('/chat', {\n        method: 'POST',\n        headers: {\n            'Content-Type': 'application/json',\n            'X-CSRF-TOKEN': document.querySelector('meta[name=\"csrf-token\"]').content,\n        },\n        body: JSON.stringify({ message: input.value }),\n    });\n\n    const { answer } = await res.json();\n    messages.insertAdjacentHTML('beforeend', `<p><b>Bot:</b> ${answer}</p>`);\n    input.value = '';\n});\n</script>\n```\n\nBefore you ship this to real users:\n\n`chat_logs`\n\ntable pays for itself the first time you debug a weird answer.`max_tokens`\n\n`OpenAI::chat()->createStreamed()`\n\n+ Server-Sent Events makes the bot feel 10x faster.*I'm Aditya Kumar ( adityakdevin) — Tech Lead & full-stack developer building AI-powered web products with Laravel, Vue, and LLM APIs. Find me at adityadev.in.*", "url": "https://wpnews.pro/news/adding-an-ai-chatbot-to-your-laravel-app-with-the-openai-api", "canonical_source": "https://dev.to/adityakdevin/adding-an-ai-chatbot-to-your-laravel-app-with-the-openai-api-h0f", "published_at": "2026-07-16 07:32:50+00:00", "updated_at": "2026-07-16 07:37:38.770506+00:00", "lang": "en", "topics": ["artificial-intelligence", "large-language-models", "developer-tools"], "entities": ["OpenAI", "Laravel", "openai-php/laravel", "ChatService", "ChatController"], "alternates": {"html": "https://wpnews.pro/news/adding-an-ai-chatbot-to-your-laravel-app-with-the-openai-api", "markdown": "https://wpnews.pro/news/adding-an-ai-chatbot-to-your-laravel-app-with-the-openai-api.md", "text": "https://wpnews.pro/news/adding-an-ai-chatbot-to-your-laravel-app-with-the-openai-api.txt", "jsonld": "https://wpnews.pro/news/adding-an-ai-chatbot-to-your-laravel-app-with-the-openai-api.jsonld"}}