Skip to main content

2. Design contracts and the manifest

A caller cannot use your Python object directly. It needs a discoverable description of the operation and a stable way to validate input and output. That is the descriptor's job.

Studio defines Pydantic contracts in contracts.py, generates JSON Schemas from them, then places those schemas in SDK descriptors. The same contracts feed its web-client types.

Start with useful operations​

Studio publishes six descriptors, all version 1.0.0:

DescriptorCaller sendsCaller receives
video.readinessReadiness requestAPI, catalog, placement and engine readiness facts.
video.planA render requestThe resolved render plan and its digest.
video.renderAn operation verb envelopePlan, status, listing or logs for a durable render.
video.refineAn operation verb envelopePlan, status, listing or logs for a durable rewrite.
video.assetsLibrary verb: list, import, label, remove or takeReference-library report.
video.takesRetention verb: list, keep, forget or deleteSaved-take marks.

These are application actions. They are not a descriptor for every HTTP endpoint, nor a remote interface to worker internals.

Plain request versus operation envelope​

A video.plan payload is a render request:

{
"prompt": "A fox crosses a snowy field, one continuous wide shot.",
"seconds": 5,
"aspect_ratio": "16:9",
"seed": 42
}

Those values still need validation against the selected model card. Five seconds is an example, not a duration supported by every card.

A video.render payload wraps the input in the SDK operation contract:

{
"op": "start",
"operation_id": "example-shot-001",
"input": {
"prompt": "A fox crosses a snowy field, one continuous wide shot.",
"seconds": 5,
"aspect_ratio": "16:9",
"seed": 42
}
}

This shows the payload shape only. For a reviewed render, use the effective input returned by the operation plan, including its plan_digest; do not blindly submit this example. The outer Fabric call also names the provider, capability version and discovered descriptor revision.

operation_descriptor() embeds the application input/result schemas inside the SDK's verb contract. Its caller-facing input is therefore not just RenderRequest. This is an easy mistake when building your first durable capability.

Read the descriptor construction​

The following is the real descriptor builder. Notice the two uses of operation_descriptor() and the four plain Descriptor values.

studio:contracts.py:build_descriptors
def build_descriptors() -> tuple[Descriptor, ...]:
"""The three descriptors of this release, generated from the models above."""
plan = Descriptor(
id=PLAN_ID,
version=DESCRIPTOR_VERSION,
title="Plan a MiniMax H3 render",
description=(
"Resolve a render request against the placed video card: mode, "
"adapter and step schedule, canvas, frame count, and an estimate. "
"Read-only; returns the plan digest that a start must match."
),
input_schema=json_schema_of(RenderRequest),
output_schema=json_schema_of(RenderPlan),
)
render = operation_descriptor(
id=RENDER_ID,
version=DESCRIPTOR_VERSION,
title="Render a MiniMax H3 clip",
description=(
"Durable render through the host video job API: start reserves the "
"operation and submits once, status mirrors the job, cancel stops "
"it, and the finished clip is kept on this host."
),
input_schema=json_schema_of(RenderRequest),
result_schema=json_schema_of(RenderResult),
)
readiness = Descriptor(
id=READINESS_ID,
version=DESCRIPTOR_VERSION,
title="Video rendering readiness",
description=(
"Whether the fleet can render: the API answers, a video card is in "
"the catalog, and a node with a video engine holds it. Read-only."
),
input_schema=json_schema_of(ReadinessRequest),
output_schema=json_schema_of(ReadinessReport),
)
refine = operation_descriptor(
id=REFINE_ID,
version=DESCRIPTOR_VERSION,
title=f"Refine a {MODEL_DISPLAY_NAME} prompt",
description=(
"Durable rewrite of an operator's intent into the model's prompt "
"structure, following MiniMax's published guides through a chat "
"model the fleet holds; attached assets are labelled the way the "
"guides expect. Local only: nothing leaves the fleet."
),
input_schema=json_schema_of(RefineRequest),
result_schema=json_schema_of(RefineResult),
)
assets = Descriptor(
id=ASSETS_ID,
version=DESCRIPTOR_VERSION,
title="Reference asset library",
description=(
"The studio's reference files, addressed by SHA-256: list them, "
"import a media file from this host, label one, or remove one. "
"Renders and refinements attach assets by digest."
),
input_schema=json_schema_of(AssetsCall),
output_schema=json_schema_of(AssetsReport),
)
takes = Descriptor(
id=TAKES_ID,
version=DESCRIPTOR_VERSION,
title="Keep or remove a take",
description=(
"The operator's marks on finished takes: list them, keep one from "
"the journal's pruning, release it again, or delete its clip and "
"thumbnail. Every verb answers with the marks as they stand."
),
input_schema=json_schema_of(TakesCall),
output_schema=json_schema_of(TakesReport),
)
return (plan, render, readiness, refine, assets, takes)

The function's old docstring says “three”; its returned tuple contains six. Read the executable contract when a comment and implementation disagree.

The descriptor's id and version identify the operation. Its revision binds the actual contract. Whenever you change a schema, regenerate the projections and rediscover the revision before calling. Do not paste a revision from a tutorial into production clients.

Request validation happens at two levels​

Studio's request model can reject impossible combinations without contacting Skulk™: duplicate first frames, keyframes without times, a source clip without a mask, or an exact size combined with a conflicting canvas selection.

Planning adds checks that depend on the card and fleet: whether the model supports that mode, whether a chosen adapter supports it, whether the duration and geometry fit, and whether eligible mounted capacity exists.

Use both. JSON Schema validates the shape; application planning validates what the requested work means on this cluster.

The manifest describes the installed application​

Studio's manifest binds the executable digest, descriptors, settings schema, operation limits and declared linked surfaces. Its effect is governed; render and refinement are exposed to Steward as operations that need effect approval.

Important limits at this source revision:

Manifest settingStudio valueWhy it matters
bounds.call_seconds20 secondsShort control calls must finish within their admission budget.
operations.max_queued8Limit waiting operations. This is not eight simultaneous GPU renders.
operations.max_runtime_seconds86,400 secondsApplication runtime ceiling; settings can reduce it.
operations.stale_after_seconds120 secondsMark stale observation rather than pretending it is fresh.
operations.retain256Bound displayed operation history. Replay fences have separate retention.
operations.log_bytes1 MiBBound retained logs for an operation.

These are Studio's limits, not recommended defaults for every application. A document converter or music generator should choose bounds suited to its own workload.

Authority is separate from agreement​

A descriptor revision says “we agree on this contract.” It does not say “you may run this effect.” Studio's host applies its governed installation policy before dispatch. The SDK operation service distinguishes read and effect authority; the authenticated Studio UI is an operator application path with effect authority.

Do not put caller-supplied authority="effect" into an untrusted request and assume it authorizes work. The grant must come from the trusted boundary admitting the call.

Discover and invoke​

A Fabric client uses GET /v1/capabilities to discover the provider and descriptors, then POST /v1/capabilities/call to invoke the chosen exact contract. Check both the HTTP result and the typed capability outcome: a valid transport response can contain invalid_payload, timeout or provider_error.

The complete transport envelope and authentication contract live in Skulk™'s capability API guide. The caller guide and descriptor explorer show discovery.

Next: start the managed child.