LarAgent v0.5 Release Notes 🎉
Welcome to LarAgent v0.5! This release makes it easier to turn your Laravel agents into OpenAI‑compatible APIs and gives you more control over how agents behave. It also adds multimodal inputs (images & audio), new drivers, flexible tool usage and better management of chat histories and structured output. Read on for the highlights.
!! Important: Check the upgrade guide: https://blog.laragent.ai/laragent-v0-4-to-v0-5-upgrade-guide/
New features ✨
Expose agents via API -- A new LarAgent\API\Completions
class lets you serve an OpenAI‑style /v1/chat/completions
endpoint from your Laravel app. You simply call the static make()
method with a Request
and your agent class to get a response:
use LarAgent\API\Completions;
public function completion(Request $request)
{
$response = Completions::make($request, MyAgent::class);
// Your custom code
}
Laravel controllers ready to use -- Completions::make
is useful for custom implementations, but for common use cases we already implemented The new SingleAgentController
and MultiAgentController
let you expose one or many agents through REST endpoints without writing boiler‑plate. In your controller, set the $agentClass
(for a single agent) or $agents
(for multiple agents) and optionally $models
to restrict models:
use LarAgent\API\Completions\Controllers\SingleAgentController;
class MyAgentApiController extends SingleAgentController
{
protected ?string $agentClass = \App\AiAgents\MyAgent::class;
protected ?array $models = ['gpt‑4o‑mini', 'gpt-4.1-mini'];
}
For multiple agents:
use LarAgent\API\Completions\Controllers\MultiAgentController;
class AgentsController extends MultiAgentController
{
protected ?array $agents = [
\App\AiAgents\ChatAgent::class,
\App\AiAgents\SupportAgent::class,
];
protected ?array $models = [
'chatAgent/gpt‑4.1‑mini',
'chatAgent/gpt‑4.1‑nano',
'supportAgent', // will use default model defined in agent class
];
}
Both controllers support completion
and models
endpoints to make it compatible with any OpenAI client, such as OpenWebUI. Example of routes registration:
Route::post('/v1/chat/completions', [MyAgentApiController::class, 'completion']);
Route::get('/v1/models', [MyAgentApiController::class, 'models']);
For more details, check the documentation
Server‑Sent Events (SSE) streaming -- When the client sets "stream": true
, the API returns text/event-stream
responses. Each event contains a JSON chunk that mirrors OpenAI's streaming format. Usage data appears only in the final chunk.
Custom controllers -- For full control, call Completions::make()
directly in your own controller and stream the chunks manually.
Multimodal inputs
Image input -- Agents can now accept publicly‑accessible image URLs using the chainable withImages()
method:
$images = [
'https://example.com/image1.jpg',
'https://example.com/image2.jpg',
];
$response = WeatherAgent::for('test_chat')
->withImages($images)
->respond();
Audio input -- Send base64‑encoded audio clips via withAudios()
. Supported formats include wav
, mp3
, ogg
, flac
, m4a
and webm
:
$audios = [
[
'format' => 'mp3',
'data' => $base64Audio,
],
];
echo WeatherAgent::for('test_chat')->withAudios($audios)->respond();
Agent usage enrichment
Custom UserMessage
instances -- Instead of passing a plain string, you can build a UserMessage
with metadata (e.g. user ID or request ID). When using a UserMessage
, the agent skips the prompt()
method:
$userMessage = Message::user($finalPrompt, ['userRequest' => $userRequestId]);
$response = WeatherAgent::for('test_chat')
->message($userMessage)
->respond();
Return message objects -- Call returnMessage()
or set the $returnMessage
property to true
to receive a MessageInterface
instance instead of a plain string. This is useful when you need the model's raw assistant message.
Check "Using an Agent" section
Groq driver
A new GroqDriver works with the Groq Platform API. Add GROQ_API_KEY to your .env file and set the provider to groq to use it. The configuration example in the quick‑start has been updated accordingly.
Contributed by @john-ltc
Tool handling enhancements 🔧
-
Tool selection methods -- You can now control whether tools are used on a per‑call basis:
-
toolNone()
disables tools for the current call. -
toolRequired()
makes at least one tool call mandatory. -
forceTool('toolName')
forces the agent to call a specific tool. After the first call, the choice automatically resets to avoid infinite loops.- Dynamic tool management -- Tools can be added or removed at runtime using
withTool()
andremoveTool()
.
- Dynamic tool management -- Tools can be added or removed at runtime using
-
Parallel tool calls -- The new
parallelToolCalls(true)
method enables or disables parallel tool execution. You can also set the tool choice manually viasetToolChoice('none')
or similar methods. -
Phantom tools -- You can define Phantom Tools that are registered with the agent but not executed by LarAgent; instead they return a
ToolCallMessage
, allowing you to handle the execution externally. Phantom tools are useful for dynamic integration with external services or when tool execution happens elsewhere.
-
use LarAgent\PhantomTool;
$phantomTool = PhantomTool::create('phantom_tool', 'Get the current weather in a location')
->addProperty('location', 'string', 'City and state, e.g. San Francisco, CA')
->setRequired('location')
->setCallback('PhantomTool');
// Register with the agent
$agent->withTool($phantomTool);
Changes 🛠️
-
Chat session IDs -- Model names are no longer included in the chat session ID by default. To retain the old
AgentName_ModelName_UserId
format, set$includeModelInChatSessionId
totrue
. -
Usage metadata keys changed -- Keys in usage data are now snake‑case (
prompt_tokens
,completion_tokens
, etc.) instead of camel‑case (promptTokens
). Update any custom code that reads these keys. -
Gemini streaming limitation -- The Gemini driver currently does not support streaming responses.
Check the upgrade guide
What's Changed
- Bump dependabot/fetch-metadata from 2.3.0 to 2.4.0 by @dependabot[bot] in #33
- Fix toDTO to use agent model by @MaestroError in #40
- Fix docblock typo in Agent.php by @MaestroError in #42
- Fix reinject instructions methods typo by @MaestroError in #43
- Fix SSE stream accumulation by @MaestroError in #41
- Improve streaming response tests by @MaestroError in #44
- Add streaming fallback provider support by @MaestroError in #45
- Fix/store usage while streaming by @MaestroError in #46
- Add additional OpenAI configuration options by @MaestroError in #47
- Bump stefanzweifel/git-auto-commit-action from 5 to 6 by @dependabot[bot] in #53
- Update openai-php/client requirement from ^0.13.0 to ^0.14.0 by @dependabot[bot] in #52
- Extend API request validation rules by @MaestroError in #48
- Add tool choice configuration in Agent by @MaestroError in #54
- Add PseudoTool tests and finalize API tool call handling by @MaestroError in #57
- New setter methods for API and first basic response by @MaestroError in #56
- Add audio modality support for agents by @MaestroError in #55
- [Feature]: Groq driver by @john-ltc in #66
- Manual tests created, readme update by @MaestroError in #67
- Codex/add OpenAI compatible api layer by @MaestroError in #70
- Add comprehensive Completions controller tests by @MaestroError in #71
- Expose any Agent(s) as API endpoint compatible to OpenAI API by @MaestroError in #72
New Contributors
Full Changelog: 0.4.1...0.5.0