Skip to content
quest'n'click

StudioHow-toFor authorsApplies from 4.2.1

The Assistant: bring your own key

Cette page en françaisThis page on the GitHub wiki

The Assistant is a chat drawer in the Studio where you ask a model of your choice (OpenAI, Anthropic, Ollama, Mistral, or any OpenAI-compatible endpoint) to help complete the game. It has the same tools as the MCP server and knows what you have selected. You bring the key; without one, your request becomes a task for an AI agent connected through MCP.

What you get

A model that reads the room or the panel you are on, writes look lines, topics or hints into the game files with the Studio's tools, and runs validate and solve; the Studio reloads what it wrote.

Context and versions

The local Studio (npm run studio, engine repository or created project), where the Studio's server relays the call, and the demo Studio, where the page calls the provider itself. True from 4.2.1.

Prerequisites

  • The Studio running (overview).
  • An API key of a provider (with a spending limit), or Ollama on your machine with a model that supports tools, or an MCP agent for the no-key route (Local MCP: setting up each client).

Where to run the commands

In the browser: the Assistant button in the top bar, or the a key when no field has focus. For Ollama, the ollama commands run on your machine.

Steps

  1. Pick a provider (gear icon). Presets:

    PresetBase URLModels offeredKey
    OpenAIhttps://api.openai.comgpt-5, gpt-5-mini, gpt-4.1yes
    Anthropic (default)https://api.anthropic.comclaude-sonnet-5 (default), claude-opus-5, claude-haiku-4-5yes
    Ollama (local)http://localhost:11434llama3.1, qwen3, mistral-smallno
    Mistralhttps://api.mistral.aimistral-large-latest, mistral-small-latestyes
    Customany OpenAI-compatible base URLtyped by youas the endpoint needs

    For Ollama, pull the model first (ollama pull llama3.1) and pick one that supports tools.

  1. Paste your key. It is kept in this browser tab only (sessionStorage) and sent with each request; the other settings (preset, URL, model) are remembered in localStorage, never the key. Forget the key removes it. Use a key with a spending limit, and forget it on a shared computer.
  1. Ask. The composer shows what the request is about: house › pantry (prop) (the room and the entity selected in Rooms), storyboard › <board> › <panel> (panel) (the selected panel, as edited, even unsaved), or the whole game. Quick actions use it: Write 3 look lines, Suggest a puzzle for this room, Write the talk topics for this character, Find what's missing (validate + solve), Draft the hint chain, Generate the art prompts for this sheet.
  1. Read the answer. Answers are light markdown (paragraphs, lists, code). Each tool call is a chip you unfold to see its arguments and result. Stop aborts the request (the server aborts the provider call too); New chat starts over. After a turn that wrote something, the Studio reloads the room, the storyboard (a banner when it has unsaved edits) or the notes, and runs Check.

How it works

  • One tool registry. tools/studio/tools.ts defines every tool (name, description, schema, handler over a backend); the MCP server and the Assistant both use it, so the Assistant has the MCP server's tools: list_rooms, get_room, set_text, set_value, add_entity, set_layout, get_storyboard, set_storyboard, get_notes, add_note, validate, solve, screenshot, read_doc, run_tests, asset_prompts and the others (MCP tools).
  • The relay (local Studio). The page posts the conversation to POST /__studio/api/assistant/chat with { provider: { kind, baseUrl, model, apiKey? }, messages: [{ role, content }], context } (a body of 4 MB at most). The relay (tools/studio/assistant.ts, loop in tools/studio/assistant-loop.ts) builds a system prompt from AGENTS.md, the game (rooms, characters, items, checkpoints) and the current selection with its texts. It calls the model, runs the tool calls on the game files, and streams server-sent events back: { type: 'text', delta }, { type: 'tool_call', id, name, args }, { type: 'tool_result', id, name, result, isError? } (result cut at 4 KB in the event; the model gets up to 32 KB), { type: 'error', message }, then { type: 'done', usage?, wrote?, stopped? }. The model is told to ask before destructive changes and to keep the game's voice. Earlier turns are sent back as text only.
  • Two wire formats, no SDK. OpenAI-compatible POST <base>/v1/chat/completions with tools and stream: true (OpenAI, Mistral, Ollama, most others), and Anthropic's POST <base>/v1/messages with tools, x-api-key and anthropic-version: 2023-06-01. Streaming answers are read as server-sent events; a provider that answers plain JSON works too. A base URL may or may not end in /v1.

Limits

LimitValueWhen it is reached
Tool rounds per request12Stopped after 12 tool rounds: ask again to continue.
One provider call60 s<url> did not answer within 60 s
A provider's answer8 MBthe provider's answer exceeds 8 MB
Redirectsnone followed<url> answered with a redirect (…): refused, a provider must answer at its own address

Custom providers and WEB_SCUMM_ALLOW_CUSTOM_PROVIDER

The relay accepts the presets' addresses (OpenAI, Anthropic, Mistral) and Ollama on this machine (localhost, 127.0.0.1, [::1]). Any other base URL is refused unless the Studio was started with the opt-in:

# in the engine repository or the created project
WEB_SCUMM_ALLOW_CUSTOM_PROVIDER=1 npm run studio

Even then, a custom provider must use HTTPS and cannot target a local or private network host (loopback, unspecified, private and link-local addresses in both IP families, .local, .internal), and a provider URL cannot carry credentials. See Local and LAN security and WEB_SCUMM_ALLOW_CUSTOM_PROVIDER.

Key safety

The key stays in this browser tab (sessionStorage) and goes with each request. On the local Studio, the relay keeps it in memory for that request only: never written to disk, never logged, and removed from error messages (replaced by ***). In the demo Studio it goes from the page straight to the provider.

No key: tasks for an MCP agent

Without a key (and not on Ollama), the composer offers Send as a task to the AI agent. The page posts POST /__studio/api/assistant/task with { about, text }, which appends a note with author: "you" and task: true to notes.json, about the current selection. An agent connected through MCP (Claude Code, Cursor, Codex, Gemini CLI…) reads it with get_notes and does the work; the Studio shows its edits live, and the Notes tab tags these notes "task" (Notes).

In the demo Studio

There is no relay on a static host: the page runs the same loop itself, with the tools on the browser backend (edits kept as demo patches, Demo mode). screenshot, run_tests and asset_prompts are not available, set_value answers that it needs the dev server, and read_doc has only CONTENT_GUIDE. The browser calls the provider directly: Anthropic gets its anthropic-dangerous-direct-browser-access header; OpenAI refuses browser calls from unknown origins for some keys, and the error says so. Use Ollama on your machine, allowing the page's origin, or the local Studio, whose server relays the call:

# on your machine, for the demo Studio's page
OLLAMA_ORIGINS=<the page's origin> ollama serve

Tasks go into the demo's notes, and its patch.

Applies from 4.5.0 to …

Documentation in the demo

A demo built from 4.5.0 also carries the wiki's ready pages in its snapshot: the demo's Assistant can use search_docs, list_docs and read_doc by id on them.

Expected result, and how to check it

The answer streams in; a tool chip shows validate returning { ok: true … }; after a write, the room or the storyboard shows the change and git diff holds it.

Common errors

SymptomCauseFix
custom provider URLs are disabled (set WEB_SCUMM_ALLOW_CUSTOM_PROVIDER=1 to opt in)A base URL that is no presetRestart the Studio with the opt-in, or use a preset
custom providers must use HTTPS and cannot target local or private network hostshttp://, or a private addressUse an HTTPS public endpoint; for a local model, the Ollama preset
`provider.kind` must be openai, anthropic or ollamaA hand-made requestUse the settings dialog
The browser could not reach <url> … (CORS)Demo Studio, provider refusing browser callsOllama with OLLAMA_ORIGINS, or the local Studio
Stopped after 12 tool roundsThe task needs more roundsAsk again to continue

More: Studio troubleshooting.

Files or data changed

Whatever the tools write (room files, layouts, storyboard.json, notes.json), as the Studio would. The key is never written; the settings without the key are in the browser's localStorage under web-scumm.studio-assistant.

Recovery or going back

The model's writes go through the Studio's operations: undo them from the header during the session, or with git.

References