Repository navigation
Service Asset Worker
Asset Worker is Atlas' containerized glTF post-processing service for generated 3D assets. It takes a raw GLB as an upload or a MinIO object reference. It applies the shared Atlas normalization contract, runs glTF-Transform optimization, and writes the GLB to a content-addressed location.
This service exists so image-to-3D providers, Blender and external pipelines, and future creative routes do not duplicate mesh cleanup logic. It is disabled by default until a workflow explicitly needs a common post-processing API.
| Surface | URL | Notes |
|---|---|---|
| Direct API | http://localhost:${ASSET_WORKER_PORT} |
Host-side FastAPI service when ASSET_WORKER_SOURCE=container. |
| Kong alias | http://asset-worker.localhost:${KONG_HTTP_PORT} |
Requires ./start.sh --setup-hosts; generated only when the service is enabled. |
| Internal API | http://asset-worker:8095 |
Used by sibling containers through ASSET_WORKER_ENDPOINT. |
| Health | GET /health |
Returns 200 only when the configured glTF-Transform executable is available; otherwise returns 503. |
| Metrics | GET /metrics |
Prometheus request counters and duration histograms; intentionally unauthenticated for in-network scraping. |
Every route except GET /health and GET /metrics requires Authorization: Bearer ${ASSET_WORKER_API_TOKEN}. Atlas generates the token on first startup; requests fail closed with 503 if authentication is not configured.
| Variable | Default | Purpose |
|---|---|---|
ASSET_WORKER_SOURCE |
disabled |
Enables the containerized worker when set to container. |
ASSET_WORKER_IMAGE |
python:3.12.9-slim |
Base image for the local build. |
ASSET_WORKER_GLTF_TRANSFORM_VERSION |
4.5.1 |
Expected pinned @gltf-transform/cli lock version. An override is a validation guard and must match both package.json and package-lock.json; update those files together when refreshing the dependency. |
ASSET_WORKER_MAX_UPLOAD_MB |
200 |
Maximum uploaded or MinIO-referenced GLB size. An upload whose declared Content-Length exceeds the limit plus 1 MiB of multipart framing gets 413 before the body is read. Other oversized inputs get 413 before transformation. |
ASSET_WORKER_TIMEOUT_SECONDS |
300 |
Per-command timeout for inspect, validate, and optimize. A timeout returns 504. |
ASSET_WORKER_CONCURRENCY |
1 |
Maximum concurrent mutation requests. A saturated worker rejects new work with 429 before acquiring its input. |
ASSET_WORKER_PORT |
computed | Host port assigned by Atlas' topology allocator. |
ASSET_WORKER_API_TOKEN |
generated | Bearer token required by upload, reference-processing, and artifact-download routes. |
ASSET_WORKER_ALLOWED_INPUT_BUCKETS |
(blank) | Optional comma- or space-separated MinIO bucket allowlist. Blank follows MINIO_BUCKET_ASSET_INPUTS. |
ASSET_WORKER_ARTIFACT_DIR |
/data/artifacts |
Local cache path for optimized GLBs and direct downloads. |
ASSET_WORKER_MINIO_ENABLED |
true |
Writes optimized GLBs to MinIO when enabled. |
ASSET_WORKER_MINIO_BUCKET |
asset-worker |
Output bucket for content-addressed artifacts. |
ASSET_WORKER_MINIO_ENDPOINT |
auto-managed | Internal MinIO S3 API endpoint. |
ASSET_WORKER_MINIO_ACCESS_KEY / ASSET_WORKER_MINIO_SECRET_KEY
|
empty | Optional credential override; compose otherwise uses the generated MINIO_ASSET_WORKER_* scoped account. |
Enable from the CLI with:
./start.sh --asset-worker-source containerThe default ASSET_WORKER_SOURCE=disabled keeps the worker out of normal starts until a creative or 3D workflow needs it.
Inputs (uploaded or MinIO-referenced) must be self-contained binary glTF 2.0 files. These inputs are rejected with 400:
- a
.gltfJSON file, whatever its name; - a GLB whose JSON chunk does not parse;
- a
buffers[].uriorimages[].urithat is not adata:URI.
These checks run before any converter. A converter would resolve such a URI against the container filesystem or network and embed what it reads. Asset Baker applies the same rules.
Malformed geometry arrays or object entries reach glTF-Transform's checks and return 422 when those checks reject them.
POST /gltf/postprocess accepts multipart/form-data:
curl -H "Authorization: Bearer ${ASSET_WORKER_API_TOKEN}" \
-F file=@mesh.glb \
"http://localhost:${ASSET_WORKER_PORT}/gltf/postprocess"| Field | Required | Notes |
|---|---|---|
file |
yes | Raw .glb file. |
target_height_m |
no | Target height after normalization when normalize_axis=height. |
target_width_m |
no | Target max horizontal width after normalization when normalize_axis=width. |
normalize_axis |
no |
height or width; default height. |
up_axis |
no | Orientation policy. keep (default) trusts +Y-up and only scales, centers and grounds. auto searches small pitch/roll tilts for the minimum bounding-box volume; it never rotates a model already within a few degrees of Y-up. x/y/z rotates that axis to +Y (a proper rotation, never a mirror). Only POSITION data changes; normals, tangents and node transforms are not rotated or applied. |
simplify_ratio |
no | glTF-Transform simplification ratio, greater than 0 and up to 1. Without it (and without collider_decimation), no simplification runs. |
draco |
no | Enables Draco mesh compression. |
meshopt |
no | Meshopt mesh compression. Default true; Draco takes precedence when draco=true. Pass meshopt=false for an uncompressed mesh, for example to re-import into Blender. |
ktx2 |
no | Requests KTX2 texture compression; otherwise WebP is used. KTX2 needs the KTX-Software ktx binary, which the stock image does not include, so the request is rejected with 422 there. |
collider_decimation |
no | Ratio for collider decimation, used as the simplification ratio when simplify_ratio is absent (same range). |
POST /gltf/postprocess/ref accepts JSON:
{
"input": {"bucket": "raw-assets", "key": "incoming/mesh.glb"},
"params": {"target_height_m": 1.8, "draco": true}
}The request bucket must be listed in ASSET_WORKER_ALLOWED_INPUT_BUCKETS; other buckets return 403 before MinIO is contacted.
Populate the default raw-assets bucket with the generated
MINIO_ASSET_INGEST_ACCESS_KEY and MINIO_ASSET_INGEST_SECRET_KEY; that
identity can write inputs without receiving MinIO root or processor-output access.
Both endpoints return a normalized artifact envelope:
{
"status": "succeeded",
"sha256": "<optimized-glb-sha256>",
"artifact": {
"storage": "minio",
"bucket": "asset-worker",
"key": "gltf/<sha256>.glb",
"uri": "s3://asset-worker/gltf/<sha256>.glb",
"content_type": "model/gltf-binary"
},
"download_url": null,
"normalization": {
"method": "keep",
"up_axis": "keep",
"base_y": 0,
"normalize_axis": "height",
"target_height_m": 1.8
},
"optimization": {
"simplify_ratio": 0.5,
"draco": true,
"meshopt": true,
"ktx2": false,
"collider_decimation": 0.25
}
}When ASSET_WORKER_MINIO_ENABLED=false, the worker stores the optimized GLB under ASSET_WORKER_ARTIFACT_DIR/gltf/<sha256>.glb and returns download_url=/gltf/artifacts/<sha256>.glb.
This service performs mechanical glTF conditioning: scale-to-target, center-XZ, ground-at-y=0, and mesh/texture optimization. Orientation policy is the consumer's. glTF is +Y-up by spec, so the default (up_axis=keep) trusts the incoming orientation. Reorientation (auto or an explicit axis) is opt-in per request. Product-specific asset rules (which assets to reorient, semantic up-ness, placement conventions) belong in the consuming pipeline, not here.
The worker performs three operations in order. Uploads are copied in chunks to bounded temporary files. The blocking pipeline runs in a worker thread, so health and other API requests stay responsive. A process-wide semaphore admits mutation requests before request-body parsing or object-store fetch; requests beyond ASSET_WORKER_CONCURRENCY receive 429 without consuming transformation, upload-spooling, or MinIO-fetch capacity.
- Normalize geometry from the float32 GLB
POSITIONaccessors. Apply base-at-y=0, center X/Z on the origin, and scale to the target height or width. Reorientation is opt-in throughup_axis(§4.1). - Run
gltf-transform inspect,gltf-transform validate, andgltf-transform optimizewith the requested simplification and compression settings. - Hash the optimized GLB with SHA-256 and write it to MinIO or the local artifact cache under
gltf/<sha256>.glb.
The service is intentionally separate from the media gateway. Image-to-3D provider adapters should send raw provider outputs to this worker rather than embed mesh normalization.
Support tier: experimental — Capability contract declared; no cited cold-start, workflow, or upgrade qualification run yet (evidence at v0.1.0).
| Capability | Status | Verification | Notes |
|---|---|---|---|
| Mechanical glTF conditioning | supported | tested | Atlas normalizes scale and grounding and validates GLB input. It applies opt-in glTF-Transform simplification, Meshopt compression by default (opt-in Draco takes precedence), and WebP texture compression. KTX2 needs KTX-Software, which the image does not ship. |
| Bounded authenticated post-processing API | supported | tested | Upload, MinIO-reference, and artifact routes require the generated bearer token and enforce admission, upload-size, and subprocess-timeout bounds; health and metrics remain public. |
| Content-addressed optimized artifacts | supported | tested | Optimized GLBs use SHA-256 keys in the scoped MinIO bucket by default, with an explicitly selected local-artifact fallback. |
| Semantic orientation correction | partial | tested | The default trusts glTF Y-up orientation; callers may request explicit-axis or bounded auto reorientation, but product-specific notions of upright remain consumer policy. |
-
400 Input must be a GLB file: use a.glbfilename and binary GLB payload. -
gltf-transform validatefailure: inspect the raw provider output; invalid GLB input is rejected before storage. -
401 Invalid Asset Worker bearer token: passAuthorization: Bearer ${ASSET_WORKER_API_TOKEN}. -
403 Input bucket is not allowed: add the intended bucket toASSET_WORKER_ALLOWED_INPUT_BUCKETS; do not broaden the list to unrelated or private buckets. - Dependency check fails with "Asset Worker requires MinIO": the container waits on
minioandminio-init, and thegen-ai-creativetrack leaves MinIO off. Add--minio-source container(for example./start.sh --track gen-ai-creative --asset-worker-source container --minio-source container), declareMINIO_SOURCE: containerin a consumer manifest, or disable Asset Worker. - MinIO upload failure: confirm
MINIO_SOURCE=container,ASSET_WORKER_MINIO_BUCKET, and the generatedMINIO_ASSET_WORKER_*credentials. - Kong alias missing: confirm
ASSET_WORKER_SOURCE=container, run./start.sh --setup-hosts, and regenerate routes through the normal startup flow.
| Service | Category |
|---|---|
| minio | data |
| Service | Category |
|---|---|
| kong | infra |
| prometheus | infra |

Open the full-size diagram for a full-screen view.
- Backend media operations should call Asset Worker after hosted image-to-3D providers return raw GLB outputs.
- Blender and external pipelines should use the API for the same upright/normalize/optimize contract instead of carrying local duplicate scripts.
No high-confidence opportunities identified.
- A request can set both
dracoandmeshopt; §4.1 gives the precedence. The responseoptimizationblock records both requested values, not only the applied one (§4.3).
Atlas documentation.
- 1. Overview
- 2. Quick Start
- 3. Core Concepts
- 4. Tracks
-
5. Services
- 5.1. Service Catalog
-
5.2. Service Guides
- 5.2.1. airflow
- 5.2.2. asset-baker
- 5.2.3. asset-worker
- 5.2.4. backend
- 5.2.5. backup
- 5.2.6. blender-mcp
- 5.2.7. celery
- 5.2.8. chatterbox
- 5.2.9. cloud-providers
- 5.2.10. cloudflared
- 5.2.11. comfyui
- 5.2.12. crawl4ai
- 5.2.13. doc-processor
- 5.2.14. docling
- 5.2.15. docling-lightrag-adapter
- 5.2.16. fal
- 5.2.17. globals
- 5.2.18. grafana
- 5.2.19. hermes
- 5.2.20. iceberg-rest
- 5.2.21. jenkins
- 5.2.22. jupyterhub
- 5.2.23. kong
- 5.2.24. label-studio
- 5.2.25. langfuse
- 5.2.26. lightrag
- 5.2.27. litellm
- 5.2.28. llm-graph-builder
- 5.2.29. local-deep-researcher
- 5.2.30. loki
- 5.2.31. mcp-servers
- 5.2.32. minio
- 5.2.33. mlflow
- 5.2.34. multi2vec-clip
- 5.2.35. n8n
- 5.2.36. neo4j
- 5.2.37. ollama
- 5.2.38. open-webui
- 5.2.39. openclaw
- 5.2.40. otel-collector
- 5.2.41. parakeet
- 5.2.42. prometheus
- 5.2.43. ray
- 5.2.44. redis
- 5.2.45. redpanda
- 5.2.46. searxng
- 5.2.47. spark
- 5.2.48. speaches
- 5.2.49. stt-provider
- 5.2.50. supabase
- 5.2.51. supavisor
- 5.2.52. tei-reranker
- 5.2.53. tempo
- 5.2.54. tika
- 5.2.55. trino
- 5.2.56. trueforge
- 5.2.57. tts-provider
- 5.2.58. verba
- 5.2.59. vllm-metal
- 5.2.60. weaviate
- 5.2.61. zeppelin
- 5.3. Provider And Extension Guides
- 6. Configuration
- 7. Operations
- 8. Architecture
- 9. Development
- 10. Reference