Cada capacidad es un endpoint antes de ser un botón

Un modelador CAD que tus programas pueden manejar igual que tus manos.

En Lola3d no hay ninguna operación que exista solo en la interfaz. La barra de herramientas, la API REST, las herramientas MCP y el asistente integrado llaman a las mismas 228 acciones, validadas por los mismos esquemas JSON y confirmadas mediante las mismas revisiones y pasos de deshacer.

Un catálogo, cuatro clientes

La misma acción, la pida quien la pida.

GET /api/studio/actions es el esquema de referencia en tiempo de ejecución — no un documento que se desvía del código, sino el catálogo sobre el que está construida la propia aplicación. Todo lo que contiene se puede llamar con un token de sesión o un token de API.

Las modificaciones llevan expected_revision. Una obsoleta se rechaza con un 409 en lugar de fusionarse por suerte, y un error del núcleo deja el documento idéntico byte a byte.

REST
# Everything the modeler can do, with its schema
curl -H "Authorization: Bearer $TOKEN" \
     https://lola3d.app/api/studio/actions

# One edit, on the revision you hold
curl -X POST https://lola3d.app/api/studio/actions/push_pull \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model_id":"…","expected_revision":12,
       "args":{"target":"body1","face_id":"f7","distance":40}}'

# A hundred commands as one revision and one undo step
curl -X POST https://lola3d.app/api/studio/actions/batch …
Diseño generativo

Python, dentro del núcleo.

Un lote de comandos no puede leer el modelo entre sus propios comandos. Esa única limitación es lo que separa automatizar un clic de generar un diseño — y es lo que elimina la consola de Python.

Lo que te da cad

  • cad.create_box(width=100, …) — cualquier acción del catálogo, por su nombre, validada por su propio esquema
  • cad.actions() / cad.help(name) — el catálogo, desde dentro del script
  • cad.document, cad.features, cad.find(name) — el modelo tal como está
  • cad.objects(), cad.bounds() — los cuerpos visibles, su volumen, su área y sus dimensiones
  • params — las variables que pasaste; print(…) capturado; result devuelto

Lo que confirma

  • Un script es una edición y un paso de deshacer.
  • Un script que lanza una excepción no confirma nada — y dice qué línea falló.
  • Un script que no cambia nada no es una revisión: medir es gratis.
  • dry_run lo ejecuta todo y no conserva nada.

Lo que vale el aislamiento — con honestidad

El espacio de nombres restringido — sin open, sin eval, sin exec, sin atributos dunder y solo con los módulos numéricos y estructurales — es una barandilla, no una frontera de seguridad. CPython nunca ha ofrecido un aislamiento real dentro del proceso y no vamos a fingir lo contrario.

Lo que de verdad protege: el script se ejecuta en un proceso worker de geometría con sus propios límites de memoria y CPU, bajo un plazo que el propio worker se impone (un bucle infinito se detiene solo en lugar de costar un worker), y detrás de un permisoadmin por defecto, porque ejecutar un script es ejecutar código en el servidor de geometría. Un ajuste lo amplía a todos los editores; otro elimina la acción del catálogo por completo.

A lattice whose size follows its own arithmetic
n = params["cells"]
pitch = params["pitch"]
strut = params["strut"]

for i in range(n + 1):
    for j in range(n + 1):
        cad.create_box(width=strut, depth=strut,
                       height=n * pitch,
                       position=[i * pitch, j * pitch, 0])

print("struts:", len(cad.features))
result = {"struts": len(cad.features),
          "extent_mm": n * pitch}
Read the model back, then decide
# Nothing applied — so this costs no revision at all.
total = 0.0
for o in cad.objects():
    print(f"{o['name']:<24} {o['volume']:>14,.1f} mm3")
    total += o["volume"]

box = cad.bounds()
size = [round(box["max"][i] - box["min"][i], 2) for i in range(3)]
result = {"bodies": len(cad.objects()), "bbox_mm": size}
La consola de Python en el espacio de trabajo, con un script, su salida y las acciones que aplicó.
Inspector → ⋯ → Consola de Python. Tab sangra, Ctrl+Enter ejecuta, Ensayo no conserva nada.
Modelado agéntico

Un agente tiene el mismo modelador que tú — y los mismos frenos.

El endpoint MCP expone el catálogo como herramientas, sujeto a los mismos permisos de lectura y escritura que cualquier otro cliente. Un agente con un token de lectura puede medir, inspeccionar y exportar; uno con un token de escritura puede modelar.

También puede trabajar como lo haría un colega: previsualizar un cambio sin escribir nada, o proponer uno. Una propuesta dibuja su fantasma en tu ventana gráfica con los dos botones que la responden, y una aprobación aplica todos los comandos como una sola edición con un solo grupo en la línea de tiempo sobre lo que creó — o un rechazo la descarta sin dejar nada.

  • Las herramientas de lectura son libres; las de escritura requieren aprobación en la aplicación.
  • Un requisito expresado con palabras se convierte en una anotación comprobada, que se vuelve a comprobar en cada reconstrucción.
  • Las llamadas largas llevan tu señal de cancelación: un cliente que se va libera el worker.
MCP
POST /mcp
X-API-Key: ign_…          # scope: ai

{"jsonrpc": "2.0", "id": 1,
 "method": "tools/call",
 "params": {
   "name": "propose_changes",
   "arguments": {
     "model_id": "…",
     "title": "Lighten the web by 18%",
     "commands": [
       {"action": "shell",
        "args": {"target": "web", "thickness": 2.4}}
     ]
   }}}
Intercambio

Tu geometría sale igual que entró.

FormatoImportarExportarNotas
STEP (.step)B-rep exacto. Los ensamblajes llegan como componentes.
IGES (.iges)Superficies cosidas donde son estancas.
BREP (.brep)La forma exacta propia del núcleo, con nombres y colores.
STL (.stl)Se cose en un sólido si es estanco; si no, se conserva como caras.
OBJ (.obj)Se exporta con su MTL, en un zip.
3MF (.3mf)Conserva los colores.
glTF / GLBPara la web y para motores de render.
Collada (.dae)La vía de entrada y salida de SketchUp, que no tiene un formato .skp abierto.
IFC (.ifc)IFC4; cuerpos como proxies, componentes como ensamblajes.
DXF / SVGEntran como entidades de boceto; salen de un boceto, un corte de sección o un plano.
PDFHojas de planos.
JSONEl propio documento editable, geometría congelada incluida.
G-codeGRBL, LinuxCNC, Fanuc o un posprocesador que describas tú mismo.

Consigue un token y crea algo.

Inicia sesión, crea un token de API en Ajustes y todo el modelador responde a curl. Después escribe el script que te habría costado una tarde de clics.