Sessions¶
An EveSession is a fixed handle. It tracks two values:
SessionIdidentifies the durable runtime session. It addresses every turn, control, and stream, and never changes once assigned.StreamIndexcounts events already consumed.
eve 0.31.0 removed continuation tokens from the client protocol. A handle
keeps its identifier across every session boundary, so a completed or failed
conversation stays inspectable and streamable.
Persist state¶
Consume the response before saving the fully advanced cursor:
EveMessageResponse response = await session.SendAsync(
"Create a checklist.",
cancellationToken);
await response.GetOutcomeAsync(cancellationToken);
await SaveAsync(session.State, cancellationToken);
Resume state¶
EveSession resumed = client.CreateSession(savedState);
EveMessageResponse response = await resumed.SendAsync(
"Shorten the checklist.",
cancellationToken);
When only the session identifier was persisted, attach to it directly:
EveSession resumed = client.AttachSession(sessionId);
EveSession rewound = client.AttachSession(sessionId, streamIndex: 12);
Overlapping sends¶
A message that reaches a session which already has an active turn is governed by
a delivery policy. eve 0.33.0 changed the server-side default from waiting to
steering, so an overlapping send now cancels the active turn and replaces it.
eve 0.33.0 steers by default
Sending no policy means eve 0.33.0 and later cancel the active turn. Set
TurnPolicy to EveTurnPolicy.Queue to keep the earlier
wait-for-completion behavior. Nothing fails loudly, because the request
format did not change.
EveMessageResponse response = await session.SendAsync(
EveMessageContent.FromText("Actually, summarize it instead."),
new EveTurnOptions { TurnPolicy = EveTurnPolicy.Queue },
cancellationToken);
The policy is sent only for a message continuing an existing session. It is omitted when the turn creates the session, because a new session has no active turn, and when the turn carries only input responses. Awaiting each turn before sending the next one never overlaps, so sequential callers are unaffected.
Clear session context¶
Control operations require identifier-addressed routes
ClearAsync, CompactAsync, and ResetAsync post to
/eve/v1/session/{sessionId}/clear, /compact, and /reset, which exist only in eve
0.31.0 and newer. They report HTTP 404 on an earlier agent. Turns, streaming, and
cancellation are unaffected. See Migration.
ClearAsync queues removal of durable model-message history while keeping the
session identity, configuration, non-message state, limits, and sandbox:
EveClearOutcome clear = await session.ClearAsync(cancellationToken);
if (clear.Status == EveClearStatus.Accepted)
{
await foreach (EveStreamEvent streamEvent in session.StreamAsync(cancellationToken))
{
if (streamEvent.Kind == EveStreamEventKind.ContextCleared)
{
// History was cleared on the durable stream.
}
if (streamEvent.Kind == EveStreamEventKind.SessionWaiting)
{
break;
}
}
}
- The session identifier is recorded as soon as
SendAsyncreturns, so clear can run before the response stream is consumed. - A session that never started returns
EveClearStatus.NoActiveSessionand issues no HTTP request. - A successful clear leaves the local cursor unchanged. Consume the durable
stream through
context.clearedand the followingsession.waitingboundary before sending another turn. - The route is
POST /eve/v1/session/{sessionId}/clearand requires eve0.31.0or newer.
ClearAsync is not an alias for ResetAsync. ResetAsync retires the
conversation; ClearAsync keeps the same durable session and only discards
model-message history.
Reset a session¶
ResetAsync terminally retires the durable session addressed by this handle:
EveResetOutcome reset = await session.ResetAsync(cancellationToken);
if (reset.Status == EveResetStatus.Reset)
{
EveSession next = client.CreateSession();
}
- A session that never started returns
EveResetStatus.NoActiveSessionand issues no HTTP request. - The handle keeps its session identifier after a successful reset. It does not
recycle into a new conversation; call
CreateSession()for that. - The route is
POST /eve/v1/session/{sessionId}/resetand requires eve0.31.0or newer.
ResetAsync is not an alias for CancelAsync. CancelAsync only requests
cooperative cancellation of the active turn and keeps the conversation
resumable; ResetAsync retires the conversation itself.
Compact a session¶
CompactAsync queues context compaction for the durable session without
sending model input:
EveCompactOutcome compact = await session.CompactAsync(cancellationToken);
if (compact.Status == EveCompactStatus.Accepted)
{
await foreach (EveStreamEvent streamEvent in session.StreamAsync(cancellationToken))
{
if (streamEvent.Kind is EveStreamEventKind.SessionWaiting
or EveStreamEventKind.SessionCompleted
or EveStreamEventKind.SessionFailed)
{
break;
}
}
}
- Compaction is asynchronous. Consume the durable stream through the next
session boundary before sending another turn.
compaction.completedconfirms successful summarization. - A session that never started returns
EveCompactStatus.NoActiveSessionand issues no HTTP request. - Unlike reset, compaction preserves the local session cursor.
- The route is
POST /eve/v1/session/{sessionId}/compactand requires eve0.31.0or newer.
CompactAsync is not an alias for ResetAsync. Compaction summarizes history
in place and keeps the conversation resumable; reset retires the conversation.
Terminal behavior¶
Every session boundary advances the cursor and preserves the session
identifier. session.waiting parks the conversation for another turn;
session.completed and session.failed end it. In all three cases the handle
remains valid for streaming and inspection, so a finished conversation can
still be replayed from index 0.