How to Build a Harness

19. Steering & Follow-ups

Inject messages mid-run, queue follow-up prompts.

pi lets you inject messages while the agent is running (steering) or after it finishes (follow-ups).

File: packages/agent/src/agent.ts L252-259

/** Queue a message to be injected after the current assistant turn finishes. */
steer(message: AgentMessage): void {
  this.steeringQueue.enqueue(message);
}

/** Queue a message to run only after the agent would otherwise stop. */
followUp(message: AgentMessage): void {
  this.followUpQueue.enqueue(message);
}

The loop checks for these between turns:

File: packages/agent/src/agent-loop.ts L216-225

pendingMessages = (await config.getSteeringMessages?.()) || [];
// If inner loop exhausted, check for follow-ups
const followUpMessages = (await config.getFollowUpMessages?.()) || [];
if (followUpMessages.length > 0) {
  pendingMessages = followUpMessages;
  continue; // Restart inner loop
}

For a minimal harness, you can skip steering entirely. Just read user input, run the loop, print the result.


Open this chapter inside the full course