> ## Documentation Index
> Fetch the complete documentation index at: https://docs.laragent.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Identity

> 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.

## Core Components

The Context system consists of four key components:

<CardGroup cols={2}>
  <Card title="SessionIdentity" icon="fingerprint">
    Uniquely identifies a storage session using agent name, user ID, chat name, group, and scope.
  </Card>

  <Card title="Context" icon="layer-group">
    Central orchestration layer that manages multiple storage instances for an agent.
  </Card>

  <Card title="IdentityStorage" icon="database">
    Tracks all storage identities registered within a context for discovery and management.
  </Card>

  <Card title="Storage" icon="hard-drive">
    Abstract base for all storage implementations (chat history, usage, custom).
  </Card>
</CardGroup>

## Session Identity

A `SessionIdentity` uniquely identifies a storage key using these components:

| Component   | Description                               | Example                    |
| ----------- | ----------------------------------------- | -------------------------- |
| `agentName` | Name of the agent class                   | `'SupportAgent'`           |
| `chatName`  | Session/chat identifier                   | `'support-ticket-123'`     |
| `userId`    | User identifier (when using `forUser()`)  | `'user-456'`               |
| `group`     | Grouping for shared context across agents | `'FAQ-team'`               |
| `scope`     | Storage type scope                        | `'chatHistory'`, `'usage'` |

### Key Generation

The identity key is generated as:

```
{scope}_{group|agentName}_{userId|chatName|'default'}
```

<AccordionGroup>
  <Accordion title="Key generation examples">
    * `chatHistory_SupportAgent_user-123` — User-based chat history
    * `chatHistory_SupportAgent_session-abc` — Session-based chat history
    * `usage_sql_user-456` — User usage in SQL group
  </Accordion>
</AccordionGroup>

## Creating Agents with Identities

LarAgent provides several ways to create agents with different identity configurations.

### Session-based Creation

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.

```php theme={null}
// 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'
```

### User-based Creation

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.

```php theme={null}
// 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'
```

### Reconstructing from Identity

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.

```php theme={null}
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...');
```

## Grouping

Groups enable **shared context** between multiple agents. When a group is set, the storage key uses the group name **instead of** the agent name.

<Info>
  **Key format without group:** `{scope}_{agentName}_{userId|chatName|'default'}`

  **Key format with group:** `{scope}_{group}_{userId|chatName|'default'}`
</Info>

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.

### Static Group Assignment

```php theme={null}
class TenantSupportAgent extends Agent
{
    protected $group = 'tenant-123';
}
```

### Dynamic Group Resolution

For runtime group resolution (e.g., based on current tenant):

```php theme={null}
class TenantSupportAgent extends Agent
{
    public function group(): ?string
    {
        return tenant()->id ?? null;
    }
}
```

<Warning>
  The group setting applies to **all** storages by default. To use different scopes for chat history vs usage tracking, use the custom identity override methods below.
</Warning>

## Custom Identity Overrides

Override identity creation methods to customize how chat history and usage tracking are scoped. This is useful for multi-tenant applications, team-based sharing, or any scenario requiring different storage isolation.

### Overriding History Identity

Use `createHistoryIdentity()` to customize chat history scoping:

```php theme={null}
use LarAgent\Context\SessionIdentity;

class TeamAgent extends Agent
{
    // Share chat history across team members
    protected function createHistoryIdentity(): SessionIdentity
    {
        return new SessionIdentity(
            agentName: $this->name(),
            chatName: $this->getTeamId(), // Share history across team
        );
    }
    
    private function getTeamId(): string
    {
        return auth()->user()->team_id;
    }
}
```

### Overriding Usage Identity

Use `createUsageIdentity()` to customize usage tracking scoping:

```php theme={null}
use LarAgent\Context\SessionIdentity;

class OrganizationAgent extends Agent
{
    // Track usage at organization level
    protected function createUsageIdentity(): SessionIdentity
    {
        return new SessionIdentity(
            agentName: $this->name(),
            chatName: 'org-' . $this->getOrganizationId(),
        );
    }
    
    private function getOrganizationId(): string
    {
        return auth()->user()->organization_id;
    }
}
```

### Dual Identity (Different Scopes)

Use different scopes for history and usage:

```php theme={null}
use LarAgent\Context\SessionIdentity;

class MultiTenantAgent extends Agent
{
    // Chat history scoped to team
    protected function createHistoryIdentity(): SessionIdentity
    {
        return new SessionIdentity(
            agentName: $this->name(),
            chatName: 'team-' . $this->getTeamId(),
        );
    }
    
    // Usage tracking scoped to organization
    protected function createUsageIdentity(): SessionIdentity
    {
        return new SessionIdentity(
            agentName: $this->name(),
            chatName: 'org-' . $this->getOrganizationId(),
        );
    }
}
```

<Tip>
  Use `createHistoryIdentity()` and `createUsageIdentity()` for simple identity customization. For full control over storage creation (including drivers and options), override `createChatHistory()` or `createUsageStorage()` instead.
</Tip>

<Accordion title="Advanced: Full storage override">
  ```php theme={null}
  use LarAgent\Context\SessionIdentity;
  use LarAgent\Context\Storages\ChatHistoryStorage;

  class MyAgent extends Agent
  {
      protected $group = 'shared-group'; // Default group for all storages
      
      // Full control over chat history storage creation
      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
          );
      }
  }
  ```

  Use this approach when you need full control over storage configuration, such as custom drivers or storage options.
</Accordion>

## Context Operations

### Accessing Context

You can access the context object directly from an agent:

```php theme={null}
// Get the context instance
$context = $agent->context();

// Get the base identity
$identity = $context->getIdentity();

// Get the context identity (used for IdentityStorage)
$contextIdentity = $context->getContextIdentity();
```

<Note>
  The `contextIdentity` is the general identity of the agent. It is stored in IdentityStorage and holds all other storage identities associated with the agent.
</Note>

### Bulk Operations

```php theme={null}
// 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();
```

### Getting Tracked Keys

```php theme={null}
// 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();
```

## Temporary Sessions

Sessions prefixed with `_temp` are not tracked in IdentityStorage:

```php theme={null}
// This session won't be tracked
$agent = SupportAgent::for('_temp_preview');
```

This is useful for:

* Preview/demo sessions
* Test sessions
* One-time interactions

## Context Events

Listen to context lifecycle events for custom behavior:

```php theme={null}
use LarAgent\Events\Context\ContextCreated;
use LarAgent\Events\Context\ContextSaving;
use LarAgent\Events\Context\ContextSaved;
use LarAgent\Events\Context\ContextReading;
use LarAgent\Events\Context\ContextRead;
use LarAgent\Events\Context\ContextClearing;
use LarAgent\Events\Context\ContextCleared;
use LarAgent\Events\Context\StorageRegistered;

// Context created
Event::listen(ContextCreated::class, function ($event) {
    $context = $event->context;
    Log::info('Context created', ['identity' => $context->getIdentity()->getKey()]);
});

// Storage registered
Event::listen(StorageRegistered::class, function ($event) {
    $context = $event->context;
    $prefix = $event->prefix;
    $storage = $event->storage;
    Log::info('Storage registered', ['prefix' => $prefix]);
});

// Before saving
Event::listen(ContextSaving::class, function ($event) {
    // Last chance to modify before persistence
});

// After saving
Event::listen(ContextSaved::class, function ($event) {
    // Trigger post-save actions
});
```

### Identity Storage Events

```php theme={null}
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 added
Event::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()]);
});
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Chat History" icon="comments" href="/v1/context/history">
    Learn how to configure and manage conversation history storage.
  </Card>

  <Card title="Usage Tracking" icon="chart-line" href="/v1/context/usage-tracking">
    Track token usage and costs across agent interactions.
  </Card>

  <Card title="Data Model" icon="cube" href="/v1/context/data-model">
    Create typed, structured data for custom storage implementations.
  </Card>

  <Card title="Truncation" icon="scissors" href="/v1/context/truncation">
    Manage context window limits with truncation strategies.
  </Card>
</CardGroup>
