Ren'Py Story Architect's AI features are optional and proposal-based. The app is fully usable with AI disabled. There are two separate AI surfaces:
- Scene / translation AI — proposes dialogue rewrites, continuations, and translations.
- Diagnostic AI — explains diagnostics and suggests fixes (never mutates anything).
Free machine translation (Google / MyMemory) is separate from AI and needs no key at all — see LOCALIZATION.md.
CRITICAL INVARIANTS:
- The browser never stores or requests a secret provider API key.
- The browser never holds a
NEXT_PUBLIC_*secret. - The browser never holds a bearer token, session token, or any other Authorization-shaped credential.
- Direct mode sends only
Content-Type: application/json. NoAuthorizationheader is ever sent. - AI proposals are validated before apply.
- AI cannot mutate the project without explicit user acceptance.
- Accepted AI changes go through the normal undo/redo history.
- AI cannot approve translations (accepted translations are always
draft). - Diagnostic AI explains facts produced by the analyzers; it never invents diagnostics and has no mutation API.
No AI features. The app is fully usable.
The browser calls an OpenAI-compatible chat completions endpoint directly.
Direct mode sends only Content-Type: application/json — no
Authorization header.
Configuration:
- Endpoint URL — e.g.
http://localhost:1234/v1. - Model — e.g.
gpt-4o-mini,llama3.1,qwen2.5.
Use cases:
- Local model server (LM Studio, Ollama's OpenAI compat endpoint, llama.cpp server).
- Your own CORS-enabled proxy that injects auth server-side.
- Endpoint where authentication is handled outside browser-held secrets.
If your endpoint requires authentication: you cannot use direct mode. Switch to the same-origin proxy mode (below) and put the secret in a server env var, or run your own external proxy that injects auth server-side.
CORS requirement: The endpoint must allow requests from your Story
Architect origin. For local model servers, this usually means setting
--cors-allow-origins "*" or similar.
The browser calls /api/ai/chat on the same origin. The server route
reads environment variables and forwards the request to the configured
upstream. A /api/ai/status route exposes whether the proxy is configured.
Server-side configuration (NEVER in client bundles):
STORY_ARCHITECT_AI_BASE_URL=http://127.0.0.1:1234/v1
STORY_ARCHITECT_AI_MODEL=my-model
STORY_ARCHITECT_AI_API_KEY=optional-secretSTORY_ARCHITECT_AI_BASE_URL and STORY_ARCHITECT_AI_MODEL are required to
enable the proxy; STORY_ARCHITECT_AI_API_KEY is optional (some upstreams
don't need it). The browser cannot influence the upstream URL — it can only
request that the server proxy a completion. If the server has no AI env
configured, the proxy returns not_configured.
Self-hosting: Set these in your server environment (e.g. .env for
local dev, or your hosting platform's env vars). NEVER commit .env to
git. NEVER put STORY_ARCHITECT_AI_API_KEY in a NEXT_PUBLIC_* variable.
Do not expose a same-origin proxy backed by a paid API key on a public deployment unless you add authentication, rate limiting, and usage controls. Otherwise anonymous visitors may consume the server owner's provider quota.
If you deploy this app publicly:
- Keep AI disabled by default (it is the default).
- Do not set
STORY_ARCHITECT_AI_*env vars on the public deployment unless you have explicitly added authentication, rate limiting, and usage controls in front of/api/ai/chat. - Prefer requiring each user to configure their own direct-mode endpoint (e.g. a local model server) for AI features.
The Public Alpha repository ships the proxy code, but a hosted demo should keep it disabled unless protected.
The AI Settings dialog has a Test connection button that issues a minimal probe. No automatic provider request is made on every render.
- Only the context required for the selected operation is sent to the configured endpoint.
- Story Architect never stores a provider API key, bearer token, or any other credential in the browser.
- Direct mode sends no
Authorizationheader. - AI proposals are previewed as a diff and applied only after you click Accept.
Can:
- Propose dialogue/narration text rewrites (improve, fix grammar, shorten, expand, custom rewrite).
- Propose scene continuations (dialogue/narration only, max 20 blocks).
- Propose translations (translate, improve, check).
- Suggest improvements to existing translations.
- Explain diagnostics and propose fixes (with
requiresHumanReviewalways forced).
Cannot:
- Modify architecture (nodes, edges, routes, stages, groups).
- Modify variables.
- Generate Python/code.
- Generate media.
- Auto-apply any proposal.
- Approve translations (accepted translations are always
draft). - Apply a diagnostic fix directly (no write/patch API exists in the web build).
The Diagnostics panel and the Project panel's parser warnings offer
[Explain with AI] (always) and [Suggest Fix] (unless the diagnostic
is explain_only). Explanations and fix proposals are structured and
validated; there is never an Apply button — fixes are proposals only, for
you to review.