Skip to main content
This guide provides comprehensive instructions for migrating your LarAgent project from v0.8 to v1.0. Follow the sections in order, starting with the most critical changes that affect the public API.

Critical Changes

These changes will break your code if not addressed. Review and update these first before upgrading.

Message Factory API Changes

The Message class is now a pure factory class with only typed static factory methods. The following methods have been removed:
Removed MethodStatus
Message::create()❌ Removed
Message::fromArray()❌ Removed
Message::fromJSON()❌ Removed
1

Find Message::create() occurrences

Run this command to locate all usages in your codebase:
grep -rn "Message::create" --include="*.php"
2

Replace with typed factory methods

Update your code to use the new typed factory methods:
$message = Message::create('user', 'Hello');
$message = Message::create('assistant', 'Hi there');
$message = Message::create('system', 'You are helpful');
3

Replace Message::fromArray()

Find occurrences:
grep -rn "Message::fromArray" --include="*.php"
$message = Message::fromArray(['role' => 'user', 'content' => 'Hello']);
4

Replace Message::fromJSON()

Find occurrences:
grep -rn "Message::fromJSON" --include="*.php"
$message = Message::fromJSON($jsonString);

Available Factory Methods

MethodDescription
Message::user($content, $metadata)Create user message
Message::assistant($content, $metadata)Create assistant message
Message::system($content, $metadata)Create system message
Message::developer($content, $metadata)Create developer message
Message::toolCall($toolCalls, $metadata)Create tool call message
Message::toolResult($content, $toolCallId, $toolName, $metadata)Create tool result message

ToolResultMessage Constructor Signature

The ToolResultMessage constructor signature has changed completely. You must provide $toolName for Gemini driver compatibility.
The constructor now accepts $toolName as an optional third parameter.
public function __construct(array $message, array $metadata = [])
1

Find ToolResultMessage usages

grep -rn "new ToolResultMessage" --include="*.php"
2

Update constructor calls

new ToolResultMessage($resultArray, $metadata);
// or
new ToolResultMessage(['content' => $result, 'tool_call_id' => $id], $metadata);

ToolCallMessage Constructor Signature

The ToolCallMessage constructor no longer accepts the $message array parameter.
public function __construct(array $toolCalls, array $message, array $metadata = [])
1

Find ToolCallMessage usages

grep -rn "new ToolCallMessage" --include="*.php"
2

Update constructor calls

new ToolCallMessage($toolCalls, $messageArray, $metadata);
// $messageArray was typically the raw API response array

ChatHistory Interface Changes

If you have custom ChatHistory implementations or directly use ChatHistory methods, this section is critical.

Key Changes

  1. getMessages() now returns MessageArray instead of array
  2. Several methods have been removed from the interface
  3. New truncation system replaces manual context window management

Removed Methods

Removed MethodStatus
setContextWindow(int $tokens)❌ Removed
exceedsContextWindow(int $tokens)❌ Removed
truncateOldMessages(int $messagesCount)❌ Removed
saveKeyToMemory()❌ Removed
loadKeysFromMemory()❌ Removed
removeChatFromMemory(string $key)❌ Removed
1

Update getMessages() usage

$messages = $chatHistory->getMessages(); // returns array
foreach ($messages as $msg) { ... }
2

Replace context window methods

$chatHistory->setContextWindow(50000);
if ($chatHistory->exceedsContextWindow($tokens)) {
    $chatHistory->truncateOldMessages(5);
}
3

Replace chat key management

Use the new Context facade or Agent methods:
use LarAgent\Facades\Context;
use App\AiAgents\MyAgent;

// Option 1: Inside Agent - get chat keys via Agent methods
$agent = MyAgent::for('user-123');
$chatKeys = $agent->getChatKeys();           // Get all chat history keys
$allStorageKeys = $agent->getStorageKeys();  // Get all storage keys
$chatIdentities = $agent->getChatIdentities(); // Get chat identities

// Option 2: Inside Agent - get current session key
$sessionKey = $this->context()->getIdentity()->getKey();
$chatName = $this->context()->getIdentity()->getChatName();

// Option 3: Outside Agent - use Context facade with agent class
$chatKeys = Context::of(MyAgent::class)->getChatKeys();
$storageKeys = Context::of(MyAgent::class)->getStorageKeys();

// Option 4: Outside Agent - use Context facade with agent name
$chatKeys = Context::named('MyAgent')->getChatKeys();
$storageKeys = Context::named('MyAgent')->getStorageKeys();
The Context facade provides powerful filtering and iteration capabilities. See the New Features section for more details.

Agent Class Changes

Removed Properties and Methods

Removed Properties

PropertyReplacement
$includeModelInChatSessionIdRemoved - not supported
$saveChatKeysAutomatic - handled by Context system’s IdentityStorage
$contextWindowSizeUse $truncationThreshold

Removed Methods

MethodReplacement
keyIncludesModelName()Removed - not supported
withModelInChatSessionId()Removed - not supported
withoutModelInChatSessionId()Removed - not supported
createChatHistory(string $sessionId)createChatHistory() (no parameter)

Renamed Methods

The old method names still work but are deprecated. Update to the new names when possible.
Old Method (v0.8)New Method (v1.0)ReturnsDescription
getChatSessionId()getSessionId()stringFull storage key (e.g., AgentName_chatHistory_user-123)
getChatKey()getSessionKey()stringSession key passed to for() (e.g., user-123)

Available Methods

These methods from HasContext trait are available:
MethodReturnsDescription
getSessionId()stringFull storage key
getSessionKey()stringSession key passed to for()
getUserId()?stringUser ID if usesUserId() was called
getAgentName()stringAgent class name
group()?stringGroup name if set
context()ContextAccess to context object
1

Update method calls

$fullKey = $this->getChatSessionId();
$chatKey = $this->getChatKey();
2

Remove includeModelInChatSessionId usage

protected $includeModelInChatSessionId = true;
// and
$agent->withModelInChatSessionId();
$agent->withoutModelInChatSessionId();
3

Replace contextWindowSize with truncationThreshold

protected $contextWindowSize = 50000;

New Context System

LarAgent v1.0 introduces a new Context System that manages all storages (chat history, state, identities) through a unified interface.

New Properties

PropertyTypeDescription
$storagearrayDefault storage drivers for context
$forceReadHistoryboolForce read history on construction
$forceSaveHistoryboolForce save history after each response
$forceReadContextboolForce read context on construction
$trackUsageboolEnable token usage tracking
$usageStoragearrayStorage drivers for usage data
$enableTruncationboolEnable automatic truncation
$this->chatHistory->addMessage($message);
Configure storage drivers in your Agent class:
protected $storage = [
    \LarAgent\Context\Drivers\CacheStorage::class,
];

// Or use the built-in history drivers:
protected $history = 'cache';  // Still works

Config Property Renames

Update your published config file (config/laragent.php):
v0.8 Keyv1.0 Key
default_context_windowdefault_truncation_threshold
chat_history (in provider)history
'providers' => [
    'default' => [
        // ...
        'default_context_window' => 50000,
        'chat_history' => \LarAgent\History\CacheChatHistory::class,
    ],
],
Alternatively, republish the config file:
php artisan vendor:publish --tag=laragent-config --force

Driver and Configuration Changes

DriverConfig DTO for Custom Drivers

This section only affects custom LLM driver implementations.
Driver configurations now use DriverConfig DTO internally instead of plain arrays.
1

Update constructor signature

class MyCustomDriver extends LlmDriver
{
    public function __construct(array $settings = [])
    {
        $this->settings = $settings;
    }
}
2

Update config access

$model = $this->settings['model'];
$apiKey = $this->settings['api_key'];
3

Update sendMessage signatures

public function sendMessage(array $messages, array $options = []): AssistantMessage

Custom ChatHistory Implementations

This section only affects custom ChatHistory classes.
Chat history classes should now extend ChatHistoryStorage instead of the old ChatHistory abstract class.
1

Update your custom history class

use LarAgent\Core\Abstractions\ChatHistory;

class MyCustomHistory extends ChatHistory
{
    public function readFromMemory(): void { /* ... */ }
    public function writeToMemory(): void { /* ... */ }
    public function saveKeyToMemory(): void { /* ... */ }
    public function loadKeysFromMemory(): array { /* ... */ }
    public function removeChatFromMemory(string $key): void { /* ... */ }
    protected function removeChatKey(string $key): void { /* ... */ }
}
2

Create custom StorageDriver (if needed)

If you need custom storage logic, create a custom StorageDriver:
use LarAgent\Context\Contracts\StorageDriver;
use LarAgent\Context\Contracts\SessionIdentity;

class MyStorageDriver implements StorageDriver
{
    public function readFromMemory(SessionIdentity $identity): ?array
    {
        // Your read logic
    }
    
    public function writeToMemory(SessionIdentity $identity, array $data): bool
    {
        // Your write logic
    }
    
    public function removeFromMemory(SessionIdentity $identity): bool
    {
        // Your remove logic
    }
    
    public static function make(?array $config = null): static
    {
        return new static();
    }
}

New Features

These features are new in v1.0 and don’t require migration. Consider using them to enhance your agents.

Message IDs and Timestamps

All messages now have unique IDs and timestamps:
$message = Message::user('Hello');
$id = $message->getId();             // e.g., 'msg_abc123...'
$created = $message->getCreatedAt(); // ISO 8601 timestamp

Message Extras

Store driver-specific or custom fields:
$message->setExtra('custom_field', 'value');
$value = $message->getExtra('custom_field');
$all = $message->getExtras();

Usage Tracking

Enable automatic token usage tracking:
class MyAgent extends Agent
{
    protected $trackUsage = true;
}

Truncation Strategies

Automatic conversation truncation when context exceeds threshold:
class MyAgent extends Agent
{
    protected $enableTruncation = true;
    protected $truncationThreshold = 50000;
    
    // Override to use custom strategy
    protected function truncationStrategy()
    {
        return new SummarizationStrategy();
    }
}

Context Facade

New facade for managing storage outside of agents:
use LarAgent\Facades\Context;
use LarAgent\Context\Storages\ChatHistoryStorage;
use App\AiAgents\MyAgent;

// ========================================
// Entry Point 1: Context::of(AgentClass::class)
// Full agent-based context access (creates temporary agent)
// ========================================

// Get all chat keys for an agent
$chatKeys = Context::of(MyAgent::class)->getChatKeys();
$storageKeys = Context::of(MyAgent::class)->getStorageKeys();

// Fluent filtering API
$count = Context::of(MyAgent::class)
    ->forUser('user-123')
    ->forStorage(ChatHistoryStorage::class)
    ->count();

// Iterate with full agent access
Context::of(MyAgent::class)
    ->forUser('user-123')
    ->each(function ($identity, $agent) {
        // $identity is SessionIdentityContract
        // $agent is fully initialized Agent instance
        $agent->chatHistory()->clear();
    });

// Clear/remove operations
Context::of(MyAgent::class)->clearAllChats();           // Clear all chat data
Context::of(MyAgent::class)->removeAllChats();          // Remove all chat entries
Context::of(MyAgent::class)->clearAllChatsByUser('user-123');
Context::of(MyAgent::class)->removeAllChatsByUser('user-123');

// Get first matching agent
$agent = Context::of(MyAgent::class)->forUser('user-123')->firstAgent();

// ========================================
// Entry Point 2: Context::named('AgentName')
// Lightweight access (no agent initialization)
// ========================================

// Get keys without creating agent instances
$chatKeys = Context::named('MyAgent')->getChatKeys();
$storageKeys = Context::named('MyAgent')->getStorageKeys();

// Custom driver configuration
$count = Context::named('MyAgent')
    ->withDrivers([CacheStorage::class])
    ->forUser('user-123')
    ->count();

// Clear chats (lightweight - no agent needed)
Context::named('MyAgent')->clearAllChats();
Context::named('MyAgent')->removeAllChats();

DataModel Classes

Use DataModels for structured output:
class MyResponse extends DataModel
{
    #[Desc('The answer to the question')]
    public string $answer;
    
    #[Desc('Confidence level 0-100')]
    public int $confidence;
}

class MyAgent extends Agent
{
    protected $responseSchema = MyResponse::class;
}

// Response is automatically reconstructed as MyResponse instance
$response = MyAgent::ask('What is 2+2?');
$response->answer;     // "4"
$response->confidence; // 95

Quick Migration Checklist

Use this checklist to ensure you’ve covered all migration steps.
  • Replace all Message::create() with typed factory methods
  • Replace all Message::fromArray() with specific message class fromArray()
  • Update ToolResultMessage constructor calls to include $toolName
  • Update ToolCallMessage constructor calls to remove $message parameter
  • Replace $contextWindowSize with $truncationThreshold
  • Remove $saveChatKeys (now automatic via Context system)
  • Remove $includeModelInChatSessionId and related method calls
  • Update provider config default_context_windowdefault_truncation_threshold
  • Update provider config chat_historyhistory
  • If custom drivers: update constructor to call parent::__construct($settings)
  • If custom chat history: refactor to use ChatHistoryStorage with custom driver

Getting Help

If you encounter issues during migration: