ToolsRun tools.run@1

Generated at from openvibe-contracts v0.33.0 and openvibe-sdk v0.5.0.

Version
1.0.0
Owner
tools
Visibility
public
Status
active
Compatibility
backward
Decision
ADR-027
Schema
https://openvibe.network/contracts/tools/run.v1.json

The answer of POST /api/v1/tools/{id}/run (tools.run-request@1; ADR-027). Finished: { state: succeeded, tool, result, took_ms } or { state: failed|cancelled, tool, error, took_ms }, with job set when the tool ran as a job. Not finished within wait_ms: { state: queued|running, tool, job, location }, sent with 202 and a Location header; follow the job there (GET, its events, its files; tools.job@1). result carries data (kind json, matching the descriptor's output schema), text (kind text) or files (kind file or files: the job's result files, downloaded from their url). took_ms runs from the request to the answer for an inline run, and from created_at to finished_at for a job. error is problem+json from the tool: tools.job.failed, tools.job.timeout, tools.job.cancelled, or a code the tool chose (tools.…). A request refused before the tool ran is a problem+json answer, not a run.

Fields

This schema has no named fields.

Examples

From the contract's own test fixtures: valid ones validate, rejected ones must fail.

Valid: failed-job
{
  "state": "failed",
  "tool": "mp3",
  "error": {
    "type": "https://openvibe.network/problems/tools.job.timeout",
    "title": "Gateway Timeout",
    "status": 504,
    "code": "tools.job.timeout",
    "detail": "The job ran longer than 900 s",
    "error": "The job ran longer than 900 s"
  },
  "took_ms": 901000,
  "job": {
    "id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
    "object": "tools.job",
    "service": "audio",
    "type": "audio.process",
    "type_version": 1,
    "state": "failed",
    "progress": {
      "percent": 42.5,
      "message": "Encoding"
    },
    "attempts": 1,
    "max_attempts": 3,
    "cancel_requested": false,
    "created_at": "2026-09-23T09:00:00.000Z",
    "started_at": "2026-09-23T09:00:01.000Z",
    "finished_at": "2026-09-23T09:15:01.000Z",
    "expires_at": "2026-09-23T10:00:00.000Z",
    "result": null,
    "error": {
      "type": "https://openvibe.network/problems/tools.job.timeout",
      "title": "Gateway Timeout",
      "status": 504,
      "code": "tools.job.timeout",
      "detail": "The job ran longer than 900 s",
      "error": "The job ran longer than 900 s"
    },
    "retryable": true,
    "retry_of": null,
    "retried_by": null,
    "references": [],
    "links": {
      "self": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
      "events": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ/events",
      "cancel": null,
      "retry": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ/retry",
      "retried_by": null
    }
  }
}
Valid: queued
{
  "state": "queued",
  "tool": "png",
  "job": {
    "id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
    "object": "tools.job",
    "service": "img",
    "type": "img.process",
    "type_version": 1,
    "state": "queued",
    "progress": {
      "percent": null,
      "message": null
    },
    "attempts": 0,
    "max_attempts": 3,
    "cancel_requested": false,
    "created_at": "2026-09-23T09:00:00.000Z",
    "started_at": null,
    "finished_at": null,
    "expires_at": "2026-09-23T10:00:00.000Z",
    "result": null,
    "error": null,
    "retryable": false,
    "retry_of": null,
    "retried_by": null,
    "references": [],
    "links": {
      "self": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
      "events": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ/events",
      "cancel": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
      "retry": null,
      "retried_by": null
    }
  },
  "location": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ"
}
Valid: running-absolute-location
{
  "state": "running",
  "tool": "png",
  "job": {
    "id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
    "object": "tools.job",
    "service": "img",
    "type": "img.process",
    "type_version": 1,
    "state": "running",
    "progress": {
      "percent": 12,
      "message": "Converting"
    },
    "attempts": 1,
    "max_attempts": 3,
    "cancel_requested": false,
    "created_at": "2026-09-23T09:00:00.000Z",
    "started_at": "2026-09-23T09:00:01.000Z",
    "finished_at": null,
    "expires_at": "2026-09-23T10:00:00.000Z",
    "result": null,
    "error": null,
    "retryable": false,
    "retry_of": null,
    "retried_by": null,
    "references": [],
    "links": {
      "self": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
      "events": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ/events",
      "cancel": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
      "retry": null,
      "retried_by": null
    }
  },
  "location": "https://openvibe.tools/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ"
}
Valid: succeeded-inline-json
{
  "state": "succeeded",
  "tool": "dns",
  "result": {
    "data": {
      "name": "openvibe.tools",
      "records": {
        "A": [
          "203.0.113.7"
        ]
      }
    }
  },
  "took_ms": 38
}
Valid: succeeded-inline-text
{
  "state": "succeeded",
  "tool": "jsonminify",
  "result": {
    "text": "{\"a\":1}"
  },
  "took_ms": 2,
  "job": null
}
Valid: succeeded-job
{
  "state": "succeeded",
  "tool": "png",
  "result": {
    "files": [
      {
        "name": "photo.png",
        "mime": "image/png",
        "size": 90112,
        "sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
        "storage": "media",
        "media": {
          "media_id": "med_01JAB2C3D4E5F6G7H8J9K0MNPS",
          "role": "output",
          "namespace": "tools",
          "size_bytes": 90112,
          "content_hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
          "mime_type": "image/png",
          "status": "ready"
        },
        "url": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ/files/0"
      }
    ],
    "data": {
      "width": 1024,
      "height": 768
    }
  },
  "took_ms": 4000,
  "job": {
    "id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
    "object": "tools.job",
    "service": "img",
    "type": "img.process",
    "type_version": 1,
    "state": "succeeded",
    "progress": {
      "percent": 100,
      "message": "Done"
    },
    "attempts": 1,
    "max_attempts": 3,
    "cancel_requested": false,
    "created_at": "2026-09-23T09:00:00.000Z",
    "started_at": "2026-09-23T09:00:01.000Z",
    "finished_at": "2026-09-23T09:00:04.000Z",
    "expires_at": null,
    "result": {
      "files": [
        {
          "name": "photo.png",
          "mime": "image/png",
          "size": 90112,
          "sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
          "storage": "media",
          "media": {
            "media_id": "med_01JAB2C3D4E5F6G7H8J9K0MNPS",
            "role": "output",
            "namespace": "tools",
            "size_bytes": 90112,
            "content_hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
            "mime_type": "image/png",
            "status": "ready"
          },
          "url": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ/files/0"
        }
      ],
      "data": {
        "width": 1024,
        "height": 768
      }
    },
    "error": null,
    "retryable": false,
    "retry_of": null,
    "retried_by": null,
    "references": [
      {
        "ref": "community:paste:p_123",
        "created_at": "2026-09-23T09:05:00.000Z"
      }
    ],
    "links": {
      "self": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
      "events": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ/events",
      "cancel": null,
      "retry": null,
      "retried_by": null
    },
    "tool": "png"
  }
}
Rejected: failed-without-error
{
  "state": "failed",
  "tool": "dns",
  "took_ms": 3
}
Rejected: location-elsewhere
{
  "state": "queued",
  "tool": "png",
  "job": {
    "id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
    "object": "tools.job",
    "service": "img",
    "type": "img.process",
    "type_version": 1,
    "state": "queued",
    "progress": {
      "percent": null,
      "message": null
    },
    "attempts": 0,
    "max_attempts": 3,
    "cancel_requested": false,
    "created_at": "2026-09-23T09:00:00.000Z",
    "started_at": null,
    "finished_at": null,
    "expires_at": "2026-09-23T10:00:00.000Z",
    "result": null,
    "error": null,
    "retryable": false,
    "retry_of": null,
    "retried_by": null,
    "references": [],
    "links": {
      "self": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
      "events": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ/events",
      "cancel": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
      "retry": null,
      "retried_by": null
    }
  },
  "location": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPR/files/0"
}
Rejected: queued-without-location
{
  "state": "queued",
  "tool": "png",
  "job": {
    "id": "job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
    "object": "tools.job",
    "service": "img",
    "type": "img.process",
    "type_version": 1,
    "state": "queued",
    "progress": {
      "percent": null,
      "message": null
    },
    "attempts": 0,
    "max_attempts": 3,
    "cancel_requested": false,
    "created_at": "2026-09-23T09:00:00.000Z",
    "started_at": null,
    "finished_at": null,
    "expires_at": "2026-09-23T10:00:00.000Z",
    "result": null,
    "error": null,
    "retryable": false,
    "retry_of": null,
    "retried_by": null,
    "references": [],
    "links": {
      "self": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
      "events": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ/events",
      "cancel": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ",
      "retry": null,
      "retried_by": null
    }
  }
}
Rejected: result-with-unknown-member
{
  "state": "succeeded",
  "tool": "dns",
  "result": {
    "html": "<b>x</b>"
  },
  "took_ms": 3
}
Rejected: running-without-job
{
  "state": "running",
  "tool": "png",
  "location": "/api/v1/jobs/job_01JAB2C3D4E5F6G7H8J9K0MNPQ"
}
Rejected: succeeded-with-error
{
  "state": "succeeded",
  "tool": "dns",
  "result": {},
  "error": {
    "type": "https://openvibe.network/problems/tools.job.timeout",
    "title": "Gateway Timeout",
    "status": 504,
    "code": "tools.job.timeout",
    "detail": "The job ran longer than 900 s",
    "error": "The job ran longer than 900 s"
  },
  "took_ms": 3
}

Validate

const contracts = require('openvibe-contracts');
contracts.validate('tools.run@1', value);   // { valid, errors: [{ path, message }] }