Support the ongoing development of Laravel.io →
Article Hero Image

LarAgent: An Open-source package to Build & Manage AI Agents in Laravel

10 Apr, 2025 7 min read

Photo by Sumaid pal Singh Bakshi on Unsplash

Laravel has all the right ingredients to become a strong candidate for AI development. With its elegant architecture and built-in components, it has huge potential to become a go-to framework for AI-driven applications.

There are existing PHP packages like LLPhant and Prism that already simplify interactions with large language models (LLMs). However, Laravel still lacks a tool for building and managing AI agents. That’s where LarAgent comes in. Inspired by LangChain - a widely used framework for building AI agents in Python - I’m Revaz Ghambarashvili, Lead Developer at Redberry. I created a Laravel-native solution that brings the same flexibility and ease of use to PHP developers. LarAgent is designed to simplify the process of creating, managing, and extending AI agents while staying true to Laravel’s fluent API design.

Under the hood, LarAgent uses the OpenAI PHP package by Nuno Maduro and Sandro Gehri, which simplifies communication between your application and LLM’s API.

In this article, I’ll walk you through all of LarAgent’s key features and how they make AI agent development in Laravel more intuitive than ever.

Standout Features of LarAgent

Eloquent-like syntax for creating and managing AI agents

The first standout feature of LarAgent is that the process of creating AI agents is just like creating any other Eloquent model.

php artisan make:agent MyAgent

LarAgent brings the same smooth syntax and class structure that Laravel developers are familiar with. Its low learning curve and user-friendly design make it easy to get started. The process of creating and managing AI agents feels natural, just like working with Laravel’s artisan commands. You’ll feel right at home with LarAgent’s familiar structure; in fact, that’s what makes AI agent development extremely intuitive with this package.

// app/AiAgents/MyAgent.php
class MyAgent extends Agent
{
    protected $model = 'gpt-4';

    protected $history = 'in_memory';

    protected $provider = 'default';

    protected $tools = [];

    public function instructions()
    {
        return "Define your agent's instructions here.";
    }

    public function prompt($message)
    {
        return $message;
    }
}

Structured Output Handling

Structured output allows you to define the exact format of the agent's response using JSON Schema. Schema has to be defined in the OpenAPI standard.

The main purpose is to get a predictable, structured response from LLM with the pre-defined schema that can be used in your application logic.

In the case of LarAgent, you just need to add the protected $responseSchema property, and your agent will automatically handle returned JSON from LLM, so that the responses from the respond method will be array adhering to your specified schema instead of strings.

protected $responseSchema = [
    'name' => 'weather_info',
    'schema' => [
        'type' => 'object',
        'properties' => [
            'temperature' => [
                'type' => 'number',
                'description' => 'Temperature in degrees'
            ],
        ],
        'required' => ['temperature'],
        'additionalProperties' => false,
    ],
    'strict' => true,
];

For defining more complex schemas you can add the public function structuredOutput() method to your agent class, build it up with custom logic, and return an array of the schema.

Multiple built-in chat history storage options

Chat history is essential for maintaining context in AI conversations. It accumulates every interaction the user has with the agent, so each new message needs to be sent along with the entire conversation history to preserve context.

LarAgent simplifies this process by offering several built-in chat history storage options, while also allowing you to implement your own custom storage solutions. Whether you prefer cache storage or a different method, LarAgent gives you flexibility in how chat history is managed, ensuring your AI agents maintain context across sessions.

  • in_memory
  • Session
  • Cache
  • File
  • JSON

The “in_memory” and “JSON” chat histories will work even if you use LarAgent outside of Laravel framework.

Easily extendable, including chat histories and LLM drivers

The structure of this package allows you to add a new element (for example, a new chat history) quickly and easily. Each element has its abstraction, which can be extended by adding a couple of methods. For example, to make a new type of chat history, you will need to extend the LarAgent\Core\Abstractions\ChatHistory class and implement these methods:

  • readFromMemory
  • writeToMemory
  • saveKeyToMemory:
  • loadKeysFromMemory
  • removeChatFromMemory
  • removeChatKey

As an example, you can check the ”LarAgent\History\InMemoryChatHistory” which is a minimalistic implementation of this feature and makes it easy to understand each needed method.

Custom tool creation with attribute-based configuration

Tools are essential for extending the capabilities of AI agents. They help the agent decide the best way to respond based on user input. For instance, if you ask an agent about the current weather, it might use several tools in parallel: one to identify your location, another to fetch the weather data for that location, and a third to let you choose the unit for the temperature (Celsius or Fahrenheit). This process, called parallel tool execution, allows the agent to run multiple tools at the same time while responding to a single user query, providing a more accurate and efficient response. LarAgent makes it easy to create custom tools with attribute-based configuration, giving you full control over how your agent uses and manages these tools. Users have different versions of creating the tools - Standalone classes, Tool facade, and Tool attributes. Creating tool classes is a recommended way of using tools since they give the highest level of control and reusability.

class WeatherTool extends LarAgent\Tool
{
    protected string $name = 'get_current_weather';

    protected string $description = 'Get the current weather in a given location';

    protected array $properties = [
        'location' => [
            'type' => 'string',
            'description' => 'The city and state, e.g. San Francisco, CA',
        ],
        'unit' => [
            'type' => 'string',
            'description' => 'The unit of temperature',
            'enum' => ['celsius', 'fahrenheit'],
        ],
    ];

    protected array $required = ['location'];

    public function execute(array $input): mixed
    {
        // Call the weather API
        return 'The weather in '.$input['location'].' is '.rand(10, 60).' degrees '.$input['unit'];
    }
}

Can be registered via your agent's property:

protected $tools = [
    WeatherTool::class,
    LocationTool::class
];

Another way is to add the registerTools method and return an array of tools created via the LarAgent\Tool class. This is the simplest way of adding new tools. While setCallback allows any callable type in PHP, according to experience this is ideal for the creation of small, simple tools:

use LarAgent\Tool;
// ...
public function registerTools() 
{
    $user = auth()->user();
    return [
        Tool::create("user_location", "Returns user's current location")
             ->setCallback(function () use ($user) {
                  return $user->location()->city;
             }),
    ];
}

And yet another, but my favorite way of adding tools is a Tool attribute, which automatically builds names, property types and enums, you only need to specify the descriptions and any method of your agent class will become a tool:

Use LarAgent\Attributes\Tool;

class WeatherAgent extends LarAgent\Agent {
// …
// Example of a tool defined as a method with optional and required parameters
    #[Tool('Get the current weather in a given location')]
    public function weatherTool($location, $unit = 'celsius') {
        return WeatherService::get($location)->withUnit($unit);
    }
}

The best part is that you can use all three ways of adding tools in one agent simultaneously.

Extensive Event system

Often, packages doing the heavy lifting for you are struggling when a project needs to implement a really custom solution and tweak some deeply nested processes. LarAgent provides a comprehensive event system to address this issue that allows you to hook into almost any stage of the agent's lifecycle and conversation flow.

You can add hook methods to your agent’s class, which provide some inner context and are called at appropriate places. Here are several methods you can use:

  • onInitialize()
  • onConversationStart()
  • onConversationEnd($message)
  • onToolChange($tool, $added = true)
  • beforeSaveHistory($history)
  • beforeResponse($history, $message)
  • afterResponse($message)
  • afterToolExecution($tool, &$result)

For more events and examples, please refer to the documentation’s Events section.

Hope this article gave you a clear look at the LarAgent package and how it can simplify AI agent development in Laravel. Can’t wait to see it in action in your projects.

Last updated 4 days ago.

driesvints liked this article

1
Like this article? Let the author know and give them a clap!

Other articles you might like

Article Hero Image April 8th 2025

Covariance and Contravariance in PHP

Introduction "Covariance" and "contravariance" are two terms I didn't know exist...

Read article
Article Hero Image April 2nd 2025

Human-Readable File Sizes in Laravel (KB, MB, GB)

Introduction There may be times when you want to display file sizes to your users in a human-readabl...

Read article
Article Hero Image March 31st 2025

Formatting and Spelling Ordinal Numbers in PHP and Laravel

Introduction There may be times when you want to convert numbers to ordinal numbers in your PHP and...

Read article

We'd like to thank these amazing companies for supporting us

Your logo here?

Laravel.io

The Laravel portal for problem solving, knowledge sharing and community building.

© 2025 Laravel.io - All rights reserved.