Sandflow-ai/sand3d · 07 Nov 2026 · Feature

An API Whose Real Unit of Measure Is the Token

sand3d is a Python 3D-modeling vocabulary built on Blender's engine, designed so a language model can write a whole articulated object in a few hundred tokens — and a human can still read it.

Sandflow-ai/sand3d
★1.4k stars

Every few months, someone rediscovers that large language models can write code, and therefore that large language models can, in principle, write 3D models. The idea is old enough by now to have a literature: papers where LLMs generate FreeCAD scripts and get refined through error feedback, systems like SceneCraft that have models emit Blender Python to assemble scenes, hobbyist evaluations where o3 and Gemini 2.5 Pro grind through OpenSCAD tasks. The pattern is consistent across all of them — simple and moderately complex designs work; highly constrained ones fall apart, and the failure mode is almost always the same: the modeling API itself. It is too big, too coordinate-obsessed, too verbose. The model runs out of attention before the part runs out of features.

Sandflow-ai/sand3d

sand3d, a young Apache-2.0 library from Sandflow, is one of the first projects I have seen that treats this not as a prompt-engineering problem but as an API-design problem. Its pitch is blunt: 3D modeling in Python, built for LLMs. Not “LLM-friendly,” not “works well with agents” — built for them, the way a keyboard is built for fingers.

The token as the design constraint

The README’s central claim is a chart, not a philosophy. The same part, measured part by part, takes a median of 4.0 times sand3d’s token count in raw Blender Python, 2.3 times in CadQuery, 6.0 in FeatureScript, and 2.0 in the Articraft SDK. The project publishes its methodology alongside the numbers, which is more than most “LLM-friendly” tools bother to do. Whether the comparison is perfectly fair is the kind of question you can only answer by rerunning it yourself — the sources here don’t include independent verification — but the direction of the claim is credible, because sand3d’s entire vocabulary is engineered around it.

The second number matters just as much: the whole API fits in a system prompt, at roughly 3,600 tokens. That is the quietly radical part. Blender’s Python API is famously vast — an entire Springer book exists essentially to explain its object hierarchy and documentation sprawl, and its own preface admits the API is “made difficult due to its complex object hierarchy.” A model asked to write bpy code is working from a fraction of that surface, recalled imperfectly. A model given sand3d’s API document is working from the whole thing, every time. For a generation task, that is the difference between an open-book exam and a memory test.

Named, not computed

The deeper design decision, though, is the one the README states in four words: named, not computed. In most programmatic CAD and modeling APIs, you reach geometry by coordinates — vertex indices, bounding-box arithmetic, hand-computed positions. This is where LLMs reliably stumble: arithmetic over floating-point coordinates is exactly the kind of thing a model does confidently and incorrectly. sand3d instead insists that parts, edges, and faces are reached by name. You fillet the edge called “top.” You put a hole on a grid pattern. The model never has to compute where anything is; it has to declare what anything is.

That reframing — from geometry-as-arithmetic to geometry-as-vocabulary — is the same insight that made LLMs good at writing SQL and bad at doing long division. It is also, incidentally, what makes the output legible to humans. A sand3d program reads like a parts list with verbs, which is why the README can show a front-loading washing machine — cabinet, drum, door with glass and handle, detergent drawer, dial, and four declared joints including a door hinge with a 143-degree range — in 38 lines. The program says how a shape is made, part by part, in its own words.

The articulation layer deserves its own paragraph, because it is the part most competitors simply don’t have. Joints are first-class: hinge, continuous, prismatic, with axes and ranges, declared alongside the geometry they move. And the export story follows from that — one call emits GLB with joints in node extras for the web, URDF with links and limits for ROS, PyBullet, MuJoCo, and Isaac, USDA with UsdPhysics for Omniverse pipelines, plus plain OBJ and STL for slicers. An object written in sand3d isn’t just a mesh; it’s a simulation-ready asset by construction. In a landscape where NVIDIA’s SimReady assets exist as a curated category of thing, an API whose output drops directly into that ecosystem is aiming at a real gap.

Underneath, it’s Blender — and that’s the point

It would be easy to dismiss sand3d as glue code over bpy, and to a degree it is: the library is a vocabulary layered on Blender’s engine, and the README is honest that the scene underneath is an ordinary Blender scene, exportable as anything Blender writes. But glue code is not a criticism when the glue is the product. Blender’s geometry kernel is battle-tested and free; what it has never had is a small, name-oriented, token-cheap front end. Recent academic work on procedural modeling in Blender still routes through the modifier stack, Geometry Nodes, and the raw Python API — a four-stage workflow for parametric technical models. sand3d collapses that into a flat surface of verbs: profiles, solids, edits, frames, joints, assemblies, all on one s3d. namespace, with no category verbs. There is no chair() function, deliberately — a chair is a program written in sand3d, which keeps the API from bloating into the thing it replaced.

Two other traits are worth flagging because they’re rare in this space and load-bearing for the LLM use case. Determinism: the same program builds the same mesh, bit for bit, which makes program output a stable ground truth for training and evaluation. And the dependency story is a real rough edge, honestly documented: bpy ships as a wheel for Python 3.11 and 3.13 only, with no 3.12 wheel at all and no Intel Mac support from 5.2 onward. If your stack is pinned elsewhere, that’s friction you’ll feel.

The datasets are the moat

The library alone would be an interesting curio. What makes the project feel like a bet rather than a tool is the Hugging Face collection: five datasets, CC BY 4.0, each converting an existing corpus of 3D objects into sand3d programs. Objaverse’s everyday objects, mechanical parts from public CAD models, articulated objects from Articraft with their joints declared, NVIDIA’s SimReady assets, and mechanical assemblies from AutoMate where each part is a function of its program. The collection page shows real traction for something days old — tens of thousands of downloads on the Objaverse conversion, with the others in the thousands, and an interactive explorer where you can play each object joint by joint.

This is the part that should make the 3D-generation research community sit up. The dominant approaches to text-to-3D have been generative — diffusion-optimized neural fields like DreamFusion and Magic3D, direct generators like Shap-E — which produce meshes that are opaque blobs of geometry: hard to edit, unarticulated, and carrying no semantics. A dataset of objects-as-programs is a different substrate entirely. It’s the raw material for training models that generate editable, parametric, jointed, simulation-ready 3D — the way code datasets made models that generate software instead of screenshots of software. Whether that training bet pays off is an open question, and the sources here don’t show anyone having fine-tuned on these datasets yet. But the dataset is the strategy: sand3d isn’t just an API a model can call, it’s a representation a model can learn.

Where it sits, and what it isn’t

The field context helps locate it. The FreeCAD-plus-LLM experiments showed models doing fine on simple parts and needing multiple error-driven refinements on constrained ones. The OpenSCAD evaluations showed reasoning models getting surprisingly good at programmatic CAD, with commenters already handing models whole OpenSCAD libraries and reporting decent results with “only some hallucination that can be iterated away.” sand3d’s wager is that the hallucination-iteration tax is mostly an API tax, and that a 3,600-token, name-based vocabulary with deterministic output cuts it to near zero. That’s testable, and someone should test it independently — the project’s own token benchmarks are exactly the kind of claim that deserves adversarial replication.

What sand3d is not: a replacement for SolidWorks, a mesh sculptor, or a renderer. It has no category intelligence, no sketch solver, no constraint system in the CAD sense. It’s a constructive vocabulary — profiles, extrusions, cuts, fillets, joints — and objects that don’t decompose into that vocabulary (organic forms, scanned geometry, freeform surfaces) are simply not its territory. The Blender Python API underneath remains available for everything else, which is both the escape hatch and the reminder that this is a layer, not a world.

One small comedy of the naming: search for “sand3d” and you will find, before the library, an entire industry of 3D-printed sand casting molds and a Sketchfab tag full of sandcastle models. The name is going to cost them some SEO for a while.

Outlook

The unresolved tensions are the interesting ones. First, adoption: the project is new, from a small team (the citation lists two authors), and its traction so far is dataset downloads rather than a visible ecosystem of users building things. Second, the training bet: five converted corpora are a start, not a benchmark, and the field’s high-fidelity CAD generation work is moving fast enough that the representation a model trains on may matter as much as the model. Third, the dependency: riding Blender’s bpy gives sand3d a free industrial-grade kernel, but ties its packaging fate to Blender’s Python-version whims — the missing 3.12 wheel is a small preview of that risk.

But the core insight is sound and overdue. For two years the field has asked “how do we make LLMs better at existing 3D APIs?” sand3d asks the inverted question: what does a 3D API look like if the token budget is the spec? The answer — small, named, deterministic, jointed, exportable everywhere from game engines to physics simulators — reads less like a library and more like a proposal for what machine-generated 3D content should be made of. Whether the proposal wins or merely shames the incumbents into shrinking their own APIs, something in the geometry stack just got measured in a new unit.

Sources

  1. How do I procedurally make 3D models with Python (not using Blender)?
  2. Generative AI for CAD Automation: Leveraging Large Language ...
  3. 3D Printed Sand Casting Molds & Cores
  4. The Blender Python API - Springer Nature
  5. AI-Driven Design Tool for Blueprints and 3D Models
  6. Sand3D - a Sandflow Collection
  7. Procedural 3D Modeling in Blender: Combining Geometry Nodes and the ...
  8. LLMs create CAD models for 3D parts
  9. Sand 3D models
  10. 3D Modeling in Blender using Python | by Lovro
  11. Towards High-Fidelity CAD Generation via LLM-Driven ...
  12. 3D Sand Printing

heatdrop uses Google Analytics to see which pages get read — nothing else. Your call. How we handle data.