Developer Guide
Runtime
The runtime is the contract between your module and the app: which exports it reads, when it calls them, and what it hands you when it does.
How a turn runs
Every hook below only fires for extensions that are enabled for the active persona. Hooks run one extension at a time and are awaited. A hook that throws is logged and skipped, and the turn continues.
- 1
onBeforeUserMessageSendruns with the outgoing text. It can rewrite the message or block it with an alert. - 2
getPromptContributionsis collected from every enabled extension and merged into the system prompt. Each extension'spromptStateis rendered into the Current Toys and Player Information sections at the same time. Silent scenario-arrival turns skip this step. - 3For each model round:
onBeforeLLMRequestruns, then the request is sent. Streamed text triggersonAfterAssistantChunk. - 4For each tool call the model makes:
onAfterToolCall, thenexecuteToolon the owning extension, thenonAfterToolResult. The result goes back to the model and a new round starts. - 5When the final reply is complete,
onAfterAssistantMessageruns once.
A turn usually has one round. Tool calls add rounds. Instructions you emit with ctx.runtime.emitPromptInstruction during a round are attached to the next round of the same turn.
Reference pages
Manifest fields
Every field the loader and app surfaces read, including which ones are required.
Runtime exports
Tools, executeTool, useExtension, each lifecycle hook with its context and return value, and emergency stop.
Prompt contributions
Contribution shape, the four placements and where they render, ordering, and request-time additions.
Runtime APIs
Signatures and result shapes for variables, memories, chat, persona, media, UI, artifacts, and the LLM helper.
API versioning
Set apiVersion in the manifest to the version you wrote against. New extensions should use v7. Every version since v1 still loads, and a manifest that asks for a newer version than the app supports is rejected at load time.
v1
Manifest, useExtension(), and browser-side tools.
v2
promptState for the Current Toys and Player Information prompt sections.
v3
Prompt contributions, lifecycle hooks, variables, memories, chat, persona, media, image artifacts, and toy emergency stop.
v4
Chat footer drawer: manifest.chatFooter and FooterComponent.
v5
runtime.emergencyStop() so any extension can trigger the same toy stop as the top-bar button.
v6
Fullscreen overlay slot (manifest.overlay and OverlayComponent), chat.sendMessage(), chat.runTurn(), and ui.toast().
v7
The Patterns system for the app's built-in toy extensions (manifest.supportsPatterns, patternCapabilities, getPatternSink).
The loader does not read getPatternSink from JS modules yet, so a JS extension gains nothing new in v7. Declaring v7 is still correct for new work.