# AgentSessionManager

> Tracon documentation. Tracon is a .NET package family that adds a control
> plane on Microsoft Agent Framework, published as NuGet packages that run
> inside your own ASP.NET Core application.
>
> Page: https://tracon.dev/api/tracon.agentsessionmanager/
> Summary: AgentSessionManager: Manages the lifecycle of named sessions: loads, restores, and saves them through ISessionStore.

<div class="api-provenance">Namespace Tracon · Assembly <code>Tracon.Core.dll</code></div>

Manages the lifecycle of named sessions: loads, restores, and saves them
through [ISessionStore](/api/tracon.isessionstore/).

```csharp
public sealed class AgentSessionManager
```

<dl class="api-relations"><dt>Inheritance</dt><dd><a href="https://learn.microsoft.com/dotnet/api/system.object">object</a> ← <a href="/api/tracon.agentsessionmanager/">AgentSessionManager</a></dd><dt>Inherited Members</dt><dd><a href="https://learn.microsoft.com/dotnet/api/system.object.gettype">object.GetType()</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.tostring">object.ToString()</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object)">object.Equals(object?)</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object-system-object)">object.Equals(object?, object?)</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.referenceequals">object.ReferenceEquals(object?, object?)</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.gethashcode">object.GetHashCode()</a></dd></dl>

## Remarks

This class is provider-agnostic. It works the same way with the in-memory
store and the PostgreSQL store; it does not know which store is registered.

The session state is Microsoft Agent Framework's `SerializeSessionAsync`
output and is treated as **opaque**. Tracon does not
interpret its content. The identity is stamped onto the session's state
bag, so that [RunRecordingAgent](/api/tracon.runrecordingagent/) can write the real session
identity to the run record.

Microsoft Agent Framework's `AgentSessionStore` abstraction is wired to
this class by delegation.

`AddTracon` registers the manager as a singleton; resolve it with
`GetRequiredService<AgentSessionManager>`.

## Methods

### <a id="Tracon_AgentSessionManager_DeleteSessionAsync_System_String_System_Threading_CancellationToken_"></a> DeleteSessionAsync\(string, CancellationToken\)

Deletes the session, and the copy of its content that conversation memory keeps.

```csharp
public ValueTask<bool> DeleteSessionAsync(string sessionId, CancellationToken cancellationToken = default)
```

#### Parameters

`sessionId` [string](https://learn.microsoft.com/dotnet/api/system.string)

The session identity.

`cancellationToken` [CancellationToken](https://learn.microsoft.com/dotnet/api/system.threading.cancellationtoken)

The cancellation token.

#### Returns

 [ValueTask](https://learn.microsoft.com/dotnet/api/system.threading.tasks.valuetask\-1)<[bool](https://learn.microsoft.com/dotnet/api/system.boolean)\>

[true](https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/bool) if a deletion occurred.

#### Remarks

The copy goes first and only for a session that exists: a copy that cannot be erased fails the
call with the session still in place, so a repeat call finds it and finishes the erasure. Erasing after
the delete would leave a copy no repeat call could reach.

#### Exceptions

 [ArgumentException](https://learn.microsoft.com/dotnet/api/system.argumentexception)

`sessionId` is empty.

### <a id="Tracon_AgentSessionManager_GetOrCreateSessionAsync_Microsoft_Agents_AI_AIAgent_System_String_System_Threading_CancellationToken_"></a> GetOrCreateSessionAsync\(AIAgent, string, CancellationToken\)

Restores the session with the given identity; opens a new session if
no record exists. In both cases, the returned session is stamped with
its own identity.

```csharp
public ValueTask<AgentSession> GetOrCreateSessionAsync(AIAgent agent, string sessionId, CancellationToken cancellationToken = default)
```

#### Parameters

`agent` AIAgent

The agent the session belongs to.

`sessionId` [string](https://learn.microsoft.com/dotnet/api/system.string)

The session identity.

`cancellationToken` [CancellationToken](https://learn.microsoft.com/dotnet/api/system.threading.cancellationtoken)

The cancellation token.

#### Returns

 [ValueTask](https://learn.microsoft.com/dotnet/api/system.threading.tasks.valuetask\-1)<AgentSession\>

A session ready for use.

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`agent` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

 [ArgumentException](https://learn.microsoft.com/dotnet/api/system.argumentexception)

`sessionId` is empty.

 [TraconException](/api/tracon.traconexception/)

The stored state cannot be restored by this agent.

 [TraconSessionOwnerRequiredException](/api/tracon.traconsessionownerrequiredexception/)

Session ownership is on, this call would OPEN a new session, and no
authenticated identity could be resolved to own it.

### <a id="Tracon_AgentSessionManager_QuerySessionsAsync_Tracon_SessionQuery_System_Threading_CancellationToken_"></a> QuerySessionsAsync\(SessionQuery, CancellationToken\)

Lists sessions matching a filter.

```csharp
public ValueTask<IReadOnlyList<SessionRecord>> QuerySessionsAsync(SessionQuery query, CancellationToken cancellationToken = default)
```

#### Parameters

`query` [SessionQuery](/api/tracon.sessionquery/)

The filter. The current tenant is used if none is specified.

`cancellationToken` [CancellationToken](https://learn.microsoft.com/dotnet/api/system.threading.cancellationtoken)

The cancellation token.

#### Returns

 [ValueTask](https://learn.microsoft.com/dotnet/api/system.threading.tasks.valuetask\-1)<[IReadOnlyList](https://learn.microsoft.com/dotnet/api/system.collections.generic.ireadonlylist\-1)<[SessionRecord](/api/tracon.sessionrecord/)\>\>

The sessions.

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

`query` is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

### <a id="Tracon_AgentSessionManager_SaveSessionAsync_Microsoft_Agents_AI_AIAgent_Microsoft_Agents_AI_AgentSession_System_Threading_CancellationToken_"></a> SaveSessionAsync\(AIAgent, AgentSession, CancellationToken\)

Serializes the session and writes it to the store.

```csharp
public ValueTask<string> SaveSessionAsync(AIAgent agent, AgentSession session, CancellationToken cancellationToken = default)
```

#### Parameters

`agent` AIAgent

The agent the session belongs to.

`session` AgentSession

The session to save.

`cancellationToken` [CancellationToken](https://learn.microsoft.com/dotnet/api/system.threading.cancellationtoken)

The cancellation token.

#### Returns

 [ValueTask](https://learn.microsoft.com/dotnet/api/system.threading.tasks.valuetask\-1)<[string](https://learn.microsoft.com/dotnet/api/system.string)\>

The identity of the saved session.

#### Remarks

If two concurrent first requests arrive for the
same new session identity, both start with an empty session in
[AgentSessionManager.GetOrCreateSessionAsync](/api/tracon.agentsessionmanager/#Tracon_AgentSessionManager_GetOrCreateSessionAsync_Microsoft_Agents_AI_AIAgent_System_String_System_Threading_CancellationToken_) and run their own turn — each
produces its own conversation identity, which is unavoidable (the
conversation identity is only known once the turn runs). The actual
defect was that the second [ISessionStore.SaveAsync](/api/tracon.isessionstore/#Tracon_ISessionStore_SaveAsync_Tracon_SessionRecord_System_Threading_CancellationToken_) would
**unconditionally** overwrite the first, silently leaving
the loser's conversation unreachable. For this reason, the first save
of a session (see the fresh sessions marked by
[AgentSessionManager.GetOrCreateSessionAsync](/api/tracon.agentsessionmanager/#Tracon_AgentSessionManager_GetOrCreateSessionAsync_Microsoft_Agents_AI_AIAgent_System_String_System_Threading_CancellationToken_)) always attempts an atomic write
with [ISessionStore.TryCreateAsync](/api/tracon.isessionstore/#Tracon_ISessionStore_TryCreateAsync_Tracon_SessionRecord_System_Threading_CancellationToken_); if it loses, it does
not silently overwrite, and instead throws an explicit
[TraconSessionConflictException](/api/tracon.traconsessionconflictexception/).

every LATER save of that same record is guarded the same way, through
[ISessionStore.TryUpdateAsync](/api/tracon.isessionstore/#Tracon_ISessionStore_TryUpdateAsync_Tracon_SessionRecord_System_Int64_System_Threading_CancellationToken_): closing the race for the
first write only left the more common case open — two concurrent turns
on an EXISTING session both reported success and the loser's turn was
silently overwritten. A save that targets a DIFFERENT identity than the
session was read from is a new record, not a replacement, and is still
written unconditionally.

The session's OWNER travels through all three of those branches
untouched once it is set: [AgentSessionManager.ResolveOwnerId](/api/tracon.agentsessionmanager/) claims it on the
first write and carries it verbatim on every later one. The stores
hold the same rule a second time, so an owner survives even a write
this manager never saw.

#### Exceptions

 [ArgumentNullException](https://learn.microsoft.com/dotnet/api/system.argumentnullexception)

One of the parameters is [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null).

 [TraconException](/api/tracon.traconexception/)

The session has no identity because it was not opened with [AgentSessionManager.GetOrCreateSessionAsync](/api/tracon.agentsessionmanager/#Tracon_AgentSessionManager_GetOrCreateSessionAsync_Microsoft_Agents_AI_AIAgent_System_String_System_Threading_CancellationToken_).

 [TraconSessionConflictException](/api/tracon.traconsessionconflictexception/)

This was the first save of a session that [AgentSessionManager.GetOrCreateSessionAsync](/api/tracon.agentsessionmanager/#Tracon_AgentSessionManager_GetOrCreateSessionAsync_Microsoft_Agents_AI_AIAgent_System_String_System_Threading_CancellationToken_)
opened FRESH, and a concurrent request saved the same new session
identity before we did.

 [TraconSessionOwnerRequiredException](/api/tracon.traconsessionownerrequiredexception/)

Session ownership is on, this write would CLAIM ownership of a session,
and no authenticated identity could be resolved to be its owner. See
[AgentSessionManager.ResolveOwnerId](/api/tracon.agentsessionmanager/).
