# How the App Scope Is Different from Other Scopes in agent-core-v2

> Understand how the App Scope differs from Workspace, Session, and Agent scopes in agent-core-v2. Learn about root-level dependency injection and lifecycle management for agent applications.

- Repository: [Moonshot AI/kimi-code](https://github.com/MoonshotAI/kimi-code)
- Tags: deep-dive
- Published: 2026-08-13

---

**The App Scope is the root-level, process-wide dependency injection container in agent-core-v2 that lives for the entire application lifetime, while Workspace, Session, and Agent scopes are child containers with shorter lifecycles that can inject App services but cannot be injected into them.**

The `agent-core-v2` package in the MoonshotAI/kimi-code repository implements a hierarchical dependency injection (DI) system that organizes services into four distinct lifetime boundaries. Understanding how the **App Scope** differs from its descendants is critical for correctly architecting global services like loggers, telemetry, and configuration providers that must persist across user sessions.

## Understanding the Scope Hierarchy in agent-core-v2

The framework defines a strict four-level tree structure in [`packages/agent-core-v2/src/app/scopes.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/src/app/scopes.ts). Each scope represents a boundary for service instantiation and visibility.

### The Four Lifecycle Scopes

| Scope | Lifetime | Typical Use | Hierarchy Position |
|-------|----------|-------------|--------------------|
| **App** | Process-wide, created once at startup | Global logging, telemetry, configuration | Root (longest-lived) |
| **Workspace** | One per user workspace/project | File indexes, workspace-wide plugins | Child of App |
| **Session** | One per interactive chat session | Session metadata, transcript cache | Child of Workspace |
| **Agent** | One per agent instance inside a session | Per-turn data, agent-specific state | Leaf (shortest-lived) |

The enum definition in [`src/app/scopes.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/src/app/scopes.ts) codifies these levels:

```typescript
// packages/agent-core-v2/src/app/scopes.ts
export enum LifecycleScope {
  App = 'app',           // process-level, global singleton
  Workspace = 'workspace',
  Session = 'session',
  Agent = 'agent',
}

```

## Key Differences Between App Scope and Child Scopes

While all four scopes use the same registration API, the **App Scope** exhibits unique behavioral constraints that prevent circular dependencies and resource leaks.

### Lifetime and Visibility Rules

**App Scope** services are instantiated **exactly once** when the process starts and remain alive until the application exits. They are **visible to every lower scope** in the hierarchy—Workspace, Session, and Agent services can all inject App-level dependencies. However, the reverse is strictly prohibited: an App service cannot depend on a Workspace, Session, or Agent service because those shorter-lived containers do not exist when the App scope is constructed.

This visibility rule is enforced by the DI container and documented in [`packages/agent-core-v2/docs/di.md`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/docs/di.md): *"短寿命的服务可以注入长寿命的服务，反过来不行"* (Shorter-lived services can inject longer-lived services, but not vice versa).

### Dependency Direction Constraints

The hierarchy forms a **directed acyclic graph**: `App → Workspace → Session → Agent`. Attempting to register an App service that depends on a Session service triggers a DI resolution error at startup. This constraint guarantees that global singletons never hold references to transient session data, preventing memory leaks and use-after-free bugs.

### Registration and Activation Patterns

App-level services typically use `ScopeActivation.OnScopeCreated` to ensure immediate availability, while child scopes often use `ScopeActivation.OnDemand` for lazy instantiation. The `registerScopedService` function in `#/_base/di/scope.ts` binds a service implementation to a specific scope level:

```typescript
registerScopedService(
  LifecycleScope.App,               // App scope
  ILogService,
  LogService,
  ScopeActivation.OnScopeCreated,   // created when App scope starts
  'log',
);

```

## Practical Implementation Examples

### Registering an App-Scope Service

Global services like loggers must be registered at the App level to ensure they are available throughout the process lifetime:

```typescript
import { LifecycleScope } from '#/app/scopes';
import { registerScopedService, ScopeActivation } from '#/_base/di/scope';
import { ILogService } from '#/log/log';

export class LogService implements ILogService {
  declare readonly _serviceBrand: undefined;
  info(msg: string) { console.log('[INFO]', msg); }
}

// App-level registration – one instance for the whole process
registerScopedService(
  LifecycleScope.App,
  ILogService,
  LogService,
  ScopeActivation.OnScopeCreated,
  'log',
);

```

### Registering a Session-Scope Service That Injects App Services

Session-level services can safely inject App-level dependencies. The following example shows a `SessionMetadata` service consuming the global logger:

```typescript
import { LifecycleScope } from '#/app/scopes';
import { registerScopedService, ScopeActivation } from '#/_base/di/scope';
import { ISessionMetadata } from '#/session/metadata';
import { ILogService } from '#/log/log';

export class SessionMetadata implements ISessionMetadata {
  declare readonly _serviceBrand: undefined;

  // The logger is an App-scope service; injection is safe here.
  constructor(@ILogService private readonly log: ILogService) {}

  record(key: string, value: unknown) {
    this.log.info(`SessionMetadata: ${key} = ${JSON.stringify(value)}`);
  }
}

// Session-level registration
registerScopedService(
  LifecycleScope.Session,
  ISessionMetadata,
  SessionMetadata,
  ScopeActivation.OnDemand,   // constructed on first retrieval
  'sessionMetadata',
);

```

### Illegal App-to-Session Dependencies

The following pattern demonstrates what happens when you violate the hierarchy rules. The DI container will throw an error during App scope creation because `ISessionMetadata` does not exist at that point:

```typescript
import { LifecycleScope } from '#/app/scopes';
import { registerScopedService, ScopeActivation } from '#/_base/di/scope';
import { IAppStateService } from '#/app/state/appState';
import { ISessionMetadata } from '#/session/metadata';

export class IllegalAppService {
  // ❌ Illegal: App service depends on Session-level service
  constructor(@ISessionMetadata private readonly meta: ISessionMetadata) {}
}

// This registration will throw at App-scope creation time
registerScopedService(
  LifecycleScope.App,
  IAppStateService,
  IllegalAppService,
  ScopeActivation.OnScopeCreated,
  'illegal',
);

```

## Why the Scope Hierarchy Matters

The strict separation between **App Scope** and child scopes serves three architectural purposes:

- **Resource Management** – App services live for the entire process, so they must be lightweight and safe to keep resident in memory (e.g., singleton loggers or configuration caches).
- **Isolation** – Session and Agent scopes can be destroyed when a user ends a chat, allowing the garbage collector to reclaim memory without affecting global state.
- **Dependency Safety** – The tree structure guarantees a **directed acyclic graph** of dependencies. Attempting to create circular dependencies across scope boundaries fails fast at startup rather than causing runtime errors.

These rules are reflected in the runtime debug protocol implementation, where [`packages/kap-server/src/transport/channelRegistry.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/kap-server/src/transport/channelRegistry.ts) maps each `LifecycleScope` value to its string representation for wire protocol communication.

## Summary

- The **App Scope** is the root DI container in agent-core-v2, created once per process and destroyed only at application exit.
- Child scopes (Workspace, Session, Agent) can **inject** App services, but App services **cannot depend** on any shorter-lived scope.
- The hierarchy `App → Workspace → Session → Agent` prevents memory leaks by ensuring global singletons never reference transient session data.
- Registration occurs via `registerScopedService` in `#/_base/di/scope.ts`, using the `LifecycleScope` enum defined in [`src/app/scopes.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/src/app/scopes.ts).

## Frequently Asked Questions

### What happens if an App service tries to depend on a Session service?

The DI container will throw a resolution error during App scope initialization. Because the Session scope is a child of the App scope, it does not exist when the App container is being constructed, making it impossible to satisfy the dependency. This enforcement prevents architectural errors where global singletons would hold references to transient data.

### Can Workspace services access App services?

Yes. Workspace services, like all child scopes, can freely inject any service registered at the App level. This is the standard pattern for accessing global loggers, configuration stores, and telemetry providers from workspace-specific logic. The dependency direction only prohibits App services from depending on Workspace services.

### How do I register a service that needs to persist across sessions?

Register the service with `LifecycleScope.App` in [`packages/agent-core-v2/src/app/scopes.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/src/app/scopes.ts). Use `ScopeActivation.OnScopeCreated` to ensure the service initializes immediately when the process starts. This pattern is used for system-wide resources like the `LogService` that must remain available regardless of how many individual chat sessions are active.

### Where is the scope hierarchy defined in the source code?

The `LifecycleScope` enum is defined in [`packages/agent-core-v2/src/app/scopes.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/src/app/scopes.ts). The hierarchy rules and dependency injection guidelines are documented in [`packages/agent-core-v2/docs/di.md`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/docs/di.md). Additionally, the debug transport layer in [`packages/kap-server/src/transport/channelRegistry.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/kap-server/src/transport/channelRegistry.ts) references these scope values when mapping them to protocol channel names.