Skip to main content
Glama

jobd_submit

Submit a shell command to the jobd broker for GPU-aware routing and execution across your machines. Supports sync waiting, job arrays, and parameter sweeps.

Instructions

Submit a job to the jobd broker. Default async; pass wait=true to block up to wait_timeout_s (server clamps to 270).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
cwdYesAbsolute path; broker validates against worker mount_roots.
gpuNotrue = pin to a GPU-capable worker. false or omitted = no GPU preference (any worker, GPU or not) — the same as leaving off the CLI's --gpu. Forbidding GPU workers (CLI --no-gpu) is not offered here.
hostNoHost alias pin (laptop, desktop-vm).
waitNoSync mode: block until terminal or timeout. For an array submit (count/sweep), waits on every member under one shared deadline and returns an aggregate {array_id, count, job_ids, states, all_completed, members:[{job_id, state, exit_code}]}.
extraNoEscape hatch: idempotent (bool), depends_on (int[]), depends_on_any_exit (bool), priority (int delta), max_wall_s (int), idle_timeout_s (int), max_retries (int, default 0: re-run up to N times on a plain non-zero exit), retry_delay_s (int), scheduling_timeout_s (int 1..604800 — give up and terminate the job as 'scheduling_timeout' if it is still QUEUED after N seconds; omit to wait indefinitely for a capable worker), checkpoint_grace_s (int 1..300), vram_gb (float — explicit GPU VRAM the job needs at dispatch; falls back to cuda-Ngb tier-tag max, then to 2 GB floor for --gpu jobs), count (int 1..1000 — submit a job array of N members, with `{i}` in the command replaced by the 0-based index; response is {array_id, count, job_ids, warnings} instead of a single job), sweep (list of {key, values[]} — parameter-sweep axes; broker fans out the cartesian product, substituting `{key}` per member plus `{i}`; mutually exclusive with count; product capped at 1000), profile (str), env (dict), preemptible (bool), session_id (str), arch (str — pin to a worker CPU arch), os (str — pin to a worker OS).
needsNoTool tags (R, python3, cuda).
commandYesShell command run by the worker shell.
dry_runNoPreview mode: run full validation + routing decision (profile, project defaults, cwd, depends_on, preflight, gpu_contention) and return the would-be plan WITHOUT queueing. Response has state='dry-run', would_route_to (list[host]), would_use_worker (host or null), validation (resolved fields + warnings). Per dry-run convention 2026-05-18.
projectYesScheduling identity. A registered projects.yaml name (matched case- and -/_-insensitively) prices at its priority; an unregistered name is priced by the project whose roots: contain cwd, else by _default. The result's project_label carries the name as typed when the two differ.
wait_timeout_sNoSeconds; permissive — server clamps to 270.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed6 schema fields changedv0.5.47
    • addedInput schema / $defs
      Added value: +{
      +  "JobRequires": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "arch": {
      +        "default": "any",
      +        "title": "Arch",
      +        "type": "string"
      +      },
      +      "gpu": {
      +        "anyOf": [
      +          {
      +            "type": "boolean"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "default": null,
      +        "title": "Gpu"
      +      },
      +      "idempotent": {
      +        "default": false,
      +        "title": "Idempotent",
      +        "type": "boolean"
      +      },
      +      "needs": {
      +        "items": {
      +          "type": "string"
      +        },
      +        "title": "Needs",
      +        "type": "array"
      +      },
      +      "os": {
      +        "default": "any",
      +        "title": "Os",
      +        "type": "string"
      +      }
      +    },
      +    "title": "JobRequires",
      +    "type": "object"
      +  },
      +  "SweepAxis": {
      +    "additionalProperties": false,
      +    "description": "One named axis of a parameter sweep: a key and the values it ranges over.\n\nThe broker takes the cartesian product of all axes to fan out array members;\neach member substitutes `{key}` → its value in the command and env. `{i}`\n(the flat member index) is always available alongside the named keys, so\n`i` is reserved and rejected as an axis key. See jobd.arrays.",
      +    "properties": {
      +      "key": {
      +        "minLength": 1,
      +        "title": "Key",
      +        "type": "string"
      +      },
      +      "values": {
      +        "items": {
      +          "type": "string"
      +        },
      +        "minItems": 1,
      +        "title": "Values",
      +        "type": "array"
      +      }
      +    },
      +    "required": [
      +      "key",
      +      "values"
      +    ],
      +    "title": "SweepAxis",
      +    "type": "object"
      +  }
      +}
    • addedInput schema / additionalProperties
      Added value: +false
    • changedInput schema / properties / extra / additionalProperties
      Previous value: -trueNew value: +false
    • changedInput schema / properties / extra / description
      Previous value: -"Escape hatch: idempotent (bool), depends_on (int[]), depends_on_any_exit (bool), priority (int delta), max_wall_s (int), idle_timeout_s (int), scheduling_timeout_s (int 1..604800 — give up and terminate the job as 'scheduling_timeout' if it is still QUEUED after N seconds; omit to wait indefinitely for a capable worker), checkpoint_grace_s (int 1..300), vram_gb (float — explicit GPU VRAM the job needs at dispatch; falls back to cuda-Ngb tier-tag max, then to 2 GB floor for --gpu jobs), count (int 1..1000 — submit a job array of N members, with `{i}` in the command replaced by the 0-based index; response is {array_id, count, job_ids, warnings} instead of a single job), sweep (list of {key, values[]} — parameter-sweep axes; broker fans out the cartesian product, substituting `{key}` per member plus `{i}`; mutually exclusive with count; product capped at 1000), profile (str), env (dict), preemptible (bool), session_id (str), arch (str — pin to a worker CPU arch), os (str — pin to a worker OS)."New value: +"Escape hatch: idempotent (bool), depends_on (int[]), depends_on_any_exit (bool), priority (int delta), max_wall_s (int), idle_timeout_s (int), max_retries (int, default 0: re-run up to N times on a plain non-zero exit), retry_delay_s (int), scheduling_timeout_s (int 1..604800 — give up and terminate the job as 'scheduling_timeout' if it is still QUEUED after N seconds; omit to wait indefinitely for a capable worker), checkpoint_grace_s (int 1..300), vram_gb (float — explicit GPU VRAM the job needs at dispatch; falls back to cuda-Ngb tier-tag max, then to 2 GB floor for --gpu jobs), count (int 1..1000 — submit a job array of N members, with `{i}` in the command replaced by the 0-based index; response is {array_id, count, job_ids, warnings} instead of a single job), sweep (list of {key, values[]} — parameter-sweep axes; broker fans out the cartesian product, substituting `{key}` per member plus `{i}`; mutually exclusive with count; product capped at 1000), profile (str), env (dict), preemptible (bool), session_id (str), arch (str — pin to a worker CPU arch), os (str — pin to a worker OS)."
    • addedInput schema / properties / extra / properties
      Added value: +{
      +  "arch": {
      +    "default": "any",
      +    "title": "Arch",
      +    "type": "string"
      +  },
      +  "checkpoint_grace_s": {
      +    "anyOf": [
      +      {
      +        "maximum": 300,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "title": "Checkpoint Grace S"
      +  },
      +  "count": {
      +    "default": 1,
      +    "maximum": 1000,
      +    "minimum": 1,
      +    "title": "Count",
      +    "type": "integer"
      +  },
      +  "depends_on": {
      +    "items": {
      +      "type": "integer"
      +    },
      +    "title": "Depends On",
      +    "type": "array"
      +  },
      +  "depends_on_any_exit": {
      +    "default": false,
      +    "title": "Depends On Any Exit",
      +    "type": "boolean"
      +  },
      +  "env": {
      +    "additionalProperties": {
      +      "type": "string"
      +    },
      +    "title": "Env",
      +    "type": "object"
      +  },
      +  "idempotent": {
      +    "default": false,
      +    "title": "Idempotent",
      +    "type": "boolean"
      +  },
      +  "idle_timeout_s": {
      +    "anyOf": [
      +      {
      +        "maximum": 86400,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "title": "Idle Timeout S"
      +  },
      +  "max_retries": {
      +    "default": 0,
      +    "maximum": 20,
      +    "minimum": 0,
      +    "title": "Max Retries",
      +    "type": "integer"
      +  },
      +  "max_wall_s": {
      +    "anyOf": [
      +      {
      +        "maximum": 604800,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "title": "Max Wall S"
      +  },
      +  "os": {
      +    "default": "any",
      +    "title": "Os",
      +    "type": "string"
      +  },
      +  "preemptible": {
      +    "anyOf": [
      +      {
      +        "type": "boolean"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "title": "Preemptible"
      +  },
      +  "priority": {
      +    "default": 0,
      +    "title": "Priority Delta",
      +    "type": "integer"
      +  },
      +  "profile": {
      +    "anyOf": [
      +      {
      +        "type": "string"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "title": "Profile"
      +  },
      +  "retry_delay_s": {
      +    "default": 0,
      +    "maximum": 86400,
      +    "minimum": 0,
      +    "title": "Retry Delay S",
      +    "type": "integer"
      +  },
      +  "scheduling_timeout_s": {
      +    "anyOf": [
      +      {
      +        "maximum": 604800,
      +        "minimum": 1,
      +        "type": "integer"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "title": "Scheduling Timeout S"
      +  },
      +  "session_id": {
      +    "anyOf": [
      +      {
      +        "type": "string"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "title": "Session Id"
      +  },
      +  "sweep": {
      +    "items": {
      +      "$ref": "#/$defs/SweepAxis"
      +    },
      +    "title": "Sweep",
      +    "type": "array"
      +  },
      +  "vram_gb": {
      +    "default": 0,
      +    "minimum": 0,
      +    "title": "Vram Gb",
      +    "type": "number"
      +  }
      +}
    • changedInput schema / properties / gpu / description
      Previous value: -"Pin to GPU-capable worker."New value: +"true = pin to a GPU-capable worker. false or omitted = no GPU preference (any worker, GPU or not) — the same as leaving off the CLI's --gpu. Forbidding GPU workers (CLI --no-gpu) is not offered here."
  2. Changed1 schema field changedv0.5.44
    • changedInput schema / properties / project / description
      Previous value: -"Priority lookup key; falls back to _default."New value: +"Scheduling identity. A registered projects.yaml name (matched case- and -/_-insensitively) prices at its priority; an unregistered name is priced by the project whose roots: contain cwd, else by _default. The result's project_label carries the name as typed when the two differ."
  3. Addedv0.5.35
  4. Removedv0.5.34
  5. Changed1 schema field changedv0.5.26
    • changedInput schema / properties / extra / description
      Previous value: -"Escape hatch: idempotent (bool), depends_on (int[]), depends_on_any_exit (bool), priority (int delta), max_wall_s (int), idle_timeout_s (int), checkpoint_grace_s (int 1..300), vram_gb (float — explicit GPU VRAM the job needs at dispatch; falls back to cuda-Ngb tier-tag max, then to 2 GB floor for --gpu jobs), count (int 1..1000 — submit a job array of N members, with `{i}` in the command replaced by the 0-based index; response is {array_id, count, job_ids, warnings} instead of a single job), sweep (list of {key, values[]} — parameter-sweep axes; broker fans out the cartesian product, substituting `{key}` per member plus `{i}`; mutually exclusive with count; product capped at 1000), profile (str), env (dict), preemptible (bool)."New value: +"Escape hatch: idempotent (bool), depends_on (int[]), depends_on_any_exit (bool), priority (int delta), max_wall_s (int), idle_timeout_s (int), scheduling_timeout_s (int 1..604800 — give up and terminate the job as 'scheduling_timeout' if it is still QUEUED after N seconds; omit to wait indefinitely for a capable worker), checkpoint_grace_s (int 1..300), vram_gb (float — explicit GPU VRAM the job needs at dispatch; falls back to cuda-Ngb tier-tag max, then to 2 GB floor for --gpu jobs), count (int 1..1000 — submit a job array of N members, with `{i}` in the command replaced by the 0-based index; response is {array_id, count, job_ids, warnings} instead of a single job), sweep (list of {key, values[]} — parameter-sweep axes; broker fans out the cartesian product, substituting `{key}` per member plus `{i}`; mutually exclusive with count; product capped at 1000), profile (str), env (dict), preemptible (bool), session_id (str), arch (str — pin to a worker CPU arch), os (str — pin to a worker OS)."
  6. First observedv0.5.5

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden, and it does disclose key behavioral traits: submission is asynchronous by default, wait=true switches to blocking, and wait_timeout_s is clamped to 270. It does not describe success responses or error conventions, though the side effect of submission is clear from the verb.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler: the primary behavior is front-loaded, and the timeout caveat is stated compactly. Nothing in the description repeats schema text unnecessarily.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter submission tool with no output schema, the description is relatively thin: it explains sync versus async but never states what a successful response contains (e.g., job_id or array_id), which the agent needs to hand off to jobd_status or jobd_logs. The rich parameter schema compensates for parameter details, but response expectations are left to inference.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the parameter baseline is 3. The description adds a useful restatement of wait/wait_timeout_s semantics, but the remaining parameters are already fully documented in the schema, so no further compensation is needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a direct verb–resource pair ('Submit a job to the jobd broker') that clearly states the operation. It is set apart from the sibling tools, which are all post-submission queries or mutations such as jobd_status, jobd_logs, and jobd_cancel.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives an explicit usage default ('Default async') and the exact condition for the blocking alternative ('pass wait=true'), so an agent knows how to invoke it. It does not explicitly name sibling tools as alternatives, but the sibling list is dominated by post-submission operations, making the correct context fairly clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.