Reference
Tool fields, numbers, codes, raw provider calls and the ai_calls record.
Tool fields
| Field | Rule |
|---|---|
name | 1–40 lowercase letters, numbers or hyphens, starting with a letter or number. Fixed once created |
label | 1–60 characters, shown to the person and on the ledger |
kind | chat (the default: answers now) or a job kind: generate (an image, a video or audio out) or transcribe (audio in, text out). A job tool answers with a run |
provider | one that serves the tool's kind (see Tool kinds and providers); a tool on a provider that does not serve its kind is refused at save. A job tool may instead run on external, your own pipeline: no key, no alias, and model your own label (up to 120 characters) or nothing |
model | pins the provider's own model id (gpt-4o; owner/name on Replicate, fal-ai/flux/dev, gen4.5). On openai and google a job tool's model names the endpoint: gpt-image-1 (images), gpt-4o-mini-tts (speech), whisper-1 or gpt-4o-transcribe (transcription), sora-2 (video); imagen-4.0-generate-001, veo-3.0-generate-001, gemini-2.5-flash (audio in). Deepgram's is nova-3; AssemblyAI takes none |
accepts | the kinds of file the tool takes: any of image, audio, video, document, each one the provider and model read (see Files a tool takes). Absent: as before ticks (a chat tool takes no files; a job tool takes what its provider takes) |
inputMaxMb | a lower limit per ticked kind, in whole MB: { "video": 200 }. Never above the provider's or the platform's limit. Optional, set in the tool's file only |
url | provider external only: your pipeline's own address (https; loopback http:// only on gemmein dev). Set on creation or later; a run started before it is set is refused tool_incomplete before any credit moves. See Your own pipeline |
credits | a whole number from 1 to 10,000, or 0 only with requiresAny set: the tool is included with access, still metered, never charged. 0 with no requiresAny is refused at save |
unit / per | call (the default; per is 1) or tokens (per 1,000 by default, 1 to 1,000,000). A generate tool meters images, seconds or characters, a transcribe tool seconds, and either may use call. How each unit reserves and settles is under Pricing |
params | a job tool's provider request, composed on the server in place of promptTemplate: a JSON object whose string values may carry {{input}} placeholders naming declared inputs ({ "prompt": "{{prompt}}", "aspect_ratio": "16:9" }). A string that is one placeholder and nothing else takes the input's typed value, so a number stays a number. The browser never shapes the request |
alias | the name of one of the app's model aliases, in place of model, never both |
requires / requiresAny | requires is one access key (access:pro-max); requiresAny is up to 10 plan or product keys. The person needs any one of them, so a Max plan may use a tool that requires Pro without a second grant. requiresAny wins when both are read; a tool that still names only requires behaves as requiresAny with that one key. A person holding none is refused, naming every key |
instructions | the system prompt, up to 20,000 characters. Never leaves the server |
promptTemplate | the user turn, with {{input}} placeholders naming declared inputs; absent, the inputs are rendered one per line |
inputs | up to 20 of { name, type: text | number | boolean | file, required?, maxLength? }; a text input holds 4,000 characters unless it says (up to 20,000). A file input takes a sealed file ref the person already owns (what g.files.upload returned for an image or document, or an earlier AI run's own output for audio or video) or an https URL. The provider receives a short-lived signed link, never the ref |
recordCalls | keep the prompt and answer on ai_calls. Off by default |
bounds | maxOutputTokens (a composed call's ceiling; 4,096 when unset), stream, maxBodyBytes (raw calls only, up to 262,144), deadlineMinutes (external tools only: how long a run may take before it expires, 1 to 1,440; 60 when unset) |
bounds.maxUnits | a metered job tool's ceiling: the most units one run may bill, 1 to 1,000,000. Required when unit is images, seconds or characters; the hold on every run is priced from it |
Numbers
- The credits the owner set for that tool; one by default.
- Up to 50 tools per environment; a name is at most 40 characters, a label at most 60.
- 20 calls per person per minute.
- 64 KB of inputs on a
g.ai.runcall. - 256 KB raw request body on a
g.ai.chatcall, unless a tool sets a smaller cap (up to 262,144 bytes); nested at most 32 levels. - 170 seconds in all; on a stream, 10 seconds to the first response headers.
- Every call counts toward the app's monthly API request ceiling like any other request.
- One test call per minute from the AI page; a test call spends no credits.
Codes
| Code | Status | Meaning · what to do |
|---|---|---|
raw_calls_off | 403 | The browser may not compose provider requests for this provider. Call a named tool with g.ai.run, or switch raw calls on for the key on the AI page |
invalid_inputs | 400 | An input is unknown, missing, the wrong type or over its cap, or a file input is not a sealed file ref or an https URL. The message names the input |
input_not_accepted | 400 | The file is a kind the tool does not tick, or a type its provider does not read. The message names what it takes |
input_too_large | 413 | The file is over the tool's, the provider's or the platform's limit. The message names the limit |
input_not_supported | 409 | The tool's model does not read that kind of file. Pick a model that does on the AI page |
input_rejected | 502 | The provider refused the file before answering. Nothing was spent |
input_busy | 429 | This person already has a large file on its way to the provider. Retry when it finishes |
tool_incomplete | 409 | The tool composes nothing: no template and no inputs. On a job tool: no params, or its alias is gone; on an external tool: no URL |
unknown_tool | 404 | No AI tool by that name in this environment |
tool_disabled | 403 | The owner switched this tool off |
entitlement_required | 403 | The tool requires a plan or product this person lacks; the message names it |
model_pinned | 403 | This tool's model is fixed; leave model out of the body |
too_many_tools | 409 | An environment holds at most 50 AI tools |
invalid_tool | 400 | Creating or updating a tool with a bad field; the message names it |
credits_exhausted | 402 | The person's balance is below the tool's price, or its ceiling on a per-token or job tool; the message names both. Show the pack |
ai_not_configured | 409 | No key for this tool's provider on this app and environment. The owner pastes one on the AI page, and the tool then runs unchanged. The person reads "This feature isn't available right now."; Development adds the owner's sentence in ownerDetail, Live never does |
provider_required | 400 | More than one provider key is set; pass provider |
model_not_allowed | 403 | The owner's allowlist names the models this app may call; the message lists them |
ai_capped | 429 | 20 calls per person per minute; wait for resetAt |
payload_too_large | 413 | On g.ai.run: the inputs are over 64 KB; send less. On g.ai.chat: the raw body is over 256 KB; shorten the conversation you send |
invalid_body | 400 | The body is not the provider's JSON request object, or is nested deeper than 32 levels |
session_required | 401 | No signed-in person; sign in first |
scope_denied | 403 | A secret key called an AI endpoint. AI tools are for the browser; a server calls the provider directly |
provider_unreachable | 502 | The provider did not answer before the first byte. Nothing was charged; the credit is refunded. Retry |
provider_error | the provider's | Thrown by g.ai.text and g.ai.runText: the provider's own non-2xx, its message in err.message. g.ai.chat and g.ai.run return it as it came |
ai_test_capped | 429 | The AI page's test call; one a minute per app |
runs_capped | 429 | Ten open runs per person; wait for one to end, or cancel one |
unknown_run | 404 | No run by this id on this person |
run_ended | 409 | cancel on a run that already ended; read its status |
not_external | 409 | A Gemmein-executed run completes on its own, never by a call to /complete |
Raw provider calls
g.ai.chat(body), where the browser sends the provider's own request, is off
until you switch raw calls on for that key on the AI page. Without the switch it answers
raw_calls_off. With the switch on, the body is forwarded as sent and the answer
passed back byte for byte. A call that names no tool runs as the default tool for one
credit.
gemmein dev's fake provider, with no key set, keeps raw calls open; there is no
switch locally. ?provider= and ?stream=1 on the URL do what the body
fields do.
| Provider | The body you send | Where it goes |
|---|---|---|
openai | Chat completions: model, messages, stream? | OpenAI's chat completions endpoint |
anthropic | Messages: model, max_tokens, messages, stream? | Anthropic's messages endpoint |
google | generateContent: model, contents; stream: true selects the streaming form | Google's generateContent endpoint for that model |
Those three endpoints are the whole list. There is no field for a URL, and no other host is reachable through a chat call.
The ai_calls record
Every call lands as one record in the ai_calls collection, per person: the
tool, the kind, the provider and model, tokens in and out when the provider said, the credits
it cost, how it ended, the refusal code, the latency and the time. The prompt and the answer
are kept only for a tool whose record calls switch is on.
A person reads their own with g.ai.calls(): what they ran, what it cost, how
it ended, and the answer when it was kept. A person never sees the prompt: it is your tool's
request, its template or parameters filled in with their inputs. You read the prompt and the
answer by app on the Records page and on the person's record. Erasure removes a person's
records.
Thanks for telling us.
Thanks for telling us.
Last updated