How to Build an AI Chatbot in PHP
A PHP AI chatbot uses server-side cURL to call a model API, a session or database to store the message history, and explicit controls on any tools the model can request. Here is how to build each part.
Updated 4 min read
A PHP AI chatbot sends POST requests to a model API using cURL, keeps a conversation history in a PHP session or a database, and handles any tool calls the model returns. The core pattern is simple. What makes it reliable is managing the message history correctly, controlling what tools the model can use, and handling the errors that come from any external HTTP dependency. If the chatbot is part of a project your team works on, a tool like fenbs can provide shared context — decisions, tasks, and progress — through an MCP client.
What you need before starting
You need PHP 8.1 or later with the cURL extension enabled (it is on by default in most hosts), an API key from your model provider stored in an environment variable or a secrets file outside the web root, and a way to store session data between requests. PHP sessions work for a single-user prototype; a database or a cache like Redis works better when multiple users need separate conversation histories.
Structuring the conversation history
The model API expects the full conversation history in every request, as an array of messages. Each message is an associative array with role and content keys. The first message is the system instruction. Each user turn adds a user message, and each model response adds an assistant message.
<?php
session_start();
if (!isset($_SESSION['messages'])) {
$_SESSION['messages'] = [
['role' => 'system', 'content' => 'You are a helpful assistant.'],
];
}
$userInput = trim($_POST['message'] ?? '');
if ($userInput !== '') {
$_SESSION['messages'][] = ['role' => 'user', 'content' => $userInput];
}After each API call, append the assistant reply to $_SESSION['messages'] so the next request includes it. Limit the array length to stay within the model's context window. Keep the system message and truncate the oldest user and assistant messages when the count grows large.
Making the API call with cURL
Use curl_init, set CURLOPT_RETURNTRANSFER to true, and pass the JSON-encoded messages body with the correct Content-Type and Authorization headers. Decode the response with json_decode. Check for curl_error before reading the response body.
- Set
CURLOPT_TIMEOUTto a reasonable value (30 to 60 seconds) to avoid hanging requests. - Check the HTTP status code with
curl_getinfo($ch, CURLINFO_HTTP_CODE)before parsing the body. - Handle a 429 status (rate limit) by returning a user-friendly message and logging the error.
- Never log the full request body if it contains user input that could include personal data.
Handling tool calls
When the model wants to call a tool, the response body contains a tool_calls array instead of a plain content string. Your PHP code checks for that field, looks up the matching function, runs it, appends the result as a tool message, and calls the API again in the same request cycle.
Keep the list of tools short and their permissions narrow. A tool that reads from a database is safer than one that writes to it. A tool that looks up a product is safer than one that processes a payment. Define the minimum set of tools the chatbot needs to complete its task and document each one clearly.
Storing and loading history across sessions
PHP sessions are tied to a session cookie and expire when the browser closes or after the session.gc_maxlifetime limit. For a chatbot where users expect their history to persist across days, store the messages in a database table keyed on a user ID and a conversation ID. Load the history at the start of each request and save it after the response is appended.
Testing your PHP chatbot before deploying
Before connecting the chatbot to a frontend or any user-facing flow, test the API call and message history logic from the command line. Write a small CLI script that sends a fixed sequence of messages and prints the response each time. Check that the message history accumulates correctly, that the system message stays at index zero, and that the truncation logic removes complete pairs rather than cutting arbitrarily.
Test each tool function independently with known inputs before using it inside the chatbot loop. The model generates arguments in varied formats; your function should validate them before executing. A tool that returns a clear error string on bad input is far easier to debug than one that throws an exception mid-conversation. Log every tool call name and the arguments it received during development, and confirm the model is calling the right tool with reasonable values before you ship.
Supply project context to your PHP chatbot
If this chatbot is part of a larger project, add a fenbs project with the Decisions and rules that govern what the chatbot may do and the tasks you are working on. Connect a supported AI coding tool over MCP from Integrations. It reads the project context at the start of each coding session, so you do not have to restate the constraints in every conversation.
Create a free accountFree for one person · No credit card · Works with Claude, ChatGPT, Cursor and more
How to do this with fenbs
- Create a free account and add a project for the chatbot product.
- Add Decisions and rules for the chatbot: which tools it may call, what topics it must avoid, the review requirement before deploying changes.
- Add tasks for each feature or conversation flow. Note the current status and any open questions.
- Connect a supported AI coding tool from Integrations. It reads the project context before each coding session.
- Ask the assistant to save its progress before finishing each session so the next one starts from Where we left off.
For the same pattern in other server-side languages, see how to build a JavaScript AI chatbot for Node.js and how to build a Java AI chatbot for Java. The API call structure and message format are the same; only the HTTP client syntax differs.