> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.islo.dev/api-reference/jobs/validate-job-manifest/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.islo.dev/_mcp/server. # Validate job manifest without deploying POST https://api.islo.dev/jobs/{name}/validate Content-Type: application/json Reference: https://docs.islo.dev/api-reference/jobs/validate-job-manifest ## Authentication - `Authorization` header (bearer token, required) — Bearer authentication of the form `Bearer `, where token is your auth token. ## Request ### Path parameters - `name` (string, required) ### Body (application/json) This endpoint expects a JobDeployRequest. - `manifest` (JobManifest-Input, required) — Job manifest (authored as TOML or JSON, stored as JSON) ## Response ### 204 Successful Response ## Errors ### 401 Unauthorized Error Unauthorized - `code` (enum, required) - Allowed values: `AUTH_REQUIRED`, `INVALID_REQUEST`, `NOT_FOUND`, `VALIDATION_ERROR`, `SANDBOX_NOT_FOUND`, `SANDBOX_ALREADY_EXISTS`, `SANDBOX_INVALID_STATE`, `SANDBOX_PROVISIONING_FAILED`, `RESOURCE_NOT_FOUND`, `FILE_NOT_FOUND`, `COMMAND_NOT_FOUND`, `EXEC_FAILED`, `FILE_OPERATION_ERROR`, `RESOURCE_UNAVAILABLE`, `ACCESS_DENIED`, `CACHE_CONFLICT`, `BILLING_NOT_ALLOWED`, `TENANT_SUSPENDED`, `RATE_LIMITED`, `TIMEOUT`, `GONE`, `BAD_GATEWAY`, `INTERNAL_ERROR` - `message` (string, required) - `available` (long, optional, nullable) - `limit` (long, optional, nullable) - `request_id` (string, optional, nullable) - `requested` (long, optional, nullable) - `resource` (string, optional, nullable) — Optional capacity fields populated for `InsufficientResources` errors so clients (including peer agents) can recover the typed payload across HTTP boundaries instead of collapsing it to an opaque message. ### 422 Unprocessable Entity Error Unprocessable Content - `code` (enum, required) - Allowed values: `AUTH_REQUIRED`, `INVALID_REQUEST`, `NOT_FOUND`, `VALIDATION_ERROR`, `SANDBOX_NOT_FOUND`, `SANDBOX_ALREADY_EXISTS`, `SANDBOX_INVALID_STATE`, `SANDBOX_PROVISIONING_FAILED`, `RESOURCE_NOT_FOUND`, `FILE_NOT_FOUND`, `COMMAND_NOT_FOUND`, `EXEC_FAILED`, `FILE_OPERATION_ERROR`, `RESOURCE_UNAVAILABLE`, `ACCESS_DENIED`, `CACHE_CONFLICT`, `BILLING_NOT_ALLOWED`, `TENANT_SUSPENDED`, `RATE_LIMITED`, `TIMEOUT`, `GONE`, `BAD_GATEWAY`, `INTERNAL_ERROR` - `message` (string, required) - `available` (long, optional, nullable) - `limit` (long, optional, nullable) - `request_id` (string, optional, nullable) - `requested` (long, optional, nullable) - `resource` (string, optional, nullable) — Optional capacity fields populated for `InsufficientResources` errors so clients (including peer agents) can recover the typed payload across HTTP boundaries instead of collapsing it to an opaque message. ## Types ### JobManifest-Input Full job.toml manifest (TOML or JSON authoring; stored as JSON). - `job` (JobSection, required) - `run` (RunSection-Input, required) - `schedule` (ScheduleSection, optional, nullable) - `verification` (VerificationSection, optional, nullable) - `outputs` (map from string to JobOutputSpec, optional, nullable) — Public job output contract for the job and downstream lines. ### JobSection - `name` (string, required) — Job name; must match jobs/\/ and deploy path - `version` (string, optional, nullable) - `description` (string, optional, nullable) - `params` (map from string to JobParamSpec, optional, nullable) — Declared run parameters. Reference as \{\{name}} in manifest strings (substitution and undeclared-reference checks walk the whole manifest, not only step fields). Reserved: \{\{run\_id}}. ### RunSection-Input - `tasks` (list of Task-Input, required) - `fail_fast` (boolean, optional, default: true) - `fanout` (boolean, optional, default: false) - `concurrency` (integer, optional, default: 1) - `workdir` (string, optional, nullable) — Working directory for every exec and run_agent step. Defaults to ".". Falls back to run.sandbox.workdir when omitted. - `timeout` (RunSectionInputTimeout, optional, nullable) - `region` (string, optional, nullable) - `teardown_on_complete` (boolean, optional, nullable) - `resume_on_start` (boolean, optional, nullable) - `sandbox` (SandboxConfig, optional, nullable) — Sandbox requirements for job runs (matches compute IncomingWebhookSandboxTemplate shape). ### ScheduleSection - `cron` (string, required) — Cron expression; validated at deploy time. Every param the schedule uses must have a default before you add [schedule]. - `timezone` (string, optional, default: UTC) - `enabled` (boolean, optional, default: true) ### VerificationSection - `enabled` (boolean, optional, default: false) - `gate` (VerificationGate, optional, nullable) ### JobOutputSpec Public job output contract. Writers emit the producer type; lines bind the published type after reduce. Session agents and $ISLO_OUTPUT use producer types (collect/gather still send the producer type, not the published array). - `type` (enum, required) - Allowed values: `string`, `integer`, `number`, `boolean`, `array` - `items` (enum, optional, nullable) — Item type for array outputs. Required at deploy when type = array. Do not use reduce = collect with type = array; use gather to concatenate arrays. - Allowed values: `string`, `integer`, `number`, `boolean` - `required` (boolean, optional, default: true) - `description` (string, optional, nullable) - `enum` (list of any, optional, nullable) - `reduce` (enum, optional, default: one) — one: exactly one claiming step. last: last successful write in manifest task order. collect: published array of producer values (dense nulls for missing tasks); required collect must be claimed by every task. gather: concatenate arrays or collect scalars, skipping omissions. - Allowed values: `one`, `last`, `collect`, `gather` ### JobParamSpec - `type` (JobParamSpecType, required) - `items` (enum, optional, nullable) — Item type when type = array. - Allowed values: `string`, `integer`, `number`, `boolean` - `required` (boolean, optional, default: false) — Cannot combine required=true with a default. - `description` (string, optional, nullable) - `pattern` (string, optional, nullable) - `prefix` (string, optional, nullable) - `enum` (list of any, optional, nullable) ### Task-Input - `name` (string, required) - `steps` (list of TaskStep-Input, required) - `sandbox` (SandboxConfig, optional, nullable) — Sandbox requirements for job runs (matches compute IncomingWebhookSandboxTemplate shape). ### RunSectionInputTimeout ### SandboxConfig Sandbox requirements for job runs (matches compute IncomingWebhookSandboxTemplate shape). - `mode` (enum, optional, default: provision) - Allowed values: `provision`, `ensure`, `reuse` - `name` (string, optional, nullable) — Required for ensure/reuse. Supports \{\{param}} substitution. - `image` (string, optional, nullable) — Required for provision/ensure. - `vcpus` (integer, optional, default: 2) - `memory_mb` (integer, optional, default: 2048) - `disk_gb` (integer, optional, default: 10) - `snapshot_name` (string, optional, nullable) - `gateway_profile` (string, optional, nullable) - `environment` (string, optional, nullable) - `init` (SandboxConfigInit, optional, nullable) - `internet_enabled` (boolean, optional, default: true) - `workdir` (string, optional, nullable) — Sandbox default working directory. Used when [run].workdir is omitted. - `cache_key` (string, optional, nullable) - `env` (map from string to string, optional, nullable) - `sources` (list of GitSource, optional, nullable) - `setup_scripts` (list of SetupScript, optional, nullable) - `lifecycle` (LifecyclePolicy, optional, nullable) ### VerificationGate - `compare_to` (string, optional, nullable) - `min_pass_rate` (double, optional, nullable) ### JobParamSpecType ### TaskStep-Input One compute action per step. Define exactly one action key (exec, run_agent, snapshot, pause, resume, or delete). Task names and step names must be unique and non-blank. A job with [outputs], exactly one session run_agent step, and no step listing outputs implicitly claims every output key. More than one potential writer, or any explicit outputs list, requires every writer to claim. - `name` (string, optional, nullable) — Unique non-blank step name within the task. - `workdir` (string, optional, nullable) — Override \[run].workdir for this step. Supports \{\{name}} placeholders. - `timeout` (integer, optional, nullable) — Max wall-clock duration for this step in seconds. - `user` (string, optional, nullable) - `exec` (TaskStepInputExec, optional, nullable) — Shell command. Supports \{\{name}} placeholders in each argv element. Control plane sets \$ISLO\_OUTPUT to /dev/null when the step claims no output keys, or /tmp/islo\_output.\.\ when it claims keys. Write key=value lines (JSON after =, raw string fallback for type=string). Do not pre-create the file. Cap is 64 KiB. - `run_agent` (TaskStepInputRunAgent, optional, nullable) — Run an agent step. Session mode publishes claimed producer keys as structured JSON. Exec mode uses $ISLO_OUTPUT like exec. - `snapshot` (SnapshotStepAction, optional, nullable) - `pause` (boolean, optional, nullable) - `resume` (boolean, optional, nullable) - `delete` (boolean, optional, nullable) - `upload` (string, optional, nullable) — Not implemented yet; do not author. - `download` (string, optional, nullable) — Not implemented yet; do not author. - `outputs` (TaskStepInputOutputs, optional, nullable) — Claim job output keys. List shortcut: outputs = ["summary"]. Table: [run.tasks.steps.outputs.summary] from = "agent_key", required = true. ### SandboxConfigInit - `type`: `custom` (SandboxInitCustom) - `await_ready` (boolean, optional, default: false) - `capabilities` (list of enum, optional) - Allowed values: `ssh`, `docker` - `type`: `full` (SandboxInitFull) - `type`: `minimal` (SandboxInitMinimal) ### GitSource A git source to clone into /workspace. - `repo_url` (string, required) - `branch` (string, optional, nullable) - `target_path` (string, optional, nullable) ### SetupScript A named setup script to execute after git clones. - `script` (string, required) - `name` (string, optional) ### LifecyclePolicy - `auto_resume` (enum, optional) - Allowed values: `never`, `on_activity` - `delete_after` (long, optional, nullable) - `pause_after` (long, optional, nullable) - `pause_after_idle` (long, optional, nullable) ### TaskStepInputExec Shell command. Supports \{\{name}} placeholders in each argv element. Control plane sets \$ISLO\_OUTPUT to /dev/null when the step claims no output keys, or /tmp/islo\_output.\.\ when it claims keys. Write key=value lines (JSON after =, raw string fallback for type=string). Do not pre-create the file. Cap is 64 KiB. ### TaskStepInputRunAgent Run an agent step. Session mode publishes claimed producer keys as structured JSON. Exec mode uses $ISLO_OUTPUT like exec. - `mode`: `exec` (RunAgentExecStepAction) - `command` (TaskStepOutputRunAgentDiscriminatorMappingExecCommand, required) - `harness` (enum, required) - Allowed values: `codex`, `cursor`, `claude`, `opencode`, `custom` - `model` (string, optional, nullable) - `mode`: `session` (RunAgentSessionStepAction) - `harness` (enum, required) — Session outputs require claude, codex, cursor, or opencode. - Allowed values: `codex`, `cursor`, `claude`, `opencode` - `command` (TaskStepOutputRunAgentDiscriminatorMappingSessionCommand, optional, nullable) - `effort` (string, optional, nullable) — Reasoning effort token. Requires model. Legal values come from the effort table on GET /inference/models, which is keyed by harness and optionally by model. For cursor the pair also resolves to a real model id, because cursor encodes effort in the id rather than taking a flag. Omit to use the harness default. - `knowledge` (list of KnowledgeBinding, optional, nullable) - `mcp` (list of McpEntry, optional, nullable) — MCP server descriptors to make available to the agent. Each entry carries a key (unique label) and url (MCP endpoint). Duplicates by key are rejected. - `model` (string, optional, nullable) - `model_provider` (enum, optional, nullable) - Allowed values: `islo`, `islo_inference` - `prompt` (TaskStepOutputRunAgentDiscriminatorMappingSessionPrompt, optional, nullable) - `resume_prompt` (TaskStepOutputRunAgentDiscriminatorMappingSessionResumePrompt, optional, nullable) - `session` (string, optional, nullable) ### SnapshotStepAction - `name` (string, required) ### TaskStepInputOutputs Claim job output keys. List shortcut: outputs = ["summary"]. Table: [run.tasks.steps.outputs.summary] from = "agent_key", required = true. ### TaskStepOutputRunAgentDiscriminatorMappingExecCommand ### TaskStepOutputRunAgentDiscriminatorMappingSessionCommand ### KnowledgeBinding - `slug` (string, required) ### McpEntry One MCP server descriptor in a run_agent step. - `key` (string, required) - `url` (string, required) ### TaskStepOutputRunAgentDiscriminatorMappingSessionPrompt - `type`: `knowledge` (KnowledgeBinding) - `slug` (string, required) - `type`: `literal` (LiteralBinding) - `value` (any, required) ### TaskStepOutputRunAgentDiscriminatorMappingSessionResumePrompt - `type`: `knowledge` (KnowledgeBinding) - `slug` (string, required) - `type`: `literal` (LiteralBinding) - `value` (any, required) ## Examples **Request** ```json { "manifest": { "job": { "name": "string" }, "run": { "tasks": [ { "name": "string", "steps": [ {} ] } ] } } } ``` **SDK Code** ```python import requests url = "https://api.islo.dev/jobs/name/validate" payload = { "manifest": { "job": { "name": "string" }, "run": { "tasks": [ { "name": "string", "steps": [{}] } ] } } } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = 'https://api.islo.dev/jobs/name/validate'; const options = { method: 'POST', headers: {Authorization: 'Bearer ', 'Content-Type': 'application/json'}, body: '{"manifest":{"job":{"name":"string"},"run":{"tasks":[{"name":"string","steps":[{}]}]}}}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```go package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://api.islo.dev/jobs/name/validate" payload := strings.NewReader("{\n \"manifest\": {\n \"job\": {\n \"name\": \"string\"\n },\n \"run\": {\n \"tasks\": [\n {\n \"name\": \"string\",\n \"steps\": [\n {}\n ]\n }\n ]\n }\n }\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "Bearer ") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` ```ruby require 'uri' require 'net/http' url = URI("https://api.islo.dev/jobs/name/validate") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = 'Bearer ' request["Content-Type"] = 'application/json' request.body = "{\n \"manifest\": {\n \"job\": {\n \"name\": \"string\"\n },\n \"run\": {\n \"tasks\": [\n {\n \"name\": \"string\",\n \"steps\": [\n {}\n ]\n }\n ]\n }\n }\n}" response = http.request(request) puts response.read_body ``` ```java import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://api.islo.dev/jobs/name/validate") .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .body("{\n \"manifest\": {\n \"job\": {\n \"name\": \"string\"\n },\n \"run\": {\n \"tasks\": [\n {\n \"name\": \"string\",\n \"steps\": [\n {}\n ]\n }\n ]\n }\n }\n}") .asString(); ``` ```php request('POST', 'https://api.islo.dev/jobs/name/validate', [ 'body' => '{ "manifest": { "job": { "name": "string" }, "run": { "tasks": [ { "name": "string", "steps": [ {} ] } ] } } }', 'headers' => [ 'Authorization' => 'Bearer ', 'Content-Type' => 'application/json', ], ]); echo $response->getBody(); ``` ```csharp using RestSharp; var client = new RestClient("https://api.islo.dev/jobs/name/validate"); var request = new RestRequest(Method.POST); request.AddHeader("Authorization", "Bearer "); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{\n \"manifest\": {\n \"job\": {\n \"name\": \"string\"\n },\n \"run\": {\n \"tasks\": [\n {\n \"name\": \"string\",\n \"steps\": [\n {}\n ]\n }\n ]\n }\n }\n}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` ```swift import Foundation let headers = [ "Authorization": "Bearer ", "Content-Type": "application/json" ] let parameters = ["manifest": [ "job": ["name": "string"], "run": ["tasks": [ [ "name": "string", "steps": [[]] ] ]] ]] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://api.islo.dev/jobs/name/validate")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "POST" request.allHTTPHeaderFields = headers request.httpBody = postData as Data let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ```