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.onSubmit → session.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.