Character Animation for Agents

Rig and animate any 3D model from a sentence. SkinTokens (ACM TOG 2026) predicts the skeleton and skin weights, the rig becomes a reusable asset on this Space, and UniMate (SIGGRAPH Asia 2026) generates the motion from text, then refines it: in-betweening, joint editing, multi-prompt expansion. One synchronous call on a ZeroGPU slice, or each stage on its own.

REST + OpenAPIMCP serverGradio clientsZeroGPU, billed to the callerglb · gltf · obj · fbx in, animated GLB outReusable assets

Give this to your agent

A one-sentence prompt for Claude, ChatGPT, Cursor or any agent with web access. Replace the placeholder with your task; the guide holds the endpoints, parameters and workflow. A full run costs about a minute of your ZeroGPU quota, a motion alone a few seconds.
Read https://townbox-character-animation-for-agents.hf.space/llms.txt and use this service to <WHAT_TO_RIG_OR_ANIMATE_AND_WHAT_TO_DO_WITH_THE_FILES>. Use my configured Hugging Face token if available.

Connect over MCP

The same operations as the REST API, served over streamable HTTP. Add the server to your MCP client with the config below; the Authorization header is optional and bills GPU seconds to your own Hugging Face quota instead of the anonymous per-IP allowance.
Endpoint
https://townbox-character-animation-for-agents.hf.space/gradio_api/mcp/ · schema /gradio_api/mcp/schema
Tools
animate_mesh (mesh_url / example / rig_job_id / asset, prompt or prompts, rig and motion options) · rig · prepare_asset (rig_job_id / mesh_url / asset_id, labels, facing) · animate · inbetween · edit_joints · expand · list_assets · get_asset · list_examples · get_result · view_rig, view_animation, view_asset (return PNGs) · service_info · guide
Claude Code
claude mcp add --transport http character-animation https://townbox-character-animation-for-agents.hf.space/gradio_api/mcp/ --header "Authorization: Bearer $HF_TOKEN"
{
  "mcpServers": {
    "character-animation": {
      "url": "https://townbox-character-animation-for-agents.hf.space/gradio_api/mcp/",
      "headers": { "Authorization": "Bearer <HF_TOKEN>" }
    }
  }
}

First call: animate_mesh with a model URL (or an example id) and a prompt that starts with “An object”; the result carries the rig, the asset and the motion with every file URL. Its asset id is reusable in animate and expand, its animation job id is the reference for inbetween and edit_joints. Signed in on the Hub, the Space's Agents menu also adds it to your Hugging Face MCP tools.

How the pieces fit

1Rig
SkinTokens / TokenRig predicts a skeleton and per-vertex skin weights for any mesh: glb, gltf, obj or fbx, up to 60 MB. 20-60 s of GPU.
POST /api/rig · MCP rig → r_ job: rigged.glb, rig.json, skin.npz, preview
2Asset
The UniMate repository's rig_preprocess runs here: Blender import, joint labels from one anatomical vocabulary, the facing pair, the canonical T-pose and a canonical GLB. Any rigged file works, not only rigs made here. A preview and review flags show what the motion model is told; labels and facing can be corrected. 5-30 s of CPU.
POST /api/assets · MCP prepare_asset → u_ asset, reusable
3Animate
UniMate generates a 60-frame motion for the asset from a prompt and bakes it into the canonical GLB; keep what you like and regenerate the rest with in-betweening, joint editing and expansion. About 10 s per call.
POST /api/animate, /api/inbetween, /api/edit, /api/expand → a_ job: animation.glb, motion.npy, joints.json, preview

POST /api/animate_mesh (MCP animate_mesh) runs all three in one request and returns a p_ result with the three stages and a flat map of file URLs; rig_job_id or asset in its body skip the stages already done. Results are kept 24 h, assets until the Space restarts.

Examples generated by this Space

6 real outputs of this API, produced on 2026-11-05 on the ZeroGPU slice: 4 by POST /api/animate_mesh (each model rigged by SkinTokens, prepared as an asset, animated by UniMate, in one request), then one /api/expand chain and one /api/edit on those assets. Each picture is an animated GIF of the generated motion, rendered from the animation GLB the API returned (15 fps, camera fixed on the whole path); click it to load the 3D mesh itself (drag to orbit). Under each: the rig preview the API returns (mesh with the predicted skeleton) and the asset preview (what the motion model is told: canonical T-pose, facing pair, labels), or the skeleton motion itself for the expansion and the edit. The seeds reproduce them; the API always generates fresh results. Machine-readable list: /api/examples.

animated preview of the generated motion: Giraffe, textured quadruped, 14.8k vertices, An object walks forward.
“An object walks forward.”
Giraffe, textured quadruped, 14.8k vertices → POST /api/animate_mesh: SkinTokens rig of 47 joints (15.8 s GPU, 10 beams, seed 7, textures kept) · asset prepared in 5.8 s (facing Right Thigh / Left Thigh, 0 flagged) · UniMate motion seed 7, 6.8 s GPU · root travel 0.78 · 34 s in all
rig preview: mesh with the predicted skeleton, front and sideasset preview: canonical T-pose with facing pair and joint labels
animation.glb · joints.json · motion.npy · skeleton.mp4 · contact sheet · rigged.glb · rig.json · rest.glb · jobs p_474f884eebc5 (rig r_2e6699f3f0bc, asset u_10e5b2e20af3, motion a_2f76391d6eda)
animated preview of the generated motion: Cesium Man, humanoid, 3.3k vertices (Khronos sample, rig removed), An object walks forward.
“An object walks forward.”
Cesium Man, humanoid, 3.3k vertices (Khronos sample, rig removed) → POST /api/animate_mesh: SkinTokens rig of 19 joints (5.5 s GPU, 10 beams, seed 7) · asset prepared in 3.1 s (facing Right Thigh / Left Thigh, 0 flagged) · UniMate motion seed 7, 8.2 s GPU · root travel 0.05 · 20 s in all
rig preview: mesh with the predicted skeleton, front and sideasset preview: canonical T-pose with facing pair and joint labels
animation.glb · joints.json · motion.npy · skeleton.mp4 · contact sheet · rigged.glb · rig.json · rest.glb · jobs p_2f231730c8f6 (rig r_7f2aec849775, asset u_953687e8544d, motion a_046e8815e9d9)
animated preview of the generated motion: Fox, low-poly, 1.7k vertices (Khronos sample, rig removed), An object runs forward.
“An object runs forward.”
Fox, low-poly, 1.7k vertices (Khronos sample, rig removed) → POST /api/animate_mesh: SkinTokens rig of 22 joints (6.5 s GPU, 10 beams, seed 7) · asset prepared in 2.7 s (facing Right Thigh / Left Thigh, 0 flagged) · UniMate motion seed 5, 7.5 s GPU · root travel 1.33 · 20 s in all
rig preview: mesh with the predicted skeleton, front and sideasset preview: canonical T-pose with facing pair and joint labels
animation.glb · joints.json · motion.npy · skeleton.mp4 · contact sheet · rigged.glb · rig.json · rest.glb · jobs p_86e991769686 (rig r_50d711b04d7f, asset u_2e9a5e883e0a, motion a_7b7af3060632)
animated preview of the generated motion: Low-poly humanoid, 370 vertices (Khronos sample, rig removed), An object jumps in place.
“An object jumps in place.”
Low-poly humanoid, 370 vertices (Khronos sample, rig removed) → POST /api/animate_mesh: SkinTokens rig of 19 joints (5.5 s GPU, 10 beams, seed 7) · asset prepared in 2.8 s (facing Right Thigh / Left Thigh, 0 flagged) · UniMate motion seed 3, 6.8 s GPU · root travel 0.07 · 25 s in all
rig preview: mesh with the predicted skeleton, front and sideasset preview: canonical T-pose with facing pair and joint labels
animation.glb · joints.json · motion.npy · skeleton.mp4 · contact sheet · rigged.glb · rig.json · rest.glb · jobs p_2f7fbbcc7328 (rig r_b90ee872d15b, asset u_f3fd9ef728c3, motion a_4baf1f28fa50)
animated preview of the generated motion: Giraffe, textured quadruped, 14.8k vertices, An object walks forward. | An object turns around. | An object sits down.
Expansion: “An object walks forward.” → “An object turns around.” → “An object sits down.” (160 frames, 5.3 s)
Giraffe, textured quadruped, 14.8k vertices, the asset of example 01 → POST /api/expand, 3 prompts, overlap 10 · seed 7 · 12.2 s GPU · root travel 1.00 · segments at frames 0, 50, 100
skeleton motion, animated
animated preview of the generated motion: Cesium Man, humanoid, 3.3k vertices (Khronos sample, rig removed), An object waves its arms.
Joint editing: “An object waves its arms.” with the legs of the walk kept
Cesium Man, humanoid, 3.3k vertices (Khronos sample, rig removed), the walk of example 02 as reference → POST /api/edit, keep_joints = Left Foot, Left Shin, Left Thigh, Left Toe, Right Foot, Right Shin, Right Thigh, Right Toe (8 joints) · seed 4 · 5.6 s GPU · 11 joints regenerated
skeleton motion, animated

Bundled example assets

Meshes: the example ids of POST /api/rig and /api/animate_mesh. Each link opens the file in the Hugging Face file viewer (3D preview, history, download from there) rather than downloading it.

giraffe
giraffe.glb · Giraffe, textured quadruped, 14.8k vertices · SkinTokens repository, MIT
fox
fox.glb · Fox, low-poly, 1.7k vertices, original rig removed · Khronos glTF sample (PixelMannen, tomkranis, AsoboStudio, scurest), CC BY 4.0
cesium_man
cesium_man.glb · Cesium Man, humanoid, 3.3k vertices, original rig removed · Khronos glTF sample (Cesium), CC BY 4.0
rigged_figure
rigged_figure.glb · Low-poly humanoid, 370 vertices, original rig removed · Khronos glTF sample (Cesium), CC BY 4.0

Skeletons: prepared assets, the asset ids of POST /api/animate and /api/expand; they need no rigging.

unitree_go2
unitree_go2.glb · Unitree Go2 quadruped robot, 18 joints · UniMate repository example, MIT; mesh from Unitree’s public Go2 description
eagle
Eagle.glb · Eagle, winged biped with tail and toes, 51 joints · UniMate repository example, MIT
shark
shark.glb · Shark, serpentine spine with fins, 16 joints · UniMate repository example, MIT

For programs: /api/examples lists the same inputs with a mesh_url per mesh, and GET /api/assets/{id}/rest.glb serves a skeleton’s canonical GLB. The folders on the Hub: examples/ (also holds the showcase outputs above) and assets/examples/ (with each skeleton’s annotation.json, cond.npy and preview).

Quick start

BASE=https://townbox-character-animation-for-agents.hf.space
# one call: mesh -> rig -> asset -> animated GLB (about a minute; GPU time goes to your ZeroGPU quota)
curl -s -X POST $BASE/api/animate_mesh -H "Authorization: Bearer $HF_TOKEN" -H 'content-type: application/json' \
  -d '{"example": "giraffe", "prompt": "An object walks forward.", "seed": 7}'
# your own model: the file as the body, the prompt as a query parameter
curl -s -X POST "$BASE/api/animate_mesh?filename=robot.glb&prompt=An%20object%20walks%20forward." \
  -H "Authorization: Bearer $HF_TOKEN" -H 'content-type: application/octet-stream' --data-binary @robot.glb
# download the animated, rigged mesh (urls.animation_glb of the result)
curl -s -H "Authorization: Bearer $HF_TOKEN" -o walk.glb "$BASE/api/jobs/<a_job_id>/files/sample0_animation.glb"

# the stages, one call each
curl -s -X POST $BASE/api/rig -H "Authorization: Bearer $HF_TOKEN" -H 'content-type: application/json' -d '{"example": "fox", "seed": 7}'
curl -s -X POST $BASE/api/assets -H "Authorization: Bearer $HF_TOKEN" -H 'content-type: application/json' -d '{"rig_job_id": "<r_job_id>"}'
curl -s -X POST $BASE/api/animate -H "Authorization: Bearer $HF_TOKEN" -H 'content-type: application/json' \
  -d '{"asset": "<u_asset_id>", "prompt": "An object jumps in place.", "num_samples": 2}'
# keep what you like, regenerate the rest (reference = an a_ job), or chain prompts
curl -s -X POST $BASE/api/edit -H "Authorization: Bearer $HF_TOKEN" -H 'content-type: application/json' \
  -d '{"reference_job_id": "<a_job_id>", "keep_joints": "Left Thigh, Right Thigh, Left Shin, Right Shin", "prompt": "An object waves its arms."}'
curl -s -X POST $BASE/api/expand -H "Authorization: Bearer $HF_TOKEN" -H 'content-type: application/json' \
  -d '{"asset": "<u_asset_id>", "prompts": ["An object walks forward.", "An object turns around.", "An object sits down."]}'

Endpoints

POST /api/animate_mesh
The mesh (raw body with ?filename=, multipart file, JSON {example} / {mesh_url}) or {rig_job_id} / {asset}, plus prompt (or prompts) and any rig, asset and motion option. Returns the three stages, every file URL and the follow-up calls.
POST /api/rig
Rig a mesh with SkinTokens. Options num_beams, seed, keep_skeleton, preserve_original, postprocess, influences, sampling parameters.
POST /api/assets
Prepare an asset from {rig_job_id}, a rigged glb/gltf/fbx (body, multipart or mesh_url), a zipped rig_preprocess output, or {asset_id} with corrections (labels, face_right, face_left, body_axis, rest_rotation, annotation).
GET /api/assets, /api/assets/{id}
Bundled and prepared skeletons: joints, labels, hierarchy, facing pair, flags, URLs of rest.glb, files/preview.png, files/annotation.json, annotation.
POST /api/animate
Body {asset, prompt, num_samples?, cfg_scale?, seed?, preview?}. Returns the result with a URL per output file and ready-made next bodies for the modes below.
POST /api/inbetween
Body {reference_job_id, reference_sample?, reference_start?, keep_frames?, prompt, …}. Kept frames stay, the others are regenerated.
POST /api/edit
Body {reference_job_id, reference_sample?, reference_start?, keep_joints, prompt, …}. Kept joints stay, the others are regenerated.
POST /api/expand
Body {asset, prompts[], overlap?, …}. One long motion from several prompts; num_samples × prompts ≤ 8 per call.
GET /api/jobs/{job_id}
A result again (kept 24 h): r_, a_ or p_. Files: /api/jobs/{job_id}/files/{name}.
GET /api/examples
The bundled meshes and skeletons, and the results above with the request that reproduces each.
GET /api/identity
Who pays the GPU time for the headers you send.
GET /api, /api/health, /api/gpu_check
Parameters, limits, provenance; liveness; a 10 s GPU probe.

Parameters

prompt, prompts
Training-style caption: start with “An object” and describe one motion (“An object walks forward.”), up to 300 characters. prompts: 2 to 6 captions for a chained motion.
num_beams, seed / rig_seed
Rigging: beam-search width 1 to 20 (default 10); the rig's seed (random by default). In animate_mesh the rig's seed is rig_seed.
keep_skeleton, preserve_original
Keep the file's armature and predict only the weights; transfer the rig onto the untouched input so textures, materials and scale survive into the animated GLB (default false: normalized frame).
postprocess, influences
Voxel mask on the skin weights (default false); bones kept per vertex in the GLB, 1 to 8 (default 4).
labels, face_right, face_left
Asset corrections: {joint name: label} from the anatomical vocabulary; the two joints (the character's own right and left) that define its facing. body_axis marks a head / tail pair; rest_rotation (“x180”, “x90,y180”) stands up a lying or upside-down rest pose.
num_samples, cfg_scale, seed
1 to 4 independent motion samples; guidance 1.0 to 15.0 (default 3.0: 5 to 7 if the prompt is ignored, lower for calmer motion); the motion's seed.
reference_job_id, reference_sample, reference_start
In-betweening and editing: an earlier motion of the same asset (kept 24 h), which sample (default 0) and the first frame of its 60-frame window (default 0).
keep_frames, keep_joints
Frames held at the reference (negatives count from the end; default "0,-1"); joint names or labels held at the reference (case-insensitive; a label selects every joint carrying it).
overlap, preview
Expansion: frames pinned between consecutive segments, 1 to 59 (default 10). Previews (skeleton MP4 and contact sheet) on by default.

Outputs

animation.glb
The asset's canonical mesh + skeleton + the generated animation (glTF 2.0, 60 LINEAR keys at 30 fps; expansion: 60 + 50 keys per extra prompt). Opens in Blender, three.js, Unity, Godot.
rigged.glb, rig.json, skin.npz
The SkinTokens rig: mesh + armature (bone_0 is the root) + skin weights; joint names, parents, rest positions, skin statistics; the full weights.
rest.glb, preview.png, annotation.json
Per asset: the canonical rest-pose GLB the motions drive; the T-pose with facing pair, forward arrow and every joint's label; the upstream review file with flags and the vocabulary.
motion.npy, joints.json
(frames, J, 12) float32 UniMate features, exactly what unimate.inference.sample writes; world joint positions per frame with names, labels and parents.
previews
Rig: mesh with the skeleton (front and side) and a GLB with visible bones and a test wiggle. Motion: skeleton MP4 and a 6-frame contact sheet.

Models and provenance

Skin Tokens: A Learned Compact Representation for Unified Autoregressive Rigging. Jia-peng Zhang, Cheng-Feng Pu, Meng-Hao Guo, Yan-Pei Cao, Shi-Min Hu. ACM Transactions on Graphics 2026. arXiv 2602.04805 · code (MIT) · weights (MIT) · authors' Space. This service runs the released checkpoint grpo_1400.ckpt (TokenRig, 595M parameters) through the authors' own inference code, vendored from their Space at revision 1f4445ba; Blender 4.5 reads the input and writes the rigged GLB. The same engine as SkinTokens for Agents.

UniMate: One Unified Model to Animate Diverse Skeletons. Linzhan Mou, Jiahui Lei, Zhiyang Dou, Chenyue Cai, Chaoyue Song, Adam Finkelstein, Szymon Rusinkiewicz. SIGGRAPH Asia 2026. arXiv 2609.05415 · project page · code (MIT) · checkpoints (CC BY-NC 4.0). This service runs unimate_uniml3d_f60_v3 step 150000 (EMA weights, 74M-parameter flow-matching transformer, 50 ODE steps) with the frozen google/flan-t5-base text encoder through the repository's own inference code at commit b78c7807, and prepares assets with the repository's own data_process.rig_preprocess pipeline (offline rule annotation, no LLM). The same engine as UniMate for Agents. The animated GLB comes from a Blender-free glTF baker checked against Blender's importer (1e-5).

SkinTokens code and weights are MIT; UniMate code is MIT and its weights are for non-commercial research use (CC BY-NC 4.0; the training data keep their own terms). The bundled example assets keep their licenses (listed above and by /api/examples). The UniMate project page's 3D showcase is access-controlled and is not used; every output of this service is generated live. Details in PROVENANCE.md.

Limitations

SkinTokens names joints bone_i, builds a single-rooted tree, occasionally stops early (the service retries once with the next seed) and gives arbitrary skeletons to shapes that are not characters. The labels of such a rig come from the rest-pose geometry (symmetry, limbs, floor, trunk, head, tail), so unusual bodies or a lying / upside-down rest pose get placeholder labels or no facing pair: the asset preview and the flags show it, labels, face_right / face_left and rest_rotation correct it; at most 71 joints. UniMate has no contact model (feet can slide or hover), rare skeletons and motions can come out static, jittery or off-prompt, and it generates 60 frames per prompt (longer through expansion) as rotations only. Ask for several samples, try a few phrasings, raise cfg_scale to 5 to 7 when a prompt is ignored.