Back to Blog
Building AI Agents with Laravel: Autonomous Task Completion
From Chatbots to Agents
AI agents go beyond simple question-answering. They can plan multi-step tasks, use tools, make decisions, and adapt when things don't go as expected. Building agents requires a different architecture than simple AI integrations.
The Agent Loop
class Agent
{
private array $tools = [];
private array $memory = [];
public function execute(string $goal): AgentResult
{
$this->memory[] = ['role' => 'user', 'content' => $goal];
while (!$this->isGoalComplete()) {
// Think: Decide next action
$action = $this->think();
if ($action['type'] === 'complete') {
return new AgentResult(
success: true,
output: $action['output'],
steps: $this->memory
);
}
// Act: Execute the action
$result = $this->act($action);
// Observe: Record the result
$this->observe($action, $result);
}
}
private function think(): array
{
$response = $this->ai->chat([
['role' => 'system', 'content' => $this->buildSystemPrompt()],
...$this->memory,
], ['tools' => $this->getToolDefinitions()]);
return $this->parseAction($response);
}
}
Defining Tools
class SearchTool implements AgentTool
{
public function getName(): string
{
return 'search_database';
}
public function getDescription(): string
{
return 'Search the product database for items matching criteria';
}
public function getParameters(): array
{
return [
'type' => 'object',
'properties' => [
'query' => ['type' => 'string', 'description' => 'Search query'],
'category' => ['type' => 'string', 'description' => 'Product category'],
'max_price' => ['type' => 'number', 'description' => 'Maximum price'],
],
'required' => ['query'],
];
}
public function execute(array $params): string
{
$products = Product::query()
->where('name', 'like', "%{$params['query']}%")
->when($params['category'] ?? null, fn ($q, $cat) => $q->where('category', $cat))
->when($params['max_price'] ?? null, fn ($q, $price) => $q->where('price', '<=', $price))
->limit(10)
->get();
return $products->toJson();
}
}
Planning Complex Tasks
class TaskPlanner
{
public function plan(string $goal): array
{
$prompt = <<formatTools()}
Return as JSON:
{
"steps": [
{"action": "tool_name", "reason": "why this step", "dependencies": []}
]
}
PROMPT;
return json_decode($this->ai->generate($prompt), true);
}
}
Error Recovery
private function act(array $action): mixed
{
try {
$tool = $this->tools[$action['tool']];
return $tool->execute($action['params']);
} catch (Exception $e) {
// Let the agent know about the error
return [
'error' => true,
'message' => $e->getMessage(),
'suggestion' => 'Try a different approach or ask for clarification',
];
}
}
private function observe(array $action, mixed $result): void
{
$this->memory[] = [
'role' => 'assistant',
'content' => null,
'tool_calls' => [
['function' => ['name' => $action['tool'], 'arguments' => json_encode($action['params'])]],
],
];
$this->memory[] = [
'role' => 'tool',
'content' => is_string($result) ? $result : json_encode($result),
];
}
Safety Guardrails
class AgentGuardrails
{
private int $maxSteps = 20;
private array $forbiddenActions = ['delete_all', 'send_mass_email'];
public function check(array $action, int $stepCount): void
{
if ($stepCount > $this->maxSteps) {
throw new AgentLimitException('Maximum steps exceeded');
}
if (in_array($action['tool'], $this->forbiddenActions)) {
throw new ForbiddenActionException("Action {$action['tool']} is not allowed");
}
}
}
Conclusion
AI agents represent the next evolution in AI applications. They require careful design around planning, tool use, error handling, and safety. Start with constrained domains and expand capabilities gradually.
Related Articles
Need Help With Your Project?
I respond to all inquiries within 24 hours. Let's discuss how I can help build your production-ready system.
Get In Touch