Laravel AI Agents in Production: Tool Calling Pattern Cuts Chatbot Limit
These articles are AI-generated summaries. Please check the original sources for full details.
Building AI Agents in PHP: Tool Calling with Laravel
Aditya Kumar, a Laravel tech lead, published a pattern for building AI agents with tool calling in Laravel. His production order-support agent averages under a cent per resolved conversation on GPT-4.1-mini.
Why This Matters
Chatbots that can only generate text confidently fabricate data like order counts or shipping statuses. Kumar’s tool-calling pattern grounds AI responses in real database queries and services via a controlled loop, with costs averaging under a cent per conversation on GPT-4.1-mini, replacing engineer time that cost more per minute.
Key Insights
- Tool calling allows AI models to execute real functions like database queries, not just generate text.
- Authorization must live in the tool code (e.g., auth()->id() in OrderLookupTool), not in prompts, because attackers can steer tool selection via crafted inputs.
- MAX_ROUNDS is critical: a loop cap of 5 prevents the model from ping-ponging between tools indefinitely and burning tokens.
- Return errors as tool results instead of throwing exceptions—models handle failures gracefully and retry with fixed arguments.
- Token costs are 3–5x a plain chat reply per round; keep tool schemas tight and register only context-relevant tools.
- Tool registry mapping names to classes enables validation and error handling in a single execute() method.
Working Examples
Tool contract interface defining the structure for AI tools in Laravel.
interface Tool
{
public function name(): string;
public function description(): string;
/** JSON Schema for the arguments the model may pass. */
public function parameters(): array;
/** @param array $args validated arguments from the model */
public function handle(array $args): string;
}
Example of a real Laravel tool that looks up orders with authorization scoping.
class OrderLookupTool implements Tool
{
public function name(): string
{
return 'order_lookup';
}
public function description(): string
{
return 'Look up an order by its number. Returns status, items, and shipping info.';
}
public function parameters(): array
{
return [
'type' => 'object',
'properties' => [
'order_number' => [
'type' => 'string',
'description' => 'The order number, e.g. ORD-2041',
],
],
'required' => ['order_number'],
];
}
public function handle(array $args): string
{
$order = Order::where('number', $args['order_number'])
->where('user_id', auth()->id()) // ← the line that matters
->first();
if (! $order) {
return json_encode(['error' => 'Order not found for this account.']);
}
return json_encode([
'number' => $order->number,
'status' => $order->status,
'items' => $order->items->pluck('name'),
'shipped_at' => $order->shipped_at?->toDateString(),
]);
}
}
AgentRunner loop that executes up to 5 rounds of tool calls with OpenAI API integration.
class AgentRunner
{
private const MAX_ROUNDS = 5;
public function __construct(private ToolRegistry $tools) {}
public function run(array $messages): string
{
foreach (range(1, self::MAX_ROUNDS) as $round) {
$response = Http::withToken(config('services.openai.key'))
->timeout(30)
->post('https://api.openai.com/v1/chat/completions', [
'model' => 'gpt-4.1-mini',
'messages' => $messages,
'tools' => $this->tools->schemas(),
])->throw()->json('choices.0.message');
if (empty($response['tool_calls'])) {
return $response['content'] ?? '';
}
$messages[] = $response;
foreach ($response['tool_calls'] as $call) {
$result = $this->tools->execute(
$call['function']['name'],
json_decode($call['function']['arguments'], true) ?? [],
);
$messages[] = [
'role' => 'tool',
'tool_call_id' => $call['id'],
'content' => $result,
];
}
}
return 'I could not complete that in a reasonable number of steps.';
}
}
Practical Applications
- Use case: Order lookup in Laravel support agents using OrderLookupTool. Pitfall: Missing authorization scoping inside tool handle()—the model is an untrusted caller that can be steered by crafted prompts.
- Use case: Report generation or shipping status checks in production apps. Pitfall: Omitting MAX_ROUNDS causes infinite loops and high token costs—every round carries full conversation history plus tool schemas.
References:
Continue reading
Next article
Agentic Coding Shifts Dev Work to Strategy, Demands Human Taste and Community Feedback
Related Content
Scaling AI Agents with Model Context Protocol: A Production REX for 87 Connected Tools
Deploying 87 tools via Anthropic's Model Context Protocol (MCP) reveals that strict typing and circuit breakers are critical for production AI systems.
SVI: A New CLI Tool to Streamline Prompt Engineering for AI-Assisted Coding
Developer Aleksandr Razinkin builds SVI, a Markdown-based CLI tool that automates prompt assembly for ChatGPT, reducing manual context gathering and enabling copy/paste or API workflows.
Lessons from Running 100+ AI Agents in Production: Scaling Rate Limits and Costs
AI Buddy reveals how production context windows can cost $3.00 per conversation and why Anthropic rate limits hit entire accounts simultaneously at scale.