-
Notifications
You must be signed in to change notification settings - Fork 0
primitives 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.
- 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
convertToLlmstep decides what the model should see.
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]
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.
-
packages/agentdefines and runs the loop overAgentMessage(packages/agent/src/agent-loop.ts). -
packages/aiprovides theMessageunion and provider streaming thatAgentMessageembeds and converts to. -
packages/coding-agentextendsCustomAgentMessages(packages/coding-agent/src/core/messages.ts) and converts messages to LLM shape. -
web/server/src/event-mapper.tsmapsAgentMessage/ assistant stream events toChatMessagefor the web. -
web/protocol/src/chat-types.tsdeclares theChatMessagewire shape.
| 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 |
-
Core agent runtime - where
AgentMessageoriginates -
LLM messages and streaming - the
Messageunion and streaming events - Session runtime - how the coding agent hosts the loop
-
Wire contract -
ChatMessagevalidation -
Event mapper - how
AgentMessagemaps to the web - Streaming flows - end-to-end streaming
- Glossary - term definitions