PiG Documentation

Guides and references for configuring, using, and extending PiG.

Message types

PiG uses one message format in session files, in JSON and RPC events, and in the Go SDK. This page defines the messages and the content blocks inside them. The JSON field names match Pi 0.87.1.

Every message has a role field that names its type. A message timestamp is a Unix time in milliseconds. Session entries use ISO 8601 timestamps instead. See session file format.

The Go definitions live in two packages:

  • github.com/MichaelKinsy/PiG/ai defines the content blocks, Usage, and the provider-facing messages.
  • github.com/MichaelKinsy/PiG/agent defines AgentMessage, the message type that sessions and events carry.

Content blocks

A content block has a type field. PiG knows four block types.

Text

{"type":"text","text":"The tests pass."}
Field
Type
Meaning
textstringThe text.
textSignaturestring, optionalProvider metadata. Pass it through unchanged.

Go type: ai.TextContent.

Image

{"type":"image","data":"iVBORw0KGgo...","mimeType":"image/png"}
Field
Type
Meaning
datastringThe image bytes, base64-encoded.
mimeTypestringThe media type, such as image/png or image/jpeg.

Go type: ai.ImageContent.

Thinking

{"type":"thinking","thinking":"The failing test reads a stale fixture.","thinkingSignature":"..."}
Field
Type
Meaning
thinkingstringThe model's visible reasoning.
thinkingSignaturestring, optionalProvider data that lets PiG send the block back later. Pass it through unchanged.
redactedboolean, optionaltrue when the provider hid the reasoning. The text can then be empty while the signature holds encrypted data.

Go type: ai.ThinkingContent.

Tool call

{"type":"toolCall","id":"call_1","name":"read","arguments":{"path":"README.md"}}
Field
Type
Meaning
idstringThe call ID. The matching tool result repeats it.
namestringThe tool name.
argumentsobjectThe tool arguments.
thoughtSignaturestring, optionalProvider data. Pass it through unchanged.
namespacestring, optionalThe OpenAI Responses namespace of a namespaced tool.

Go type: ai.ToolCall.

Usage

Assistant messages always carry usage. A tool result carries usage only when the tool made its own model calls.

{"input":1200,"output":340,"cacheRead":800,"cacheWrite":0,"totalTokens":2340,"cost":{"input":0.0012,"output":0.0034,"cacheRead":0.0002,"cacheWrite":0,"total":0.0048}}
Field
Type
Meaning
inputnumberInput tokens.
outputnumberOutput tokens.
cacheReadnumberTokens read from the prompt cache.
cacheWritenumberTokens written to the prompt cache.
cacheWrite1hnumber, optionalThe part of cacheWrite stored with one-hour retention.
reasoningnumber, optionalReasoning tokens. They are already part of output, so do not add them again.
totalTokensnumberTotal tokens.
costobjectCost of input, output, cacheRead and cacheWrite, and the total.

Tool-result usage counts toward session statistics. It is not part of the usage of the main model call.

Go type: ai.Usage.

Model messages

These four roles are the messages a provider understands.

System message

A system message sets the instructions and the tool set from its position in the transcript onward.

{"role":"system","content":"","sections":{"preamble":"You are an expert coding assistant..."},"timestamp":1768485600000}
Field
Type
Meaning
contentstring or text blocksInstruction text.
sectionsobject, optionalNamed prompt sections in order. A later message replaces a section by name. A null value removes the section.
toolsAddedarray, optionalFull definitions of tools that become available here.
toolsRemovedarray, optional{"name": ...} references to tools that stop being available here.

The first system message declares the starting prompt and tools. Replay the later ones in order to get the current state.

Pi's message-types.md also lists a replace field. The Pi 0.87.1 source does not define that field, and PiG does not read or write it.

Go type: ai.SystemMessage.

User message

{"role":"user","content":[{"type":"text","text":"Fix the failing test."}],"timestamp":1768485601000}

content holds text and image blocks. PiG also accepts a plain string when it reads a message, and it turns the string into one text block. It always writes an array.

Go type: agent.UserMessage, or ai.UserMessage for a provider request.

Assistant message

{"role":"assistant","content":[{"type":"text","text":"Done."}],"api":"openai-responses","provider":"openai","model":"gpt-5","usage":{"input":1200,"output":340,"cacheRead":0,"cacheWrite":0,"totalTokens":1540,"cost":{"input":0,"output":0,"cacheRead":0,"cacheWrite":0,"total":0}},"stopReason":"stop","timestamp":1768485605000}
Field
Type
Meaning
contentarrayText, thinking and tool-call blocks.
apistringThe provider API that produced the message.
providerstringThe provider name.
modelstringThe requested model ID.
responseModelstring, optionalThe model the provider reports, when it differs from model.
responseIdstring, optionalThe provider's response ID.
providerThinkingLevelstring, optionalThe thinking level the provider applied.
diagnosticsarray, optionalRuntime diagnostics, each with type, timestamp, and an optional error and details.
usageobjectSee Usage.
stopReasonstringWhy the response ended. See below.
deferredobject, optionalA handle for a response that the provider finishes later.
errorMessagestring, optionalThe error text when stopReason is error or aborted.
rawStopReasonstring, optionalThe provider's own stop reason.
endTurnboolean, optionalWhether the provider marked the end of its turn.

stopReason is one of these values:

Value
Meaning
pendingThe message is still streaming.
stopThe model finished.
lengthThe model reached its output limit.
toolUseThe model called one or more tools.
errorThe request failed.
abortedThe run was stopped.
deferredThe provider will finish the response later.

A deferred handle has provider, modelId, api and id, and optionally expiresAt, pollAfterMs and data.

Go type: agent.AssistantMessage, or ai.AssistantMessage for a provider request.

Tool result

{"role":"toolResult","toolCallId":"call_1","toolName":"read","content":[{"type":"text","text":"# Project"}],"isError":false,"timestamp":1768485603000}
Field
Type
Meaning
toolCallIdstringThe id of the tool call.
toolNamestringThe tool name.
contentarrayText and image blocks that the model sees.
detailsany, optionalTool-specific data for renderers and extensions. The model does not see it.
usageobject, optionalModel usage of the tool itself.
isErrorbooleanWhether the tool failed.

Go type: agent.ToolResultMessage.

Coding agent messages

PiG adds four roles for the coding agent. Before a model request, PiG turns each of them into user-role text, with the exceptions that this section names.

Shell execution

PiG records a shell command that you run with ! or !!, or through the RPC bash command. It is not a tool result.

{"role":"bashExecution","command":"go test ./...","output":"ok ...","exitCode":0,"cancelled":false,"truncated":false,"timestamp":1768485610000}
Field
Type
Meaning
commandstringThe command as typed.
outputstringThe combined output.
exitCodenumberThe exit status.
cancelledbooleanWhether the command was stopped.
truncatedbooleanWhether PiG shortened the output.
fullOutputPathstring, optionalThe file that holds the full output when PiG shortened it.
excludeFromContextboolean, optionaltrue for !! commands. PiG does not send them to the model.

Custom message

An extension creates a custom message when it sends a message into the session.

{"role":"custom","customType":"review-note","content":"Check the error path.","display":true,"timestamp":1768485620000}
Field
Type
Meaning
customTypestringA name that the extension chooses.
contentstring or arrayThe text, or text and image blocks.
displaybooleanWhether the terminal UI shows the message.
detailsany, optionalExtension data. The model does not see it.

PiG sends a custom message to the model when its content is a string. Pi also sends a custom message whose content is an array of blocks. PiG currently leaves such a message out of the model request.

Branch summary

{"role":"branchSummary","summary":"Tried a cache fix; it did not help.","fromId":"e5f6a7b8","timestamp":1768485630000}

PiG builds this message from a branch_summary session entry. fromId is the entry the branch started from, or null.

Compaction summary

{"role":"compactionSummary","summary":"## Goal\n...","tokensBefore":50000,"timestamp":1768485640000}

PiG builds this message from a compaction session entry. tokensBefore is the context size before compaction. See compaction.

AgentMessage in Go

agent.AgentMessage holds exactly one message. It has one pointer field per model role and a map for every other role:

Field
Role
System *ai.SystemMessagesystem
User *agent.UserMessageuser
Assistant *agent.AssistantMessageassistant
ToolResult *agent.ToolResultMessagetoolResult
Custom map[string]anybashExecution, custom, branchSummary, compactionSummary, and any other role

Role() returns the role string. MarshalJSON and UnmarshalJSON read and write the flat JSON shapes on this page. A message with an unknown role decodes into Custom, so code that reads messages from an extended host keeps working. The constants agent.RoleBashExecution, agent.RoleCustom, agent.RoleBranchSummary and agent.RoleCompactionSummary name the coding agent roles.

Adapted from upstream Pi documentation · Upstream documentation ↗ · MIT License