Understand the Context and Identity system for managing storage isolation, session tracking, and data scoping in LarAgent
The Context system in LarAgent provides a unified way to manage storage isolation, session tracking, and data scoping across agents and users. It serves as the central orchestration layer that connects agents with their storage backends.
Use session-based creation when you need to manage conversations by a custom session key rather than user identity. This is ideal for anonymous users, guest sessions, or when you want explicit control over session naming.
Copy
// Create agent with a specific session key$agent = SupportAgent::for('session-123');// Create agent with random session key$agent = SupportAgent::make();// Access identity$identity = $agent->context()->getIdentity();echo $identity->getChatName(); // 'session-123'echo $identity->getAgentName(); // 'SupportAgent'
Use user-based creation to automatically tie conversations to authenticated users. The identity key will include the user ID, enabling easy querying and management of all conversations for a specific user.
Copy
// Create agent for authenticated user$agent = SupportAgent::forUser($request->user());// Create agent for specific user ID$agent = SupportAgent::forUserId('user-123');// Access identity$identity = $agent->context()->getIdentity();echo $identity->getUserId(); // 'user-123'echo $identity->getAgentName(); // 'SupportAgent'
Use fromIdentity() to recreate an agent instance from a previously tracked identity. This is useful for admin panels, background jobs, or any scenario where you need to operate on existing conversations.
Copy
use LarAgent\Facades\Context;// Get an identity from storage$identity = Context::of(SupportAgent::class) ->forUser('user-123') ->first();// Reconstruct the agent from identity$agent = SupportAgent::fromIdentity($identity);// The agent is now configured with the same session context$response = $agent->respond('Continue our conversation...');
Groups enable shared context between multiple agents. When a group is set, the storage key uses the group name instead of the agent name.
Key format without group:{scope}_{agentName}_{userId|chatName|'default'}Key format with group:{scope}_{group}_{userId|chatName|'default'}
This is useful for multi-tenant applications where agents should share context within a tenant, or when you want multiple agent types to work with the same conversation history.
For runtime group resolution (e.g., based on current tenant):
Copy
class TenantSupportAgent extends Agent{ public function group(): ?string { return tenant()->id ?? null; }}
The group setting applies to all storages by default. To use different groups for specific storages (e.g., group usage but not chat history), override createChatHistory() or createUsageStorage() with a custom identity.
Custom identity for specific storage
Copy
use LarAgent\Context\SessionIdentity;use LarAgent\Context\Storages\ChatHistoryStorage;class MyAgent extends Agent{ protected $group = 'shared-group'; // Default group for all storages // Override to use agent-specific identity for chat history (no grouping) public function createChatHistory() { $identity = new SessionIdentity( agentName: $this->getAgentName(), chatName: $this->getChatKey(), userId: $this->getUserId(), group: null, // No group - uses agentName instead ); return new ChatHistoryStorage( $identity, $this->historyStorageDrivers(), $this->storeMeta ?? false ); }}
Or, alternatively, you can override to set group only for specific storage instead using $group property.
You can access the context object directly from an agent:
Copy
// Get the context instance$context = $agent->context();// Get the base identity$identity = $context->getIdentity();// Get the context identity (used for IdentityStorage)$contextIdentity = $context->getContextIdentity();
The contextIdentity is the general identity of the agent. It is stored in IdentityStorage and holds all other storage identities associated with the agent.
// Save all dirty storages$context->save();// Read all storages from drivers$context->read();// Clear all storages (marks as dirty, sets to empty)$context->clear();// Remove all storages completely$context->remove();
// Get all tracked storage keys$keys = $agent->getStorageKeys();// ['chatHistory_SupportAgent_user-123', 'usage_SupportAgent_user-123', ...]// Get chat history keys only$chatKeys = $agent->getChatKeys();// Get chat history identities$chatIdentities = $agent->getChatIdentities();
use LarAgent\Events\IdentityStorage\IdentityAdding;use LarAgent\Events\IdentityStorage\IdentityAdded;use LarAgent\Events\IdentityStorage\IdentityStorageSaving;use LarAgent\Events\IdentityStorage\IdentityStorageSaved;use LarAgent\Events\IdentityStorage\IdentityStorageLoaded;// Before identity is addedEvent::listen(IdentityAdding::class, function ($event) { $identity = $event->identity; // Can modify or validate});// After identity is added (only when actually new)Event::listen(IdentityAdded::class, function ($event) { $identity = $event->identity; Log::info('New session tracked', ['key' => $identity->getKey()]);});