# Node-Gen generate a Node subclass from a description, validate in isolation, run it. ```{raw} html 📄 Docs only ``` **Tags:** `ai` `llm` `codegen` The LLM/AI epic capstone. A natural-language description ("a sprite that spins") is turned into a SimVX scene module (a ``.py`` defining one ``Node`` subclass) by :class:`~simvx.ai.NodeGenerator`, validated, written to disk, then loaded with the canonical :func:`~simvx.core.scene_io.load_scene` and run live in a window. Security is first-class (design decision D5: generating a node executes model output, which is code-execution). The security model has two guarantees: - OFF BY DEFAULT: without ``--allow-exec`` the generated source is only static-validated (``ast`` parse, no execution) and never run. You see and save the code, but nothing from the model is executed. - OPT-IN, VALIDATED IN ISOLATION: ``--allow-exec`` is the explicit opt-in to running model-generated code. Even then the candidate is first smoke-tested in a SUBPROCESS (never imported into this host process); only a "verified" result is loaded into this process and run live. ## How to run OFFLINE (default, no LLM, no network, no setup): a scripted fake client returns a canned ``Spinner`` module. Without ``--allow-exec`` it is static-validated and written to disk but NOT executed: uv run python examples/features/ai/nodegen.py Add ``--allow-exec`` to opt in: validate the candidate in an isolated subprocess, then load + run it live in a window (still offline; uses the canned module): uv run python examples/features/ai/nodegen.py --allow-exec LIVE: generate against any OpenAI-compatible endpoint with ``--live``, configured via the same env vars `OpenAICompatibleClient.from_env()` reads: SIMVX_LLM_BASE_URL required, e.g. http://host:8000/v1 SIMVX_LLM_MODEL required, the model name the endpoint serves SIMVX_LLM_API_KEY optional, only if your endpoint needs a key SIMVX_LLM_BASE_URL=http://host:8000/v1 SIMVX_LLM_MODEL=your-model uv run python examples/features/ai/nodegen.py --allow-exec --live --describe "a label that pulses its scale" Live runs record responses to a local cache (CACHE_DIR) so a re-run is deterministic and free. ``--describe`` sets the natural-language prompt. Controls: Esc quits. ## Source ```{literalinclude} ../../examples/features/ai/nodegen.py :language: python :linenos: ```