nvidia/skills · Official

tao-run-inference-service

Start, query, and stop a network-specific TAO inference microservice ({network_arch}-inference-microservice) by delegating container execution to the appropriate platform skill. Handles container image resolution, job-payload JSON construction, and the service registry. Use when the user wants to run inference on a TAO model checkpoint using a microservice container, deploy a TAO inference endpoint, or stop a running inference container.

All-time #7465 First seen Jun 8, 2026
8-week activity · all time api

Installation

$ npx skills add nvidia/skills --skill tao-run-inference-service

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from nvidia/skills · top by installs.

npx skills add nvidia/skills

Browse all from nvidia/skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 3.2K
License LICENSE-APACHE
Default branch main
Open issues 5
Status Active

Skill metadata

Parsed from SKILL.md frontmatter.

Version0.1.0
LicenseApache-2.0
CompatibilityThe inference service has no cloud-storage dependency — model weights come from the HuggingFace Hub (HF_TOKEN env var for gated models) or a local container path. Platform prerequisites are checked by each platform skill.
Allowed toolsRead Bash Write
More metadata
author
NVIDIA Corporation
version
0.1.0

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 18,441 B
  • docs SUMMARY.md 473 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1,600 installs

SKILL.md

TAO Inference Microservice

Standalone install? If this session was not initialized by the TAO skill bank plugin, run the tao-setup skill first (host preflight, credentials, cross-skill discovery).

Instructions

To start an inference service:

  1. Collect required inputs (Section 1) and resolve the container image (Section 2).
  2. Build the job payload and inner command (Sections 3–4.1); use references/code-templates.yamljobpayloadbuilder.
  3. Read skills/platform/<platform>/SKILL.md and start the container (Section 4.2).
  4. Write the service registry and poll readiness (Section 4.3); use references/code-templates.yamlregistrywrite.<platform> and readinesscheck.

To send an inference request:

  1. Resolve which service receives the request per Section 6.0 (by jobid, by networkarch, or by explicit user choice when multiple services run — never silently default to "latest" when more than one service exists), then read the endpoint from references/code-templates.yamlrequest.registryread with the resolved jobid.
  2. Before building the request body, prompt the user for the vLLM-style sampling parameters (Section 6.1). Present maxtokens, topp, temperature (and any per-arch extras) with their defaults; let the user override or skip each one to accept the default. Never silently use defaults.
  3. Build and send the body per Section 6.2; handle the response per Section 6.3.

To stop a service: Read references/code-templates.yamlstop.registryread to resolve the jobid, read skills/platform/<platform>/SKILL.md, then follow Section 5.

Reference data (schemas, mappings, valid values — no instructions):

  • references/service.yaml — image mappings, valid network_arch names, job payload schema, env var names, secrets classification.
  • references/request.yaml — endpoint definition, request field schema, response shapes, code examples.
  • references/code-templates.yaml — Python templates for payload building, registry writes, readiness checks, and stop/request flows.

Secrets rule (applies to every generated code block in this skill)

Never ask the user to type a secret value into a prompt. For every secret value:

  1. Tell the user which environment variable to set (e.g. export HF_TOKEN=...).
  2. Generate code that reads it with os.environ["VAR_NAME"] — never hard-code, interpolate, or prompt for the value.

Secret env vars (full list in references/service.yamlsecretshandling): HFTOKEN, WANDBAPIKEY, CLEARMLAPIACCESSKEY, CLEARMLAPISECRETKEY, TAOAPIKEY, TAOUSERKEY.

Safe to collect in the prompt: networkarch, modelpath, numgpus, prompt text, WANDB config URLs, CLEARMLHOST URLs.


1. What to collect from the user

Input Role
network_arch Chooses container image, the per-arch inner command shape (references/service.yamlcontainercommands.<networkarch>), and neuralnetworkname in the job JSON when applicable. Must match a basename in validnetworkarchconfigbasenames in references/service.yaml (e.g. cosmos-rl, cosmos-predict2.5).
model_path The trained model checkpoint. Valid forms: hfmodel://<org>/<model> (HuggingFace Hub — set HFTOKEN for gated models) or a local container filesystem path. Cloud URIs (s3://, gs://, az://) are NOT supported — the inference service has no cloud-storage dependency. Always ask the user; never substitute a placeholder. See references/service.yamlmodelpathprotocols.
platform Compute platform: local-docker, brev, slurm, or kubernetes.
num_gpus Defaults to 1; minimum 1 for inference.

2. Image resolution

Each networkarch has a sidecar config file named {networkarch}.config.json. Resolve the container image as follows:

  1. Read {networkarch}.config.json and take apiparams.image (e.g. COSMOSRL). This is a key into dockerimage_defaults.mapping in references/service.yaml.
  2. Look up that key in the mapping. If the host env var IMAGE<KEY> is set (e.g. IMAGECOSMOS_RL), it overrides the mapped default.
  3. The mapped value is normally a dotted key into the repo-root versions.yaml manifest (e.g. taotoolkit.cosmosrl). Resolve it to a concrete nvcr.io/... image URI by looking up versions.yamlimages.<group>.<name>. Absolute URIs pass through unchanged, so an IMAGE_<KEY> env-var override that contains a full URI still works. The Python helper for this lives in references/code-templates.yaml.
  4. If the config file is missing or apiparams.image is empty, fall back to the COSMOSRL key.

The config file also has specparams.inference.modelpath which drives folder vs file path semantics: if the value contains the substring folder, the container treats the path as a directory.


3. Environment variables (no callbacks)

Set these in envpayload before encoding envjson. Do not set TAOLOGGINGSERVERURL or TAOADMIN_KEY.

TAOEXECUTIONBACKEND — must match the platform:

Platform TAOEXECUTIONBACKEND value
local-docker local-docker
brev local-docker
slurm slurm
kubernetes local-k8s

CLOUDBASED — always "False" for this skill (disables callback posting to TAOLOGGINGSERVERURL).

GPU env vars — only needed when the platform skill does not handle GPU injection automatically:

  • Tegra / Jetson: --runtime=nvidia with NVIDIADRIVERCAPABILITIES=all and NVIDIAVISIBLEDEVICES=<ids>.
  • Standard x86 + nvidia-container-toolkit: use Docker device_requests. The platform skill handles this.

4. Executing across platforms

The job payload and inner command (Sections 1–3) are platform-agnostic. For each platform, read skills/platform/<name>/SKILL.md for preflight checks and credentials before generating any execution code.

4.1 Build the inner command (per arch)

The inner-command shape is per networkarch — there is no uniform template. Look up the per-arch entry in references/service.yamlcontainercommands.<networkarch>; if not present, the arch is unsupported — stop and ask. Pick the matching sub-block in references/code-templates.yamljobpayloadbuilder.<networkarch>. Prefix the command with umask 0 && and keep it identical across platforms (local-docker, brev, slurm, kubernetes).

Common across arches:

  • job_id: fresh uuid.uuid4() — becomes the container name and registry key.
  • image: resolve per Section 2.
  • Secrets (accesskey, secretkey, HF_TOKEN, etc.) are read from env vars at runtime — never hard-code, never log or print.

Arch-specific notes (full details in references/service.yamlcontainer_commands):

  • cosmos-rl — single --job '<JOBJSON>' --dockerenvvars '<ENVJSON>' blob; json.dumps(...) + shlex.quote(...). envpayload carries TAOEXECUTIONBACKEND (per Section 3 table), TAOAPIJOBID, CLOUDBASED=False. The inference service has no cloud-storage dependency; HFTOKEN is the only cred env var that ever applies (for gated HuggingFace models).
  • cosmos-predict2.5 — flag-style cosmospredict inferencemicroservice start ... --port 8080 (no setup. prefix; uses tyro.conf.OmitArgPrefixes). --job/--dockerenvvars are not accepted. Translate modelpath to --checkpoint-path (local path) or --model <registeredkey> (hfmodel://); cloud URIs are rejected. The only cred env var that ever applies is HFTOKEN for gated HuggingFace models. Per-request params (prompt, inferencetype, numoutputframes, guidance, seed, numsteps, negativeprompt) go in the request body, not at startup. TAOEXECUTIONBACKEND/TAOAPIJOBID/CLOUD_BASED are unused and may be omitted.

4.2 Delegate execution to the platform skill

Read skills/platform/<platform>/SKILL.md and follow it to start the container.

Base parameters (all platforms):

Parameter Value
image resolved container image (Section 2)
command inner — the shell string built in Section 4.1
gpu_count num_gpus
env_vars env_payload
job / container name job_id — must equal the UUID from 4.1 so the registry can reference it
host_port (local-docker, brev) host-side port to bind to container port 8080. Default 8080, but must be unique per concurrent service — see the port-allocation rule below.

Platform-specific additional inputs:

Platform Additional inputs
local-docker None beyond base
brev instanceid (optional — reuse an existing instance); on multi-credential / multi-workspace accounts also cloudcredid and workspacegroup_id for first-create — see skills/platform/tao-run-on-brev/SKILL.md
slurm partition and account — check SLURMPARTITION/SLURMACCOUNT env vars; ask user if unset
kubernetes namespace (default: default); imagepullsecret (required for nvcr.io images)

Port binding (local-docker and brev): use direct docker run (not DockerSDK) so that -p <hostport>:8080 can be passed and the container name equals jobid exactly.

Port allocation rule (local-docker and brev, REQUIRED for concurrent services): Before starting a service, read the registry (/tmp/tao-inf-ms-state.json) and collect the set of hostport values from every existing entry on the same platform (and, for brev, the same instanceid). Pick the lowest free port starting from 8080 that is not in that set — e.g. hostport = next(p for p in range(8080, 8200) if p not in usedports). The default 8080 only applies when no other service is running. This is what makes "start 3 services, each reachable at a distinct host_url" work; without it, services 2 and 3 fail with bind: address already in use. SLURM and kubernetes get distinct endpoints from their own platform mechanisms and do not need this step.

4.3 After start: service registry and endpoint

Write the service registry immediately after the platform confirms the container is running. The registry (/tmp/tao-inf-ms-state.json) is keyed by job_id; "latest" always points to the most recently started service.

See references/code-templates.yamlregistry_write.<platform> for the Python template.

Platform host_url platformjobid Extra step before writing
local-docker http://localhost:{host_port} None
brev http://{brevip}:{hostport} brev ls → get instance IP (localhost is invalid on remote VM)
slurm http://localhost:{host_port} SLURM scheduler job ID Wait until Running; SSH port-forward localhost:{host_port}→{node}:8080
kubernetes http://{external_ip}:8080 k8s job name kubectl expose job … --type=LoadBalancer; wait for external IP

After writing the registry, print the job_id and URL:

print(f"Inference service started.")
print(f"  Job ID : {job_id}")
print(f"  Arch   : {network_arch}")
print(f"  URL    : {state[job_id]['host_url']}/v1/chat/completions")
print(f"Use this Job ID to send requests or stop the service.")

Then poll for readiness — see references/code-templates.yamlreadiness_check. The container loads the model in the background; do not send requests before it returns 200.


5. Stopping the inference service

Ask the user for the jobid to stop. If they don't provide one, default to state["latest"] and confirm which jobid is being stopped. Read the registry using references/code-templates.yamlstop.registry_read, then read skills/platform/<platform>/SKILL.md and use its cancellation / stop mechanism.

Platform Identifier to pass Extra cleanup
local-docker jobidto_stop — container name None
brev jobidto_stop — container name None
slurm entry["platformjobid"] — SLURM job ID pkill -f "ssh.-L.{entry['host_port']}"
kubernetes entry["platformjobid"] — k8s job name kubectl delete svc {entry["platformjobid"]} -n <namespace>

where entry = state[jobidtostop]. After stopping, clean up the registry: references/code-templates.yamlstop.registrycleanup.


6. Sending inference requests

6.0 Resolve which service receives this request (REQUIRED)

Each request must be routed to the specific service that runs the matching model. Routing happens by jobid — the registry stores networkarch per entry, so you can resolve a target by arch when the user names a model instead of a job_id. Apply these rules in order:

  1. User provided an explicit job_id → use it. Verify it exists in state.
  2. User named a networkarch (e.g. "send this to the cosmos-rl service") → look up matching entries: candidates = [j for j, e in state.items() if j != "latest" and isinstance(e, dict) and e["networkarch"] == arch].

- Exactly one match → use it. - Multiple matches → prompt the user with the candidate jobids and their startedat; do not auto-pick. - No match → stop and tell the user no service for that arch is running.

  1. No jobid and no networkarch → count non-"latest" entries in state:

- Exactly one running service → use it. - Two or more → do not silently default to state["latest"]. Prompt the user with the full list (jobid, networkarch, host_url) and require an explicit choice. The "latest" pointer is a convenience for single-service workflows, not a routing fallback when multiple services coexist. - Zero → stop and tell the user to start a service first.

After resolving, read the endpoint from the registry (references/code-templates.yamlrequest.registryread), passing the resolved jobid as userprovidedjobid. Confirm to the user: "Sending to jobid=… arch=… url=…". If the service may still be loading, poll readiness first (references/code-templates.yamlreadiness_check).

Cross-check before sending: if the user-supplied request body contains arch-specific fields (e.g. guidance / numsteps / seed / negativeprompt → cosmos-predict2.5; required imageurl/videourl content items → cosmos-rl), verify they are consistent with state[jobid]["networkarch"]. On mismatch, stop and ask — sending a cosmos-predict2.5 body to a cosmos-rl service will fail at the container with a 4xx/5xx that is harder to diagnose than catching it here.

6.1 Sampling parameters — REQUIRED user prompt before each request

Before constructing the request body, you MUST explicitly prompt the user for the vLLM-style sampling parameters. Do not silently apply defaults. Use a structured prompt, one question per field, that:

  1. Lists every applicable field with its type and default value.
  2. Lets the user skip / accept any field to take that field's default — entering a value is never required.
  3. Collects all fields in one round.

After the prompt, apply each user-entered value verbatim and substitute the default for any skipped field. Do not invent values or silently clamp.

Field list, defaults, and per-arch applicability: references/request.yamlchatcompletionsrequestbody (base sampling fields: maxtokens, topp, temperature) and networkarchconstraints.<networkarch> (per-arch overrides and extras such as guidance/numsteps/seed/negativeprompt for cosmos-predict2.5). If a field is marked unsupported for the active arch, do not prompt for it and do not include it in the body.

6.2 Request format

Send a POST to {BASEURL}/v1/chat/completions with Content-Type: application/json and a timeout of at least 300 s. The body is OpenAI-compatible (vLLM chat completions); see references/request.yamlchatcompletionsrequestbody for the full field schema and content-item shapes (text / imageurl / videourl), and code_examples for ready-to-run Python and curl samples.

Constraints: only the first user message is processed. No secret values in request bodies. Per-network constraints (e.g. cosmos-rl requires every request to include an image or video; cosmos-rl rejects data: URIs) are in references/request.yamlnetworkarchconstraints.

6.3 Response handling

HTTP status Meaning Action
200 Success — choices[0].message.content has the generated text Read result
202 Server still initializing or model still loading Retry after a delay
503 Initialization failed, model load failed, or model not yet ready Inspect error.type: modelnotready → retry; initializationerror / modelload_error → give up and check logs
400 Missing or empty JSON body Fix request
500 Unhandled exception during inference Check container logs

For 202 and 503, the body contains {"error": {"type": "<errortype>", "message": "<reason>"}}. See containerresponse_shapes in references/request.yaml for error type strings.