The bridge keeps protocol data as JSONCodec structs internally. These examples show the JSON shape at process/HTTP boundaries.
{
"type": "ready",
"info": {
"project": "pi_bridge",
"transport": "stdio",
"skills": [],
"plugins": [],
"apis": {
"runtime": [
{
"name": "llm",
"module": "Elixir.Pi.LLM",
"functions": [{ "name": "complete", "arity": 1 }]
}
],
"extensions": []
}
}
}{ "type": "call", "id": 1, "name": "project_eval", "arguments": { "code": "1 + 1" } }{ "type": "result", "id": 1, "text": "2", "isError": false }pi owns provider/model selection, credentials, streaming, cancellation, usage, and transcript UI. BEAM code sends structured requests over the active bridge and receives structured results.
{
"type": "request",
"id": "llm_123_1",
"op": "llm_complete",
"payload": {
"messages": [{ "role": "user", "content": "hello" }],
"opts": {}
}
}{
"type": "response",
"id": "llm_123_1",
"ok": true,
"result": {
"text": "hello from pi",
"usage": null,
"model": "gpt-5.5",
"provider": "openai"
}
}{
"type": "request",
"id": "llm_456_2",
"op": "llm_stream",
"payload": {
"messages": [{ "role": "user", "content": "stream" }],
"opts": {}
}
}{ "type": "llm_chunk", "id": "llm_456_2", "delta": "first " }
{ "type": "llm_chunk", "id": "llm_456_2", "delta": "second" }
{
"type": "llm_done",
"id": "llm_456_2",
"result": {
"text": "first second",
"usage": null,
"model": "gpt-5.5",
"provider": "openai"
}
}Cancellation from BEAM to pi:
{ "type": "llm_cancel", "id": "llm_456_2", "reason": "closed" }Pi.Session workers emit structured snapshots as pi_session events. Field names are camelCase at the JSON boundary via JSONCodec.
{
"type": "event",
"name": "pi_session",
"data": {
"session": {
"id": "session_1",
"parentId": null,
"name": "reviewer",
"status": "done",
"result": "passed",
"error": null,
"startedAt": "2026-06-09T09:00:00Z",
"updatedAt": "2026-06-09T09:00:01Z",
"completedAt": "2026-06-09T09:00:01Z",
"durationMs": 1000,
"prompt": "review this change",
"response": "passed",
"latest": "passed",
"current": null,
"runCount": 1,
"messageCount": 2,
"recentOutput": [],
"events": [
{ "type": "started", "at": "2026-06-09T09:00:00Z", "data": {} },
{ "type": "llm", "at": "2026-06-09T09:00:00Z", "data": {} },
{ "type": "done", "at": "2026-06-09T09:00:01Z", "data": {} }
]
}
}
}Running or streaming sessions may include live activity and recent output without requiring TS renderers to parse event blobs:
{
"status": "running",
"current": "streaming",
"recentOutput": ["first ", "second"],
"runCount": 1
}Reruns increment runCount and update completedAt. Cancelled sessions also set completedAt and clear current before the terminal snapshot is emitted.
The extension exposes session control through private bridge-native stdio tools and slash commands, not model-facing tools. The slash commands dispatch to these calls:
{
"type": "call",
"id": 10,
"name": "pi_session_rerun",
"arguments": { "id": "session_131" }
}{ "type": "result", "id": 10, "text": "ok", "isError": false }{
"type": "call",
"id": 11,
"name": "pi_session_cancel",
"arguments": { "id": "session_163" }
}{ "type": "result", "id": 11, "text": "ok", "isError": false }A rerun emits fresh pi_session snapshots for the same session id with an incremented runCount. A cancel emits one terminal cancelled snapshot.
{ "type": "ui", "op": "status", "key": "ecto", "text": "ecto 1/1" }{ "type": "event", "name": "pi-elixir:demo", "data": { "events": 1 } }Plugin commands are called by the TypeScript extension after it registers /elixir:<name> commands from the ready inventory:
{ "type": "call", "id": 2, "name": "pi_plugin_command", "arguments": { "name": "demo_plugin_status", "args": "smoke" } }Tool hooks use strict hook payload shapes before dispatching to plugin callbacks. pi_plugin_tool_call responses patch tool input only; result hook responses may patch result content or isError.
{ "type": "call", "id": 3, "name": "pi_plugin_tool_call", "arguments": { "toolName": "bash", "toolCallId": "tool_1", "input": { "command": "pwd" } } }{ "type": "result", "id": 3, "text": "{\"block\":\"blocked by plugin\"}", "isError": false }