API reference
Runner
Agent task execution: catalogs, jobs and execution permissions.
- Operations
- 7
- Base path
https://os.one.ml/api/v1/runner- Scopes
runner:readrunner:write- API keys
- 7 not yet tested
- SDK
genesis.call('runner_getCatalog', …)· helpers undergenesis.runner- MCP
- 7 tools
Operations
| Operation | Endpoint | API key |
|---|---|---|
| Get authorized Runner workspaces and execution routes | GET/catalog | — |
| List the newest 100 Runner jobs for the verified principal | GET/jobs | — |
| Start a bounded Runner task with an idempotency key | POST/jobs | — |
| Read an authoritative Runner job snapshot | GET/jobs/{jobId} | — |
| Request cancellation of a Runner job | POST/jobs/{jobId}/cancel | — |
| Read an ordered page of Runner job events | GET/jobs/{jobId}/events | — |
| Retrieve the verified provider result for a completed Runner task | GET/jobs/{jobId}/result | — |
Catalog
Get authorized Runner workspaces and execution routes
GET/v1/runner/catalog
Responses
- 200Authorized catalog; unbound routes cannot execute
Response fields
workspacesobject[]requiredworkspaces[].[].keyobjectrequiredworkspaces[].[].labelstringrequiredmin length 1 · max length 160
routesobject[]requiredroutes[].[].routeIdobjectrequiredroutes[].[].kind"external-harness" | "internal-model"requiredroutes[].[].namestringrequiredmin length 1 · max length 160
routes[].[].viastringrequiredmax length 160
routes[].[].state"synthetic" | "bound" | "unbound"requiredroutes[].[].defaultbooleanrequired
- 4xx 5xxThe error envelope.
curl "https://os.one.ml/api/v1/runner/catalog" \
-H "Authorization: Bearer $GENESIS_API_KEY"import { Genesis } from '@lifesi/genesis'
const genesis = new Genesis({ apiKey: process.env.GENESIS_API_KEY })
const result = await genesis.call('runner_getCatalog'){
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "runner_getCatalog",
"arguments": {}
}
}Jobs
List the newest 100 Runner jobs for the verified principal
GET/v1/runner/jobs
Responses
- 200Newest jobs first
Response fields
jobsobject[]requiredjobs[].[].jobIdobjectrequiredjobs[].[].sessionIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
jobs[].[].attemptIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
jobs[].[].executionobject | nullrequiredjobs[].[].cleanupPendingbooleanrequiredjobs[].[].taskobjectrequiredjobs[].[].task.idstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
jobs[].[].task.textstringrequiredmin length 1 · max length 32768 · pattern \S
jobs[].[].task.metaobjectOptional bounded JSON. The entire start input has depth <= 6, <= 256 nodes, <= 65536 total string/key characters, <= 64 items per array and <= 32 keys per object; functions, accessors, cycles and non-plain values are rejected.
jobs[].[].workspaceRefstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
jobs[].[].executionRefobjectrequiredjobs[].[].executionRef.kind"external-harness" | "internal-model"requiredjobs[].[].executionRef.routeIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
jobs[].[].limitsobjectrequiredjobs[].[].limits.maxDurationMsintegerrequiredmin 1 · max 86400000
jobs[].[].limits.maxOutputBytesintegerrequiredmin 1 · max 67108864
jobs[].[].limits.maxEventsintegermin 1 · max 1000 · default 200
jobs[].[].status"queued" | "running" | "cancel_requested" | "completed" | "failed" | "cancelled"requiredjobs[].[].availabilityobjectrequiredjobs[].[].availability.state"synthetic" | "bound" | "unbound"requiredjobs[].[].availability.kind"external-harness" | "internal-model"requiredjobs[].[].availability.routeIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
jobs[].[].availability.reasonstring | nullrequiredmax length 200
jobs[].[].lastSeqintegerrequiredmin 0
jobs[].[].eventsobject[]requiredjobs[].[].events[].[].jobIdobjectrequiredjobs[].[].events[].[].sessionIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
jobs[].[].events[].[].attemptIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
jobs[].[].events[].[].seqintegerrequiredmin 1
jobs[].[].events[].[].type"status" | "output" | "chat" | "artifact" | "error" | "result" | "execution"requiredjobs[].[].events[].[].timestampintegerrequiredjobs[].[].events[].[].payloadobjectrequiredBounded event data; see runner/task-client/v0
jobs[].[].resultobject | nullrequiredjobs[].[].errorobject | nullrequired
- 4xx 5xxThe error envelope.
curl "https://os.one.ml/api/v1/runner/jobs" \
-H "Authorization: Bearer $GENESIS_API_KEY"import { Genesis } from '@lifesi/genesis'
const genesis = new Genesis({ apiKey: process.env.GENESIS_API_KEY })
const result = await genesis.call('runner_listJobs'){
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "runner_listJobs",
"arguments": {}
}
}Start a bounded Runner task with an idempotency key
POST/v1/runner/jobs
Use workspace and route references from the authorized catalog. Reusing a key with the same input returns the existing job; changed input returns 409. A bound route is required for real execution.
Request body application/json
taskobjectrequiredtask.idstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
task.textstringrequiredmin length 1 · max length 32768 · pattern \S
task.metaobjectOptional bounded JSON. The entire start input has depth <= 6, <= 256 nodes, <= 65536 total string/key characters, <= 64 items per array and <= 32 keys per object; functions, accessors, cycles and non-plain values are rejected.
workspaceRefobjectrequiredAuthorized catalog workspace key; never a filesystem path
executionRefobjectrequiredexecutionRef.kind"external-harness" | "internal-model"requiredexecutionRef.routeIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
limitsobjectrequiredlimits.maxDurationMsintegerrequiredmin 1 · max 86400000
limits.maxOutputBytesintegerrequiredmin 1 · max 67108864
limits.maxEventsintegermin 1 · max 1000 · default 200
idempotencyKeystringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
Responses
- 201Durable job accepted; acceptance is not task completion
Response fields
jobIdobjectrequiredsnapshotobjectrequiredsnapshot.jobIdobjectrequiredsnapshot.sessionIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.attemptIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.executionobject | nullrequiredsnapshot.cleanupPendingbooleanrequiredsnapshot.taskobjectrequiredsnapshot.task.idstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.task.textstringrequiredmin length 1 · max length 32768 · pattern \S
snapshot.task.metaobjectOptional bounded JSON. The entire start input has depth <= 6, <= 256 nodes, <= 65536 total string/key characters, <= 64 items per array and <= 32 keys per object; functions, accessors, cycles and non-plain values are rejected.
snapshot.workspaceRefstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.executionRefobjectrequiredsnapshot.executionRef.kind"external-harness" | "internal-model"requiredsnapshot.executionRef.routeIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.limitsobjectrequiredsnapshot.limits.maxDurationMsintegerrequiredmin 1 · max 86400000
snapshot.limits.maxOutputBytesintegerrequiredmin 1 · max 67108864
snapshot.limits.maxEventsintegermin 1 · max 1000 · default 200
snapshot.status"queued" | "running" | "cancel_requested" | "completed" | "failed" | "cancelled"requiredsnapshot.availabilityobjectrequiredsnapshot.availability.state"synthetic" | "bound" | "unbound"requiredsnapshot.availability.kind"external-harness" | "internal-model"requiredsnapshot.availability.routeIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.availability.reasonstring | nullrequiredmax length 200
snapshot.lastSeqintegerrequiredmin 0
snapshot.eventsobject[]requiredsnapshot.events[].[].jobIdobjectrequiredsnapshot.events[].[].sessionIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.events[].[].attemptIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.events[].[].seqintegerrequiredmin 1
snapshot.events[].[].type"status" | "output" | "chat" | "artifact" | "error" | "result" | "execution"requiredsnapshot.events[].[].timestampintegerrequiredsnapshot.events[].[].payloadobjectrequiredBounded event data; see runner/task-client/v0
snapshot.resultobject | nullrequiredsnapshot.errorobject | nullrequired
- 4xx 5xxThe error envelope.
curl -X POST "https://os.one.ml/api/v1/runner/jobs" \
-H "Authorization: Bearer $GENESIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"task": {
"id": "string",
"text": "string"
},
"workspaceRef": {},
"executionRef": {
"kind": "external-harness",
"routeId": "string"
},
"limits": {
"maxDurationMs": 1,
"maxOutputBytes": 1
},
"idempotencyKey": "string"
}'import { Genesis } from '@lifesi/genesis'
const genesis = new Genesis({ apiKey: process.env.GENESIS_API_KEY })
const result = await genesis.call('runner_startJob', {
body: {
task: {
id: 'string',
text: 'string',
},
workspaceRef: {},
executionRef: {
kind: 'external-harness',
routeId: 'string',
},
limits: {
maxDurationMs: 1,
maxOutputBytes: 1,
},
idempotencyKey: 'string',
},
}){
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "runner_startJob",
"arguments": {
"body": {
"task": {
"id": "string",
"text": "string"
},
"workspaceRef": {},
"executionRef": {
"kind": "external-harness",
"routeId": "string"
},
"limits": {
"maxDurationMs": 1,
"maxOutputBytes": 1
},
"idempotencyKey": "string"
}
}
}
}Read an authoritative Runner job snapshot
GET/v1/runner/jobs/{jobId}
A job outside the verified org and subject is 404, including a valid ID belonging to another principal.
Parameters
jobIdpath · stringrequired
Responses
- 200Current authoritative snapshot
Response fields
snapshotobjectrequiredsnapshot.jobIdobjectrequiredsnapshot.sessionIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.attemptIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.executionobject | nullrequiredsnapshot.cleanupPendingbooleanrequiredsnapshot.taskobjectrequiredsnapshot.task.idstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.task.textstringrequiredmin length 1 · max length 32768 · pattern \S
snapshot.task.metaobjectOptional bounded JSON. The entire start input has depth <= 6, <= 256 nodes, <= 65536 total string/key characters, <= 64 items per array and <= 32 keys per object; functions, accessors, cycles and non-plain values are rejected.
snapshot.workspaceRefstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.executionRefobjectrequiredsnapshot.executionRef.kind"external-harness" | "internal-model"requiredsnapshot.executionRef.routeIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.limitsobjectrequiredsnapshot.limits.maxDurationMsintegerrequiredmin 1 · max 86400000
snapshot.limits.maxOutputBytesintegerrequiredmin 1 · max 67108864
snapshot.limits.maxEventsintegermin 1 · max 1000 · default 200
snapshot.status"queued" | "running" | "cancel_requested" | "completed" | "failed" | "cancelled"requiredsnapshot.availabilityobjectrequiredsnapshot.availability.state"synthetic" | "bound" | "unbound"requiredsnapshot.availability.kind"external-harness" | "internal-model"requiredsnapshot.availability.routeIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.availability.reasonstring | nullrequiredmax length 200
snapshot.lastSeqintegerrequiredmin 0
snapshot.eventsobject[]requiredsnapshot.events[].[].jobIdobjectrequiredsnapshot.events[].[].sessionIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.events[].[].attemptIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.events[].[].seqintegerrequiredmin 1
snapshot.events[].[].type"status" | "output" | "chat" | "artifact" | "error" | "result" | "execution"requiredsnapshot.events[].[].timestampintegerrequiredsnapshot.events[].[].payloadobjectrequiredBounded event data; see runner/task-client/v0
snapshot.resultobject | nullrequiredsnapshot.errorobject | nullrequired
- 4xx 5xxThe error envelope.
curl "https://os.one.ml/api/v1/runner/jobs/$JOB_ID" \
-H "Authorization: Bearer $GENESIS_API_KEY"import { Genesis } from '@lifesi/genesis'
const genesis = new Genesis({ apiKey: process.env.GENESIS_API_KEY })
const result = await genesis.call('runner_getJob', {
jobId: '<jobId>',
}){
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "runner_getJob",
"arguments": {
"jobId": "<jobId>"
}
}
}Cancel
Request cancellation of a Runner job
POST/v1/runner/jobs/{jobId}/cancel
Send an empty request body. Cancellation is a request; read status and cleanupPending until the authoritative outcome settles. Repeated cancellation returns the current snapshot.
Parameters
jobIdpath · stringrequired
Responses
- 200Current authoritative snapshot
Response fields
snapshotobjectrequiredsnapshot.jobIdobjectrequiredsnapshot.sessionIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.attemptIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.executionobject | nullrequiredsnapshot.cleanupPendingbooleanrequiredsnapshot.taskobjectrequiredsnapshot.task.idstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.task.textstringrequiredmin length 1 · max length 32768 · pattern \S
snapshot.task.metaobjectOptional bounded JSON. The entire start input has depth <= 6, <= 256 nodes, <= 65536 total string/key characters, <= 64 items per array and <= 32 keys per object; functions, accessors, cycles and non-plain values are rejected.
snapshot.workspaceRefstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.executionRefobjectrequiredsnapshot.executionRef.kind"external-harness" | "internal-model"requiredsnapshot.executionRef.routeIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.limitsobjectrequiredsnapshot.limits.maxDurationMsintegerrequiredmin 1 · max 86400000
snapshot.limits.maxOutputBytesintegerrequiredmin 1 · max 67108864
snapshot.limits.maxEventsintegermin 1 · max 1000 · default 200
snapshot.status"queued" | "running" | "cancel_requested" | "completed" | "failed" | "cancelled"requiredsnapshot.availabilityobjectrequiredsnapshot.availability.state"synthetic" | "bound" | "unbound"requiredsnapshot.availability.kind"external-harness" | "internal-model"requiredsnapshot.availability.routeIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.availability.reasonstring | nullrequiredmax length 200
snapshot.lastSeqintegerrequiredmin 0
snapshot.eventsobject[]requiredsnapshot.events[].[].jobIdobjectrequiredsnapshot.events[].[].sessionIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.events[].[].attemptIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
snapshot.events[].[].seqintegerrequiredmin 1
snapshot.events[].[].type"status" | "output" | "chat" | "artifact" | "error" | "result" | "execution"requiredsnapshot.events[].[].timestampintegerrequiredsnapshot.events[].[].payloadobjectrequiredBounded event data; see runner/task-client/v0
snapshot.resultobject | nullrequiredsnapshot.errorobject | nullrequired
- 4xx 5xxThe error envelope.
curl -X POST "https://os.one.ml/api/v1/runner/jobs/$JOB_ID/cancel" \
-H "Authorization: Bearer $GENESIS_API_KEY"import { Genesis } from '@lifesi/genesis'
const genesis = new Genesis({ apiKey: process.env.GENESIS_API_KEY })
const result = await genesis.call('runner_cancelJob', {
jobId: '<jobId>',
}){
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "runner_cancelJob",
"arguments": {
"jobId": "<jobId>"
}
}
}Events
Read an ordered page of Runner job events
GET/v1/runner/jobs/{jobId}/events
Parameters
jobIdpath · stringrequiredafterSeqquery · integerExclusive event cursor. Use nextAfterSeq for the next page.
Responses
- 200At most 200 events; drain pages while hasMore is true
Response fields
eventsobject[]requiredevents[].[].jobIdobjectrequiredevents[].[].sessionIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
events[].[].attemptIdstringrequiredmin length 1 · max length 128 · pattern ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
events[].[].seqintegerrequiredmin 1
events[].[].type"status" | "output" | "chat" | "artifact" | "error" | "result" | "execution"requiredevents[].[].timestampintegerrequiredevents[].[].payloadobjectrequiredBounded event data; see runner/task-client/v0
nextAfterSeqintegerrequiredmin 0 · max 9007199254740991
hasMorebooleanrequired
- 4xx 5xxThe error envelope.
curl "https://os.one.ml/api/v1/runner/jobs/$JOB_ID/events" \
-H "Authorization: Bearer $GENESIS_API_KEY"import { Genesis } from '@lifesi/genesis'
const genesis = new Genesis({ apiKey: process.env.GENESIS_API_KEY })
const result = await genesis.call('runner_getJobEvents', {
jobId: '<jobId>',
}){
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "runner_getJobEvents",
"arguments": {
"jobId": "<jobId>"
}
}
}Result
Retrieve the verified provider result for a completed Runner task
GET/v1/runner/jobs/{jobId}/result
Returns 409 E_RESULT_NOT_READY until authoritative Fleets success, a confirmed cleanup receipt and a resolvable result reference exist. The server verifies the digest and rejects secret-bearing result content.
Parameters
jobIdpath · stringrequired
Responses
- 200Bounded provider deliverable
Response fields
resultobjectrequiredresult.schema"runner/provider-result/v1"requiredresult.provider"flocks" | "fleets"requiredresult.providerExecutionIdobjectrequiredresult.resultRefobjectrequiredresult.resultRef.refobjectrequiredresult.resultRef.kind"diff" | "test_report" | "artifact" | "result"requiredresult.digeststringrequiredpattern ^sha256:[0-9a-f]{64}$
result.contentType"application/vnd.life.henry-deliverable+json"requiredresult.encoding"utf8"requiredresult.contentstringrequired<= 8192 UTF-8 bytes of digest-verified JSON; no credentials max length 8192
- 4xx 5xxThe error envelope.
curl "https://os.one.ml/api/v1/runner/jobs/$JOB_ID/result" \
-H "Authorization: Bearer $GENESIS_API_KEY"import { Genesis } from '@lifesi/genesis'
const genesis = new Genesis({ apiKey: process.env.GENESIS_API_KEY })
const result = await genesis.call('runner_getJobResult', {
jobId: '<jobId>',
}){
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "runner_getJobResult",
"arguments": {
"jobId": "<jobId>"
}
}
}One Superintelligence, Inc. · Built from Genesis 0.1.12 and the live gateway on 2026-10-20. Support