Developer Guide
Prompt contributions
Short instruction blocks the app merges into the system prompt while your extension is enabled. Use them for policy: when to call a tool, how to follow up, what tone to keep.
Contribution shape
textstringrequiredThe instruction. Whitespace-only text is dropped.placement'system_pre' | 'persona_post' | 'tool_guidance' | 'system_post'requiredWhich section of the prompt it renders in.prioritynumberSort key within a placement. Lower runs first. Defaults to 0.idstringOptional stable id. Used as the final tiebreaker when sorting and shown in the extension devtools.export function getPromptContributions(ctx) {
const style = ctx.extensionState.resolvedSettings.photoStyle || 'candid';
return [
{
placement: 'system_pre',
priority: 10,
text: 'When a visual beat would help, send a photo near the end of the turn.',
},
{
placement: 'tool_guidance',
priority: 20,
text: `Photos are ${style}. After send_photo succeeds, acknowledge the photo once and keep the reply short.`,
},
];
}
export async function onBeforeLLMRequest(ctx) {
if (!(await isCameraReady())) {
return {
promptContributions: [
{ placement: 'system_post', text: 'The camera is offline this round. Do not offer photos.' },
],
};
}
}Placements and how they render
Contributions from every enabled extension are grouped by placement, sorted by priority and then id, and rendered under fixed headings. Sections with no text are omitted. Turn-start contributions from getPromptContributions are woven into the system prompt at four different positions. Per-round contributions from onBeforeLLMRequest and emitted instructions go into one extra system message appended after the chat history, under the same headings.
system_pre# Extension InstructionsRight after the persona's own prompt and traits, before visual context and memories.persona_post# Persona Extension GuidanceDirectly after system_pre, so it reads as part of the persona's rules.tool_guidance# Tool GuidanceAfter memories, Current Toys, and Player Information, just before the scenario.system_post# Additional InstructionsAfter the scenario, immediately before the closing Goal section.The two examples above render like this:
--- system prompt (built once per turn) --- ...persona and personality traits... # Extension Instructions: When a visual beat would help, send a photo near the end of the turn. ...visual context, summaries, memories, Current Toys, Player Information... # Tool Guidance: Photos are candid. After send_photo succeeds, acknowledge the photo once and keep the reply short. ...scenario... # Goal: ... --- extra system message (appended after the history, per round) --- # Additional Instructions: The camera is offline this round. Do not offer photos.
Three ways to contribute
getPromptContributions(ctx)every turnCollected once per turn before the first model round, except on silent scenario-arrival turns. May be async. ctx has extensionKey, personaId, sessionId, extensionState, and visualContext.onBeforeLLMRequest → promptContributionsevery roundCollected before each model round in the turn, so it can react to tool results from earlier rounds.runtime.emitPromptInstruction(c) / appendAssistantInstruction(text)mid-turnQueue an instruction from inside a tool or hook. It is attached to the next model round of the same turn and discarded when the turn ends.What belongs here
Prompt contributions
Tool policy and follow-up rules.
Style defaults the extension owns.
Short conditions for this turn or round.
Somewhere else
Live device or player readouts. Use promptState, which renders in fixed sections the model already knows.
Counters and scene flags. Use variables, and summarise them in one line if the model needs them.
Anything already visible in the chat.