How Session Scope Provides Isolation for Conversations in agent-core-v2
In MoonshotAI/kimi-code, the agent-core-v2 architecture isolates each conversation by running it inside a dedicated Session Scope—a child dependency-injection container that maintains separate service instances and state from all other sessions.
The agent-core-v2 package manages AI conversations through a sophisticated scoping system designed to prevent cross-contamination of memory, tool state, and telemetry data. When multiple conversations run concurrently or sequentially, the framework must guarantee that resources from one session cannot leak into another. The Session Scope pattern achieves this by creating hierarchical dependency-injection containers that strictly compartmentalize each conversation's resources.
Core Isolation Mechanisms in Session Scope
Creating a Child DI Container
When a new session starts, SessionLifecycleService.create invokes createScopedChildHandle with the LifecycleScope.Session kind. According to the source code in packages/agent-core-v2/src/workspace/sessionLifecycle/sessionLifecycleService.ts (lines 51-57), this instantiates a fresh InstantiationService child container that exists solely for that conversation, completely separate from the workspace and application containers.
Seeding Session-Specific Services
The framework supplies initial seeds to the child container during creation. As implemented in sessionLifecycleService.ts (lines 108-119), these seeds include ISessionContext, telemetry providers, agent-profile catalogs, and process runners. These objects become singletons within the session scope, ensuring they remain invisible to other sessions while being shared within their own conversation context.
Isolated Service Accessors
The returned ISessionScopeHandle contains an accessor property—typed as ServicesAccessor—that resolves services exclusively from the child container. Code in packages/agent-core-v2/src/_base/di/scope.ts (lines 91-96) demonstrates that this accessor restricts dependency resolution to the session's own container, preventing accidental cross-session service access.
Lifetime Management and Disposal
When conversations end, SessionLifecycleService.close triggers handle.dispose(). The implementation in sessionLifecycleService.ts (lines 30-38) demonstrates that disposing the child InstantiationService destroys all services created within that scope, frees memory, and eliminates lingering references that could cause leaks between sessions.
Hierarchical Scope Ordering
Session scopes exist in a strict hierarchy enforced by Scope.createChild in scope.ts (lines 12-23). Session scopes sit below the workspace scope, ensuring sessions inherit only read-only configuration from ancestor containers while remaining unable to access or modify sibling workspace or application services.
Conversation State Isolation
All per-conversation data—including dialog history, tool calls, agent lifecycles, and telemetry tags—lives within session-scoped services like ISessionMetadata and IAgentLifecycleService. As shown in sessionLifecycleService.ts (lines 36-44), each session's unique handle ensures two concurrent conversations never share the same state objects, even when running in parallel.
Why Session Scope Guarantees Isolation
The architecture ensures complete conversation isolation through four key design principles:
- Separate DI Containers: Each session receives its own
InstantiationServicechild; service instances are not singletons across sessions. - Unique Session IDs: The
ISessionScopeHandle.idserves as the session identifier, used by every scoped service to index its data. - Explicit Disposal: The
disposemethod removes the child scope from its parent and tears down its ledger, preventing memory leakage. - Controlled Inheritance: Session scopes inherit only read-only configuration from workspace and app scopes; they cannot mutate parent services.
Practical Implementation Examples
Creating an Isolated Session
import { SessionLifecycleService } from '#/workspace/sessionLifecycle/sessionLifecycleService';
import { CreateSessionOptions } from '#/workspace/sessionLifecycle/types';
async function startConversation(workspaceContext, opts: CreateSessionOptions) {
const sessionService = workspaceContext.sessionLifecycle;
const sessionHandle = await sessionService.create(opts);
return sessionHandle;
}
The returned sessionHandle implements ISessionScopeHandle and provides an accessor that resolves services only for that specific conversation.
Accessing Scoped Services
const mainAgent = await sessionHandle.accessor
.get(IAgentLifecycleService)
.create({ agentId: 'main', binding: opts.mainAgentBinding });
await mainAgent.sendMessage('Hello, world!');
All calls to IAgentLifecycleService resolve inside the session's DI container, keeping the agent's state private to that session.
Forking Sessions
const forkedHandle = await sessionService.fork({
parentSessionId: sessionHandle.id,
workDir: '/tmp/fork',
});
The fork operation creates a brand-new ISessionScopeHandle with its own child container, inheriting only read-only values from the parent session.
Cleaning Up Resources
await sessionService.close(sessionHandle.id);
This invocation runs handle.dispose(), destroying the entire child container and releasing all isolated resources.
Key Source Files
The Session Scope isolation mechanism is implemented across these critical files:
packages/agent-core-v2/src/_base/di/scope.ts: DefinesIScopeHandle, scoped service registration, andcreateScopedChildHandlethat constructs Session Scopes.packages/agent-core-v2/src/workspace/sessionLifecycle/sessionLifecycleService.ts: Orchestrates session creation, materialization, and disposal; usescreateScopedChildHandleto produce isolated handles.packages/agent-core-v2/src/workspace/sessionLifecycle/sessionLifecycle.ts: Exposes the public session-lifecycle API includingcreate,resume,fork, andclosemethods.packages/agent-core-v2/src/app/scopes.ts: Declares the scope topology (app → workspace → session → agent) that enforces hierarchical isolation.
Summary
- Session Scope creates a dedicated child DI container for each conversation in
agent-core-v2. - Isolation is enforced through separate
InstantiationServiceinstances, unique session IDs, and hierarchical scope ordering. - Seeding ensures each session receives its own instances of
ISessionContext, telemetry, and agent catalogs. - Disposal guarantees cleanup via
SessionLifecycleService.close, which tears down the child container and frees all associated resources. - Forking creates entirely new scopes while maintaining read-only inheritance from parent sessions.
Frequently Asked Questions
What is a Session Scope in agent-core-v2?
A Session Scope is a dedicated dependency-injection child container created for each conversation. It encapsulates all services, state, and resources—such as dialog history and tool configurations—ensuring complete isolation from other concurrent or sequential sessions.
How does Session Scope prevent memory leaks between conversations?
When SessionLifecycleService.close is called, it invokes handle.dispose() on the ISessionScopeHandle. This disposes the child InstantiationService, which tears down all service instances and removes the scope from the parent container's ledger, ensuring no references persist after the conversation ends.
Can sessions access each other's state?
No. Each session operates with its own ServicesAccessor that resolves instances exclusively from its child container. Because services like ISessionMetadata and IAgentLifecycleService are scoped to the session level, two conversations cannot share state objects or interfere with each other's memory.
What happens when a session is forked?
Forking creates a new ISessionScopeHandle with its own isolated DI container via sessionService.fork. The forked session inherits read-only configuration from its parent but receives fresh instances of all scoped services, ensuring the forked conversation operates independently while maintaining the desired parent-child relationship.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →