GenerateRequest
The body of POST /generate.
Top-level shape
| Field | Type | Required | Notes |
|---|---|---|---|
protocol_version | string matching ^\d+\.\d+$ | yes | Wire version. A v1.x server MUST accept any value matching ^1\.\d+$ and MAY refuse other majors with version_unsupported |
model | string | yes | One of Capabilities.models[].id |
skeleton | Skeleton | yes | The character's skeleton; must be sent every time |
segments | Segment[] | no, default [] | Discriminated union of TextSegment, UnconditionedSegment, PoseSegment and (1.2) MotionReferenceSegment and VideoReferenceSegment. A pose stands alone; a motion or video reference composes exactly like a text segment. At least one of segments or constraints must be non-empty |
constraints | Constraint[] | no, default [] | See constraint primitives |
duration_frames | int (> 0) | conditional | Required when segments is empty (constraints-only); forbidden when segments is non-empty |
timing | { "fps": number } | no | If set, frames are interpreted in this fps and the response is resampled. See Timing → |
options | Options | no, default object | Generation hyperparameters |
The skeleton is required in every request. A backbone with
supports_retargeting=false MUST be sent its canonical_skeleton
verbatim; otherwise the server returns 400. A backbone with retargeting
accepts any skeleton.
Options
{
"diffusion_steps": 100,
"num_samples": 1,
"seed": 42,
"post_processing": true,
"transition_frames": 5,
"guidance": {
"type": "separated",
"weight": [2.0, 2.0]
}
}
| Field | Type | Default | Notes |
|---|---|---|---|
diffusion_steps | int (1–500) | 100 | Backbone-specific; ignored by non-diffusion models |
num_samples | int (1–model.limits.max_num_samples) | 1 | Independent samples per request. Samples differ only in stochastic backbone choices (e.g. distinct initial noise drawn from the shared RNG stream) |
seed | int | null | null | RNG seed for reproducibility. Fixes the RNG state before generation, making the full (seed, num_samples) tuple deterministic |
post_processing | bool | true | Foot-skate cleanup, root correction (backbone-specific) |
transition_frames | int (0–60) | 5 | Blend window between segments. Rotations blend via slerp; root translation blends linearly |
guidance.type | "nocfg" | "regular" | "separated" | backbone default | Classifier-free guidance mode |
guidance.weight | float[] | backbone default | Length 1 for regular, length 2 for separated, length 0 (or omitted) for nocfg |
Backbones that don't implement an option MAY ignore it; they MUST NOT fail.
Re-sending an identical request with the same seed and num_samples
yields an identical response. Clients that need to reproduce an
individual sample from a multi-sample response should re-request with the
same seed and sample count, then pick the same index — servers do not
guarantee that sample i is reproducible via a separate num_samples: 1
request with a derived seed.
Examples
Minimal — text-only
{
"protocol_version": "1.0",
"model": "kimodo-soma-rp",
"skeleton": { "joints": [ /* model's canonical skeleton */ ] },
"segments": [{ "type": "text", "prompt": "a person walks forward", "duration_frames": 90 }]
}
Multi-segment with unconditioned bridge
{
"protocol_version": "1.0",
"model": "kimodo-soma-rp",
"skeleton": { "joints": [ /* … */ ] },
"segments": [
{ "type": "text", "prompt": "person walks forward", "duration_frames": 90 },
{ "type": "unconditioned", "duration_frames": 30 },
{ "type": "text", "prompt": "then sits down", "duration_frames": 60 }
],
"options": { "seed": 42, "transition_frames": 8 }
}
Constraints + custom skeleton
{
"protocol_version": "1.0",
"model": "kimodo-soma-rp",
"skeleton": {
"joints": [
{ "name": "Hips", "parent": null, "rest_translation": [0, 0.95, 0], "rest_rotation": [0, 0, 0, 1] },
{ "name": "Spine", "parent": "Hips", "rest_translation": [0, 0.10, 0], "rest_rotation": [0, 0, 0, 1] },
{ "name": "LeftArm", "parent": "Spine", "rest_translation": [0.18, 0.30, 0], "rest_rotation": [0, 0, 0, 1] }
],
"coordinate_system": "right_handed_y_up",
"units": "meters"
},
"segments": [{ "type": "text", "prompt": "wave hello", "duration_frames": 60 }],
"constraints": [
{
"type": "root_path",
"frames": [0, 30, 60],
"positions_xz": [[0,0], [0.5,0], [1,0]]
},
{
"type": "effector_target",
"joint": "LeftArm",
"frames": [0, 30, 59],
"positions": [[0.5, 1.4, 0.2], [0.6, 1.6, 0.3], [0.5, 1.4, 0.2]]
}
]
}
A clip as the prompt (1.2)
Four new performances of the kind of motion in a 2-second reference,
3 seconds long, to a model that lists "motion_reference" in
supported_segments — the request a text prompt would make, with the clip
where the prompt was:
{
"protocol_version": "1.2",
"model": "kimodo-soma-rp",
"skeleton": { "joints": [ /* … */ ] },
"segments": [{
"type": "motion_reference",
"duration_frames": 90,
"joint_names": ["Hips", "Spine1", "..."],
"rotations": [ /* 60 frames × one [x, y, z, w] per joint */ ],
"root_positions": [ /* 60 × [x, y, z] */ ],
"fps": 30
}],
"options": { "num_samples": 4 }
}
A clip from another rig carries that rig as the segment's skeleton (same
schema as the request skeleton); its joint_names are then that rig's,
and the server retargets the clip from it:
{ "type": "motion_reference", "duration_frames": 120,
"skeleton": { "joints": [ { "name": "mixamorig:Hips", "parent": null, /* … */ }, /* … */ ] },
"joint_names": ["mixamorig:Hips", "mixamorig:Spine", "..."],
"rotations": [ /* … */ ], "root_positions": [ /* … */ ], "fps": 30 }
Two clips in one take (1.2)
References are prompts like text segments, so they mix with them: here a walk like one clip, a text prompt, then a sit like another clip (sampled on a Mixamo rig), stitched with the usual transitions.
{
"protocol_version": "1.2",
"model": "kimodo-soma-rp",
"skeleton": { "joints": [ /* the character */ ] },
"segments": [
{ "type": "motion_reference", "duration_frames": 90,
"joint_names": ["Hips", "Spine1", "..."],
"rotations": [ /* walk: T × J × [x, y, z, w] */ ], "root_positions": [ /* T × 3 */ ], "fps": 30 },
{ "type": "text", "prompt": "a person stops and looks around", "duration_frames": 45 },
{ "type": "motion_reference", "duration_frames": 75,
"skeleton": { "joints": [ /* the sit clip's rig */ ] },
"joint_names": ["mixamorig:Hips", "..."],
"rotations": [ /* sit */ ], "root_positions": [ /* … */ ], "fps": 30 }
],
"options": { "num_samples": 2, "transition_frames": 5 }
}
See Segments →
for the rules, and Building reference segments → for how to sample
rotations and root_positions from a rig.
A video as the prompt (1.2)
The dance in seconds 2–6 of a video, as a 4-second take on the character,
to a model that lists "video_reference" in supported_segments. The
server fetches the URL and follows the most prominent dancer in it:
{
"protocol_version": "1.2",
"model": "my-video-model",
"skeleton": { "joints": [ /* … */ ] },
"segments": [{
"type": "video_reference",
"duration_frames": 120,
"video": { "url": "https://cdn.example.com/dance.mp4" },
"start_s": 2.0,
"end_s": 6.0
}]
}
A video from disk goes inline as base64, with its container's media type
(motionmcp.client.video_source("clip.mov") builds this object):
{ "type": "video_reference", "duration_frames": 90,
"video": { "data": "AAAAFGZ0eXBxdCAg…", "media_type": "video/quicktime" } }
Text, a clip and a video in one take (1.2)
All three kinds of prompt mix in any order: a walk from words, a stop like a
reference clip, then a turn like the one in a video, stitched with the usual
transitions. Each segment can take its own seed.
{
"protocol_version": "1.2",
"model": "my-video-model",
"skeleton": { "joints": [ /* the character */ ] },
"segments": [
{ "type": "text", "prompt": "a person walks forward", "duration_frames": 90, "seed": 7 },
{ "type": "motion_reference", "duration_frames": 45,
"joint_names": ["Hips", "Spine1", "..."],
"rotations": [ /* stop: T × J × [x, y, z, w] */ ], "root_positions": [ /* T × 3 */ ],
"fps": 30 },
{ "type": "video_reference", "duration_frames": 60,
"video": { "url": "https://cdn.example.com/turn.mp4" }, "end_s": 2.5 }
],
"options": { "num_samples": 2, "transition_frames": 5 }
}
See Segments → for the rules, and Building reference segments → for how to build each one.