{"slug": "blender-forbids-python-threads-so-my-ai-add-on-talks-to-itself-through-two-json", "title": "Blender forbids Python threads. So my AI add-on talks to itself through two JSON files", "summary": "A developer built Game Asset Assistant, a Blender 4.2+ add-on that embeds a chat-based AI assistant in the 3D Viewport sidebar, backed by local Ollama models or any OpenAI-compatible API. Because Blender's API forbids Python threads that outlive the script, the add-on runs the model in a separate worker process and communicates through two JSONL files, with a bpy.app.timers callback pumping events on the main thread every 0.1 seconds. The model's Python code blocks can be executed directly in the current scene, with print output and tracebacks fed back into the chat so the model can fix its own errors.", "body_md": "The pivot\n\nI spent the last months building a local multi-agent CLI code generator - planner → coder → tester → executor → reviewer, running on open models via Ollama. It closed the loop: it wrote code, ran it, tested it, and fixed it.\n\nIt worked. And that's exactly the problem: it solved a problem I don't have. Writing code for files on disk is a solved niche - I was competing with every other code-gen tool for a user who already has one.\n\nWhat I actually do all day is 3D. So the project became something else: an AI assistant that lives inside Blender and holds real tools for working with models, not just a text box that emits code.\n\nWhat works right now\n\nThe add-on is called Game Asset Assistant, targets Blender 4.2+, and ships as a proper extension zip.\n\nChat where you work\n\nDocked in the 3D Viewport sidebar (N → AI tab)\n\nAlso opens as a standalone floating window with Ctrl+Alt+A\n\nStreamed responses, message history, stop/clear buttons\n\nIt knows your scene\n\nEvery request carries a compact snapshot injected into the system prompt:\n\nBlender 4.2.0\n\nScene: Scene | fps=24 | units=METRIC | render=CYCLES\n\nObjects: 12\n\nOne click from answer to action\n\nWhen a reply contains a \n\n```\npython block, it appears in a box with two buttons:\n\nRun code - executes it in the current scene on the main thread, captures print() output and tracebacks, and pushes both back into the chat. That closes the loop: the model writes, Blender executes, the model sees the error and fixes it.\nTo Text Editor - saves it as a text datablock for manual review.\nBackends\n\nLocal (Ollama, e.g. qwen2.5-coder:7b) or any OpenAI-compatible API - switchable in preferences, no code changes.\n\nThe part that broke my brain: Blender forbids threads\nHere's the non-obvious bit worth the whole post.\n\nBlender's API docs say it plainly: Python threads that outlive the script cause hard-to-diagnose crashes in Blender's own drawing code. So the obvious approach - \"spawn a thread, call the LLM API, update the UI when it returns\" - is off the table.\n\nThe add-on therefore never blocks and never spawns a thread. Instead:\n\nBlender (main thread)              worker process            network\n┌────────────────────────┐         ┌──────────────┐\n│ operator appends a     │commands │              │\n│ JSON line ─────────────┼────────→│  worker.py   │──HTTP──→ Ollama / API\n│                        │         │              │\n│ bpy.app.timers,        │events   │              │\n│ every 0.1s, reads new  │←────────┤              │\n│ lines ─────────────────┤         └──────────────┘\n└────────────────────────┘\nCommands are just JSON objects appended to commands.jsonl.\nEvents (chunk, done, error) are appended to events.jsonl.\nA bpy.app.timers callback pumps events every 0.1 s - and a timer is not a thread, it's a callback Blender invokes on the main thread between frames. That's the only legal way to do background work.\nSide effect: the whole add-on ships without any third-party dependency, and the protocol already has room for tool-call requests in a later phase.\n\nWhat's not there yet\nBeing honest about the gaps:\n\nNo structured tool-calling - the model emits a code block and we exec() it\nNo confirmation for destructive operations (the prompt asks the model to warn; that's a request, not a guarantee)\nNo undo grouping - one Ctrl+Z won't roll back a whole script\nUV, rigging and texturing exist only as chat advice, not as one-click tools\nScene snapshot is blind to UV islands, texel density, weights and armature pose\nRoadmap\nPhase   What    Why first\n0   Richer snapshot, undo-push, destructive-op confirmation Cheap, unlocks everything after\n1   Tool-calling over the JSONL channel, executed on the main thread with a registry + JSON schemas The reliability jump: from \"80 lines of text that may fail\" to named calls\n2   Texturing: PBR material presets, texture assignment, packing, bake helpers  Stable API, high daily value\n3   UV: quick unwrap/pack/texel-density, seam-by-angle, and a UV diagnostics report (overlaps, density) Most repetitive work; the report lets the model read the result and propose fixes\n4   Auto-rig: metarig → Rigify, auto-weights, weight validation, export checks    Hardest - errors are silent, so diagnostics matter more than generation\n5   One-click pipelines: GBC Prep, Char Prep, PBR Bake, Game Export Combines 2–4 into buttons\n6   Teach the model: tool catalog in the prompt, domain recipes, few-shot examples  Ongoing, parallel\nIntegration with other Blender add-ons (delegating to UV packers, for example) is on the list - but the final roadmap is still open. I'd rather ship phases 0–3 and let real usage decide what phase 4 looks like.\n\nThe plan from here\nPost progress as it lands. If you're working on AI × 3D pipelines, or you've wrapped a DCC tool for an LLM - I'd love to compare notes.\n\nRepo link in the comments.\n\n#blender #ai #python #gamedev #3d #showdev\n```\n\n", "url": "https://wpnews.pro/news/blender-forbids-python-threads-so-my-ai-add-on-talks-to-itself-through-two-json", "canonical_source": "https://dev.to/sicksect/blender-forbids-python-threads-so-my-ai-add-on-talks-to-itself-through-two-json-files-58hb", "published_at": "2026-10-19 09:36:01+00:00", "updated_at": "2026-10-19 09:44:51.758198+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "large-language-models"], "entities": ["Blender", "Game Asset Assistant", "Ollama", "qwen2.5-coder:7b"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/blender-forbids-python-threads-so-my-ai-add-on-talks-to-itself-through-two-json", "markdown": "https://wpnews.pro/news/blender-forbids-python-threads-so-my-ai-add-on-talks-to-itself-through-two-json.md", "text": "https://wpnews.pro/news/blender-forbids-python-threads-so-my-ai-add-on-talks-to-itself-through-two-json.txt", "jsonld": "https://wpnews.pro/news/blender-forbids-python-threads-so-my-ai-add-on-talks-to-itself-through-two-json.jsonld"}}