Why the key stays on the server
A provider key in client code is a key anyone can copy. It is included in the app bundle, where anyone who opens the site or app can read it and spend against your account. Obfuscation does not fix that. Gemmein holds the key on the server and gives the browser a named tool to call instead.
Where the key goes
In the cloud, you paste the key on the dashboard's AI page, never in a file and never in the SDK. On your machine, npx gemmein dev reads the key from an environment variable such as GEMMEIN_AI_KEY_OPENAI. Without one, it answers with a sample reply marked x-gemmein-ai: fake. Keys never sync between the two. You can connect OpenAI, Anthropic, Google, Deepgram, Replicate, fal, AssemblyAI, ElevenLabs or Runway, or any OpenAI-compatible chat provider (OpenRouter, Mistral, Groq).
ai_not_configured until you paste the key, and then the same tool runs with no further change.How it works
A tool is a file in your project: provider, model, instructions, template and inputs. Gemmein builds the provider request from the tool and runs it on your key for a signed-in person, at the tool's price. The browser sends only a tool name and its inputs, and the key is never in a request your app can read.
{
"label": "Deep Research",
"provider": "openai",
"model": "gpt-4o",
"credits": 20,
"instructions": "You are a careful research assistant. Answer with sources.",
"promptTemplate": "Research this question:\n\n{{question}}",
"inputs": [
{ "name": "question", "type": "text", "required": true, "maxLength": 2000 }
]
}// A name and inputs. No key. No prompt. No provider request.
const answer = await g.ai.runText("deep-research", {
question: "How can I improve client onboarding?"
});Upload the tool with npx gemmein sync.
Browser calls to the provider
If the browser built the provider request, your prompt would be in the bundle and the caller would control the request. So raw calls from the browser are off for every key until you turn them on for an app that needs them.
Images, audio, video and embeddings
Image, audio, video and transcript tools run on the same key. For embeddings, call the provider from your own server with your own key. To use your own model, run it behind an external tool at your URL. Gemmein still checks who the person is and what they hold.
Prompt for your coding agent
Paste this into Cursor, Claude, Bolt or Lovable so your agent keeps the key on the server from the start.
Read https://docs.gemmein.com/llms.txt and https://docs.gemmein.com/ai. I do not want my OpenAI key in the browser or app bundle. Show me how the provider key stays on the server (pasted in the dashboard) and how my app calls a named AI tool by name with inputs, without sending the key or a prompt. Include the tool definition file and the client call.
npx gemmein devRead the getting-started guide