SYS://VISION.ACTIVE
VIEWPORT.01
LAT 28.0222° N
SIGNAL.NOMINAL
VISION Loading
Back to Blog

Building AI Agents with Laravel: Autonomous Task Completion

Shane Barron

Shane Barron

Laravel Developer & AI Integration Specialist

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.

Share this article
Shane Barron

Shane Barron

Strategic Technology Architect with 40 years of experience building production systems. Specializing in Laravel, AI integration, and enterprise architecture.

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