AGDevelop

GDevelop, with your own key

AGDevelop is the studio's fork of GDevelop, the full-featured open-source game engine. The fork's one substantial addition is a complete bring-your-own-key implementation of the "Ask AI" agent: the chat runs against your own OpenAI-compatible endpoint, on your machine, with your key.

Everything else is upstream GDevelop — the editor, the GDJS game engine, the C++ Core, the extensions ecosystem — kept in sync by regular merges. The last upstream commit folded in is 4d867e222b, merged on 2026-11-02. The fork's own code lives in newIDE/app/src/AiGeneration/Byok/ and newIDE/app/src/Fork/, with the Electron-side pieces in newIDE/electron-app/app/.

Pay for your AI somewhere else, use it here

If you make games with GDevelop and pay for an AI subscription somewhere else, this fork lets the built-in assistant use that subscription instead of GDevelop's hosted service.

You point it at any OpenAI-compatible endpoint — OpenAI, OpenRouter, Azure OpenAI, Groq, DeepSeek, a local Ollama or LM Studio server — and pick the model you want per chat. The agent keeps working the whole time, and the whole conversation stays on your machine.

Nothing you type and no key you paste is sent to GDevelop's servers: the agent loop, the tools and the game edits all run inside the editor. You also get an MCP endpoint, so the AI agents you already use — Claude Code, Cursor, your own scripts — can read and edit your GDevelop project directly.

Why the fork exists

Bring-your-own-key has been asked for upstream, repeatedly, and it never shipped. The request is not the studio's — it comes from the GDevelop community, and it is still open.

Two open issues, two closed pull requests

Issue #7932 — "Feature Request: BYOK (Bring Your Own Key/Model) support for GDevelop AI Agent" — was opened in October 2025 and is still open. The maintainer answered it asking for use cases, and several users spelled out exactly why they need it: using an OpenRouter key to test models on demand, running a local model for privacy and zero marginal cost, and not being blocked when the official server is unavailable.

Issue #8854, opened in July 2026, is a second and independent request for the same thing, also still open.

Two community contributors have already tried to implement it upstream: PR #8606 ("Add BYOK custom AI provider support for Ask AI") and PR #8986 ("Bring Your Own Key (BYOK) and local/custom model support"). Both were closed by their authors, without a maintainer decision.

As of upstream 4d867e222b the upstream tree contains no BYOK implementation at all, the feature is not part of any official release, and it is not advertised on the official website.

This fork exists to make it real. The implementation below was written from scratch, is tested end to end, and is offered to everyone who needs it.

The agent, running on your machine

The same loop, a different transport

Upstream runs the agent server-side, which is exactly why it needs your key on their servers. The fork re-implements the loop locally in ByokOrchestrator.js: it composes the system prompt once per chat and reuses it byte-identically, so provider prompt caching keeps working across a long build session, sends the request to your endpoint, parses the tool calls, executes them through the same tool registry the hosted agent uses, feeds the results back, and repeats until the model stops.

The chat interface, the message types and the tool implementations are reused rather than forked, so the two agents behave the same way. Only the transport changes.

A project snapshot rides its own synthetic trailing user message instead of being folded into the last one, which keeps the transcript strictly append-only and therefore cache-friendly.

Any endpoint, any model, per chat

ByokModelRouter.js resolves the endpoint, the model and the reasoning effort for each turn. Providers are declared once in Preferences — endpoint URL, model list, per-model temperature, max tokens and context window — and each chat can override the provider, the model and the effort from the dropdowns in the chat header.

Two routing profiles, a "default strong" and a "default fast" pair, are stored per provider and migrated when the settings shape changes.

ByokCapabilities.js probes what an endpoint actually supports — tools, vision, reasoning effort — instead of assuming, and ByokBenchmark.js runs a built-in four-task benchmark against a provider, so you can compare models before committing to one.

The key is encrypted at rest

API keys are never stored in plain text. The renderer hands them to the Electron main process in ByokSafeStorage.js, which encrypts them with the operating system key store — DPAPI on Windows, Keychain on macOS, libsecret on Linux — and hands back only ciphertext.

ByokKeyStorage.js keeps one encrypted slot per provider, so switching providers never clobbers a key, and removing a provider does not wipe the shared legacy slot.

The agent writes real events

EventScript, parsed and written for real

ByokEventScriptParser.js implements the full EventScript grammar — conditions, actions, if and else, while, repeat, for-each, groups, local variables, await, and string-aware top-level splitting — and ByokLocalEventWriter.js turns the parsed batch into real gd.EventsList objects.

The write is all-or-nothing: the whole batch is validated against a real event list before anything is modified, so a rejected batch leaves the project untouched and returns a positioned, model-fixable error plus a targeted retry hint.

Upstream's newer JavaScript code events (js """…""") are supported, and a set of canonical examples is shipped in Byok/docs/eventscript-examples.json and round-tripped through the real writer by the specs.

Seventy-five tools, twenty-eight of them inline

ByokToolSchema.js exposes 75 dispatchable tools, of which 28 are advertised inline on every turn. The rest are found through the search_tools meta-tool, which keeps the billed tool list small without hiding capability.

ByokExtraTools.js intercepts the tools that only make sense against GDevelop's backend and implements them locally instead. The tool surface covers scenes, objects, instances, variables, behaviors, effects, sprites, extensions, external events and external layouts, resources, the asset store, the debugger, and the fork's own asset and build tools.

Because upstream shipped its own extension tools with the same names but a different argument shape, the fork's variants live in a separate _BYOK namespace — create_extension_BYOK and friends — so a name can never reach the wrong implementation.

It can see your game

Screenshots and the live debugger

ByokPreviewSession.js captures the open preview window as a base64 PNG and replays it to the provider as an image part, so the agent can check what it just changed instead of guessing.

Images are stored in the BYOK image store and replayed monotonically, so an image never reappears earlier in the transcript, which would break provider-side caching.

ByokDebuggerTools.js talks to the preview session's targeted debugger channel: read_runtime_details to inspect variables, scenes and instances as the game runs, control_runtime to pause, resume and step, and profile_runtime to wait for pushed profiler output. The dumps are capped with an honest truncation report rather than silently truncated, and the tools honour the scene name and the variable paths they advertise.

Long conversations hold up

Chat history that survives a restart

ByokChatPersistence.js and ByokChatStore.js save each BYOK chat as a Markdown transcript with image sidecars, through Electron IPC files or IndexedDB depending on the platform.

Writes are atomic — a unique temp file and a rename, with cleanup on failure — a quarantine path keeps a corrupt chat from taking the store down, and a 200 MB quota bounds the folder. A versioned index.json means the steady-state save path and the rail's actions read zero chat content, only the metadata, and a reconcile pass adopts legacy or unseen files and drops stale entries.

Compaction, loop guards and a watchdog

ByokCompactor.js compacts the transcript when it approaches the model's context limit, preserving a designated block and dropping in a documented order, with a round-based fallback boundary so a single mega-turn build chat — one user message, fifty-plus tool rounds — can still be compacted.

ByokLoopGuards.js detects an alternating cycle and rolls back an unexecuted batch instead of letting the agent repeat itself, and the stall watchdog turns a silent hang into a visible notice row in the chat.

The error codes are distinct — byok-context-full, byok-repeated-tool-call-loop, byok-too-many-tool-rounds, byok-empty-answer — and they are mapped to the right recovery text in AiRequestErrorRow.js.

An MCP endpoint for the agents you already use

A loopback server inside the editor

electron-app/app/ByokMcpServer.js runs a loopback HTTP endpoint inside the Electron main process: a bearer token, an ephemeral port, a discovery file in the user-data folder, focused-window routing, second-instance refusal and a 150-second forward timeout.

The renderer side lives in newIDE/app/src/AiGeneration/Byok/Mcp/ and holds the protocol core pinned to MCP revision 2026-07-28, the tool mapping and the read-only or read-write access gate, and a serialized tool host with an activity ring.

newIDE/app/scripts/gdevelop-mcp-stdio.js is the zero-dependency stdio adapter, so a zero-config MCP client can find the endpoint on its own.

Skills are exposed as MCP prompts, notes and docs as gdevelop:// resources, and a project mutation lock serializes the chat's tool batches against MCP calls, so the two cannot edit the project at the same time.

The documentation, on your disk

Retrieval over the whole wiki

newIDE/app/src/AiGeneration/Byok/Rag/ builds a local corpus — the whole gdevelop5 wiki, minified by the committed generator, 601 of 601 pages and 2.2 MB, plus the engine reference — into about 4,000 chunks, 4,024 in the shipped bundle, held in a deterministic in-process index with base64 vectors, and searches it hybrid-wise, lexical and semantic together, through the search_knowledge tool.

The embedder is lazy-loaded from @huggingface/transformers, so nothing is downloaded until you opt in. The ranking is source-weighted, so curated tiers outrank raw wiki prose, and the corpus is checked by a 30-query evaluation set. A prebuilt index can be downloaded and verified by sha256, and Qdrant is available as an optional backend.

Game code on disk

Byok/GameCode/ lets the agent write ordinary JavaScript files into <project>/<GameName>Code/.

The rules are pure and pinned by specs: the files may never leave that folder, they load in a defined order, they publish into a folder-derived namespace such as GameCode.character.spawn, and because the exporter copies resources flat, the hot reload computes the exact exported name instead of guessing it. The agent can also read, list and update those files through tools.

Prompt, skills and attachments

ByokPrompts.js composes the system prompt — currently version byok-v18 — from a retrieval map, a machine-checked task catalog, the EventScript syntax block and the knowledge sections. Byok/Knowledge/ holds the generated sections and Byok/Skills/ the built-in skills, and user-written skills are read from <userData>/byok-skills by electron-app/app/ByokUserSkills.js.

The prompt budget is measured by a spec on every change — currently about 12.7k tokens for byok-v18, roughly 6.6k of prompt plus 6.1k of tool schemas, against a 15k hard cap — and the specs fail if a section grows past its share.

ByokAttachments.js adds the "+" button to the chat: text files are sniffed by extension and by a NUL-byte check, capped at 100 KB and injected as a fenced block; images go through the BYOK image store and are replayed as image_url parts. Chips show what is attached, the menu is gated by what the provider supports, and the whole path is compaction-aware.

What the fork adds on top

Tagged assets, with a virtual tree

newIDE/app/src/Fork/AssetPipeline/ adds tags to the project resources. They ride the existing resource metadata, so there is no second source of truth, and they come with a many-to-many virtual tree and an "Untagged" bucket, an Assets view hosted in the resources panel, a tag editor in the properties panel, auto-registration of files dropped into the project folder, name-based aliases with Monaco completions in the code editor, and hot reload — a changed asset refreshes both the editor and the running preview.

The agent works with the same model, through list_assets and set_asset_tags.

Smaller builds, and the originals left alone

newIDE/app/src/Fork/AssetBuild/ plans an optimization pass — extension-driven, per kind, in place for the same format, with explicit reasoned skips — and electron-app/app/ForkAssetOptimizer.js applies it with sharp and ffmpeg-static, to the export copy only, never to the project's originals.

The applier writes to a temp file and renames, so a failure leaves the file exactly as it was exported, and a before-and-after report shows what was saved. The agent can read that report and change the settings through report_asset_optimization and set_asset_optimization_settings, without ever touching the project's serialized state.

Guardrails for the event sheet

newIDE/app/src/Fork/Guardrails/ is a pure rule engine with four rules — stable ids, ancestor-stack recursion, disabled-subtree silencing, never mutating — that flags common event-sheet mistakes, for example an event that fires once inside a loop whose guard is re-checked every iteration.

The badges render inline in the event sheet, the rules can be muted individually or globally, and the filters are applied at render time, so toggling a rule never rebuilds the tree. The agent can run the same checks over a scene through the read-only scan_scene_events tool.

Sprite sheets, external events, and a real asset store

newIDE/app/src/Fork/SpriteSheet/ plans an exact-tiling slice, rows times columns with margin slack, and refuses before any write when the grid does not divide evenly. The frames land in the project's assets folder through the same import path the agent uses, and a failure rolls the registrations back. electron-app/app/ForkSpriteSheet.js does the confined slicing with sharp, the sprite editor gains an "Import sprite sheet" button, and the import dialog shows a live canvas preview of the slices. The agent can trigger it too, through the approval-gated import_sprite_sheet tool.

When the agent writes to an external layout or an external events sheet, the open editor for that item now refreshes: the notifications fan out through the main frame to the external editor containers, so the change is visible immediately instead of on the next manual reload.

ByokCatalogTools.js gives the agent get_game_starter_summary, the real public examples catalog instead of the model's memory, plus search_object_asset_store and search_resource_store over the auth-free public catalogs with a self-contained scorer, and a real install path: "add an enemy" fetches the asset, resolves its required extensions and registers it in the project.

Building the app

One command, or one double click

Node.js 20 or newer with npm is the only requirement; CI builds on Node 20. A C++ toolchain is not needed, because the prebuilt libGD WASM is downloaded rather than compiled.

Double-click Build GDevelop App.cmd at the root of the repository, or run node newIDE/scripts/build-desktop-app.js. The installer and a portable zip are left in newIDE/electron-app/dist.

The useful flags are --dev for a development build, --web for the web app only with no desktop packaging, --skip-app-build to package the IDE that is already built, --skip-install never to run npm install, --portable to build without code signing, --dry-run to print the commands without running them, and --open-folder. The script gives its Node processes --max-old-space-size=12288, because the production build of the IDE does not fit in Node's default heap.

The checks

From newIDE/app: npm test -- --watchAll=false for the Jest suite, npm run lint for ESLint with zero warnings allowed, npm run flow for the Flow type check, and npm run check-format for Prettier.

From newIDE/electron-app: npm run check-format, because the Electron main process has no test runner of its own.

Where it lives

The repository

The fork is published at github.com/annoyinggoods/GDevelop. Clone it, read the README and build it with the command above; upstream GDevelop stays at github.com/4ian/GDevelop, and the merges flow in that direction.

The Core library, the native and HTML5 game engines, the IDE and all the extensions are under the MIT licence, the same as upstream.

If something in the fork breaks, the bug report form is the way to say so, and the feature request form is the way to ask for what is missing.