How to Configure Message Queue and Steering Mode in π‑AI

Configure message queue and steering mode in π‑AI by setting steeringMode and followUpMode to either "all" or "one-at-a-time" in your ~/.pi/settings.json file or via the SettingsManager API.

The π‑AI engine (powering the agent and coding‑agent packages in the badlogic/pi‑mono repository) manages concurrent user input through two internal buffers. Understanding how to configure these queues allows you to control whether the AI processes interruptions immediately or sequences them for later handling.

Understanding π‑AI Message Queues

π‑AI maintains two distinct message queues while the model is processing a turn:

  • Steering queue – Holds "steering" messages that interrupt the current turn (for example, when a user types a new command while the assistant is still generating a response).
  • Follow‑up queue – Holds messages that should be sent after the current turn finishes (such as continuations or secondary requests).

Both queues are implemented as simple arrays inside the agent (steeringQueue and followUpQueue in packages/agent/src/agent.ts) and are flushed according to the selected mode.

Configuring Steering Mode in π‑AI

The steeringMode setting determines how the agent delivers messages from the steering queue.

Steering Mode Options

  • "one-at-a-time" (default) – The agent sends only the first pending steering message and waits for the model to reply before delivering the next one.
  • "all" – The agent flushes the entire steering queue in a single batch the next time the model is invoked.

Settings File Configuration

Add the following to your ~/.pi/settings.json file:

{
  "steeringMode": "all"
}

The SettingsManager class in packages/coding-agent/src/core/settings-manager.ts reads this value at runtime:

// packages/coding-agent/src/core/settings-manager.ts
public getSteeringMode(): "all" | "one-at-a-time" {
    return this.settings.steeringMode || "one-at-a-time";
}

Programmatic Configuration

Change the steering mode dynamically via the agent API:

import { getAgent } from "@mariozechner/pi-ai";

async function enableBatchSteering() {
  const agent = await getAgent();
  await agent.setSteeringMode("all");
}

Configuring Follow-Up Mode in π‑AI

The followUpMode setting controls delivery of the follow‑up queue using the same logic as steering mode.

Follow-Up Mode Options

  • "one-at-a-time" (default) – Follow‑up messages are delivered sequentially, each waiting for the model's response.
  • "all" – All queued follow‑up messages are sent together after the current turn completes.

Configuration Examples

In ~/.pi/settings.json:

{
  "steeringMode": "one-at-a-time",
  "followUpMode": "all"
}

Via the SettingsManager in packages/coding-agent/src/core/settings-manager.ts:

public getFollowUpMode(): "all" | "one-at-a-time" {
    return this.settings.followUpMode || "one-at-a-time";
}

Queue Implementation Details

The internal implementation in packages/agent/src/agent.ts uses simple arrays and mode-driven flushing logic:

// packages/agent/src/agent.ts
private steeringQueue: AgentMessage[] = [];  // L113

public queueSteering(m: AgentMessage) {
    this.steeringQueue.push(m);              // L253
}

private getSteeringMessages(): AgentMessage[] {
    if (this.steeringMode === "one-at-a-time" && this.steeringQueue.length > 0) {
        const first = this.steeringQueue[0];
        this.steeringQueue = this.steeringQueue.slice(1);  // L283‑L285
        return [first];
    }
    const all = this.steeringQueue.slice();  // L291‑L292
    this.steeringQueue = [];
    return all;
}

Before each turn, the agent checks hasPendingMessages() (which combines steering and follow‑up queues) and injects queued messages back into the conversation flow according to the configured modes.

Migrating from Legacy queueMode Settings

Earlier versions of π‑AI used a single queueMode setting. Starting with v0.12.x, this was split into steeringMode and followUpMode.

The SettingsManager in packages/coding-agent/src/core/settings-manager.ts automatically migrates legacy configurations:

// packages/coding-agent/src/core/settings-manager.ts
if ("queueMode" in settings && !("steeringMode" in settings)) {
    settings.steeringMode = settings.queueMode;  // L189‑L191
    delete settings.queueMode;
}

If you have existing ~/.pi/settings.json files with queueMode, they will continue to work without manual intervention.

Practical Code Examples

Queuing a Steering Message

From an extension or external tool, you can interrupt the current AI turn by queuing a steering message:

import { getAgent } from "@mariozechner/pi-ai";

async function interruptAgent(text: string) {
  const agent = await getAgent();
  await agent.queueSteering({ role: "user", content: text });
}

The message will be delivered according to the current steeringMode setting.

Inspecting Pending Queues

For debugging purposes, you can inspect the contents of both queues:

import { getAgent } from "@mariozechner/pi-ai";

async function logQueues() {
  const agent = await getAgent();
  console.log("Steering queue:", await agent.getSteeringQueue());
  console.log("Follow‑up queue:", await agent.getFollowUpQueue());
}

Summary

  • π‑AI uses two internal buffers—the steering queue for interruptions and the follow‑up queue for post‑turn messages—implemented as arrays in packages/agent/src/agent.ts.
  • Configure delivery behavior via steeringMode and followUpMode in ~/.pi/settings.json, accepting values "all" (batch flush) or "one-at-a-time" (sequential delivery).
  • The SettingsManager class in packages/coding-agent/src/core/settings-manager.ts provides getters and automatic migration from the legacy queueMode setting.
  • Change modes programmatically using agent.setSteeringMode() and queue messages via agent.queueSteering() according to the API exposed by the agent package.

Frequently Asked Questions

What is the difference between steering mode and follow-up mode in π‑AI?

Steering mode controls how interruption messages (sent while the AI is processing) are delivered, while follow-up mode controls messages queued to run after the current turn completes. Both support "all" (batch delivery) and "one-at-a-time" (sequential delivery), but they operate on separate queues defined in packages/agent/src/agent.ts.

How do I enable batch processing for steering messages?

Set "steeringMode": "all" in your ~/.pi/settings.json file or call agent.setSteeringMode("all") programmatically. When set to "all", the agent flushes the entire steeringQueue array in a single batch the next time the model is invoked, rather than waiting for individual responses between messages.

Where are the steering and follow-up queues implemented?

Both queues are implemented as private arrays in the Agent class located at packages/agent/src/agent.ts. The steeringQueue is explicitly defined at line 113, while queue manipulation methods like queueSteering() (line 253) and getSteeringMessages() (lines 283‑292) handle the mode‑driven flushing logic.

What happened to the old queueMode setting?

The queueMode setting was deprecated in π‑AI v0.12.x and replaced by separate steeringMode and followUpMode settings. The SettingsManager class in packages/coding-agent/src/core/settings-manager.ts automatically migrates legacy configurations by copying queueMode to steeringMode when the latter is absent, ensuring backward compatibility without manual intervention.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →