Skip to content

primitives agent message

Zachary BENSALEM edited this page Aug 15, 2026 · 1 revision

Agent message

Active contributors: Mario Zechner, kt, Armin Ronacher

AgentMessage is the message model of the Prime Agent runtime. It is declared in packages/agent/src/types.ts as a union of the raw LLM messages (user, assistant, toolResult) and any app-extended custom message types. It is the transcript type the agent loop works with end to end; conversion to plain LLM messages happens only at the provider boundary.

Purpose

  • Give the agent loop and the UI one extensible transcript type instead of forcing every app to use raw provider messages.
  • Let apps add their own message kinds (bash executions, compaction summaries, slash commands, agent-to-agent messages) without loosening type safety.
  • Keep custom, UI-only messages out of the LLM request until an explicit convertToLlm step decides what the model should see.

How it works

The base type is AgentMessage = Message | CustomAgentMessages[keyof CustomAgentMessages] (packages/agent/src/types.ts). Message comes from @earendil-works/pi-ai and is the user / assistant / toolResult union the providers understand. CustomAgentMessages is an empty interface that apps extend via declaration merging; the empty interface keeps the base union identical to Message until an app augments it.

The coding agent augments it in packages/coding-agent/src/core/messages.ts:

declare module "@earendil-works/pi-agent-core" {
	interface CustomAgentMessages {
		bashExecution: BashExecutionMessage;
		custom: CustomMessage;
		branchSummary: BranchSummaryMessage;
		compactionSummary: CompactionSummaryMessage;
	}
}

The CustomMessage type carries role: "custom", a customType discriminator, content, display, optional details, and a timestamp. The coding agent derives concrete messages from it such as SessionSlashCommandMessage and AgentSessionMessage (the latter in packages/coding-agent/src/core/agent-messages.ts).

Conversion to LLM messages is a two-step pipeline owned by the loop config in packages/agent/src/types.ts and consumed in packages/agent/src/agent-loop.ts (streamAssistantResponse):

flowchart LR
    A[AgentMessage[]] --> B[transformContext?]
    B --> C[AgentMessage[]]
    C --> D[convertToLlm]
    D --> E[Message[]]
    E --> F[LLM provider]
Loading

transformContext (optional) prunes or injects context at the AgentMessage level before every LLM call. convertToLlm maps each AgentMessage to a Message the provider accepts, or drops it. Both run inside the loop in packages/agent/src/agent-loop.ts, so custom types never leak to the wire unless convertToLlm chooses to include them.

The coding agent supplies the real implementations in packages/coding-agent/src/core/messages.ts (convertToLlm) and wires them into its session runtime (packages/coding-agent/src/core/sdk.ts, packages/coding-agent/src/core/agent-session.ts). Its convertToLlm turns bashExecution, custom, branchSummary, and compactionSummary into user text messages and filters out custom types that are UI-only (for example SESSION_SLASH_COMMAND, SESSION_SLASH_COMMAND_RESULT, and COMPACTION_OUTCOME).

On the wire, the coding agent's AgentSessionEvent stream is mapped to web messages by web/server/src/event-mapper.ts. toChatMessageFromAssistant turns an AssistantMessage into a ChatMessage with text, tool-Thinking, and tool-* parts; toChatMessageFromUser turns a UserMessage string or text blocks into a ChatMessage text part. The resulting ChatMessage is defined in web/protocol/src/chat-types.ts.

Integration points

  • packages/agent defines and runs the loop over AgentMessage (packages/agent/src/agent-loop.ts).
  • packages/ai provides the Message union and provider streaming that AgentMessage embeds and converts to.
  • packages/coding-agent extends CustomAgentMessages (packages/coding-agent/src/core/messages.ts) and converts messages to LLM shape.
  • web/server/src/event-mapper.ts maps AgentMessage / assistant stream events to ChatMessage for the web.
  • web/protocol/src/chat-types.ts declares the ChatMessage wire shape.

Key source files

Path Purpose
packages/agent/src/types.ts AgentMessage, Message union embed, CustomAgentMessages, AgentLoopConfig with transformContext / convertToLlm
packages/agent/src/agent-loop.ts Turn loop; applies transformContext then convertToLlm in streamAssistantResponse
packages/coding-agent/src/core/messages.ts Extends CustomAgentMessages; implements convertToLlm for coding-agent message types
packages/coding-agent/src/core/agent-messages.ts AgentSessionMessage custom type for agent-to-agent messaging
packages/coding-agent/src/core/sdk.ts Wires convertToLlm and transformContext into the session SDK
web/server/src/event-mapper.ts toChatMessageFromAssistant / toChatMessageFromUser mapping to ChatMessage
web/protocol/src/chat-types.ts ChatMessage and part types on the wire

Related pages

Clone this wiki locally