Skip to content

AgentSession: the orchestration layer of the coding agent

源码版本v0.73.1

AgentSession is the heaviest layer in pi-coding-agent — it doesn't run the LLM directly, nor does it render the UI. It sits between the two: upstream it accepts user input and UI events; downstream it drives pi-agent-core's Agent loop. Model registration, tool definitions, system prompt construction, context compaction, failure retries, and message queueing all live here. Think of it as the assembly workshop that wraps a generic Agent into a stateful, resumable coding assistant with skills and tools.

Responsibilities

AgentSession does four things:

  1. Assembly: AgentSessionConfig takes an Agent instance, model registry, tool definitions, extension runtime, and system prompt builder; the constructor hooks beforeToolCall/afterToolCall and subscribes to events. See packages/coding-agent/src/core/agent-session.ts:313-330.
  2. Input intake: prompt(text) is the main entry — it handles / slash commands, expands file-based prompt templates, turns text into AgentMessage[], and hands it to the underlying Agent. See packages/coding-agent/src/core/agent-session.ts:967-1000.
  3. Event forwarding: subscribes to the Agent event stream, repackages events as AgentSessionEvent, and emits them to the UI above. See packages/coding-agent/src/core/agent-session.ts:330-335.
  4. Queueing and retry: when the user keeps typing during streaming, streamingBehavior decides between steer (interrupt) and followUp (queue), instead of just dropping or blocking. See packages/coding-agent/src/core/agent-session.ts:1181-1296.

Design Motivation

Why not let the UI call Agent.prompt directly? A coding assistant needs a bunch of cross-cutting logic that a generic Agent doesn't care about: slash commands (/model, /settings), prompt template expansion, model/API key validation, auto-compaction when context overflows, auth and telemetry around tool calls. Pushing these into Agent would weigh down the generic loop; pushing them into the UI layer would duplicate them across print mode, rpc mode, and extensions. AgentSession is extracted as the single entry point: all three run modes share the same orchestration logic, and the UI only renders events.

Key Files

Hooking and subscribing in the constructor is the starting point of the whole orchestration:

typescript
// packages/coding-agent/src/core/agent-session.ts:313-335
constructor(config: AgentSessionConfig) {
  // ... store config, initialize state ...
  this._unsubscribeAgent = this.agent.subscribe(this._handleAgentEvent);
  // ... etc ...
}

prompt turns user text into AgentMessage[] and hands it to the underlying Agent:

typescript
// packages/coding-agent/src/core/agent-session.ts:1107-1112
  try {
    await this.agent.prompt(messages);
  } catch (error) {
    // ... failure handling ...
  }

Data Flow

User presses Enter in the TUI editor → InteractiveMode.defaultEditor.onSubmitsession.prompt(text):

When the user keeps typing during streaming, prompt doesn't force through — it splits:

Edges and Failures

  • Slash command conflicts: commands registered by extensions can also execute immediately during streaming (they manage their own LLM interaction), bypassing the queue. If a command can't be queued, it throws directly. See packages/coding-agent/src/core/agent-session.ts:1255-1259.
  • Missing model/key: the non-streaming path validates model and API key, throwing instead of sending an empty request.
  • Compaction abort: abort cancels both the main loop and the compaction/branch-summary controllers. See packages/coding-agent/src/core/agent-session.ts:1744-1752.
  • Retry: Agent.emit() calls _handleAgentEvent synchronously, while prompt() does waitForRetry(); the retry logic decides whether to re-emit the turn after a failure.

Summary

AgentSession is the assembly workshop and event bus for the coding assistant: it assembles Agent, forwards events, queues interrupts, and manages tool hooks. Upstream are the three UI modes — InteractiveMode / runPrintMode / runRpcMode. Downstream is the generic loop in pi-agent-core. For assembly internals, see createAgentSession Wiring; for the underlying loop, see Double while Loop.