API reference

Agent device endpoints

The endpoints a self-hosted agent calls with its device token.
POST/v1/agent/poll

Marks the device as seen, returns its current policy and claims the oldest queued job it may run.

Auth
An agent device token, as Authorization: Bearer.
Install an agent

Request body

  • versionstring

    Up to 32 characters.

  • platformstring

    Up to 64 characters.

  • featuresstring[]

    Up to 20 items. Each up to 32 characters.

  • connectedboolean
  • codeFoldersstring[]

    Up to 50 items. Each 1–1,024 characters.

curl -X POST 'https://api.cactive.com.au/v1/agent/poll' \
  -H "Authorization: Bearer $AGENT_DEVICE_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "version": "example",
    "platform": "example",
    "features": [
      "example"
    ]
  }'

Try it isn't offered here: these routes take an agent device's own token.

Response 200

{
  push?: {
    url: string
  }
  policy: {
    capabilities: string[]
    networkMode?: "allowlist" | "full"
    hosts?: string[]
  }
  job: null | {
    jobId: string
    type: "http.batch" | "exec" | "browser.batch" | "pipeline" | "code.session"
    label?: string
    hosts?: string[]
    input: unknown
    uploadUrl: string
  }
  nextPollMs: number
}
POST/v1/agent/jobs/:jobId/complete

Reports a claimed job as done or failed.

Auth
None.

Path parameters

  • jobId

    Job id: an agent job (job_…), under pipelines a pipeline job (pjb_…), or under crm an import or export (cjb_…); under marketing a list import (mkj_…).

Request body

  • status"done" | "failed" | "canceled"required
  • errorstring

    Up to 2,000 characters.

Errors

  • 404Job not found
curl -X POST 'https://api.cactive.com.au/v1/agent/jobs/{jobId}/complete' \
  -H 'Content-Type: application/json' \
  -d '{
    "status": "done"
  }'
Send it from this page with your session or a key.

Response 200

{
  ok: true
}
POST/v1/agent/jobs/:jobId/pipeline

A pipeline job this device claimed: the job's token for the runner, which then talks to /v1/runner like a hosted runner. Only the device holding the claim gets it.

Auth
An agent device token, as Authorization: Bearer.
Install an agent

Path parameters

  • jobId

    Job id: an agent job (job_…), under pipelines a pipeline job (pjb_…), or under crm an import or export (cjb_…); under marketing a list import (mkj_…).

curl -X POST 'https://api.cactive.com.au/v1/agent/jobs/{jobId}/pipeline' \
  -H "Authorization: Bearer $AGENT_DEVICE_TOKEN"

Try it isn't offered here: these routes take an agent device's own token.

Response 200

{
  token: string
  apiUrl: string
}
POST/v1/agent/jobs/:jobId/heartbeat

Sent every 20 s while a job runs: keeps the device online and says whether to stop.

Auth
None.

Path parameters

  • jobId

    Job id: an agent job (job_…), under pipelines a pipeline job (pjb_…), or under crm an import or export (cjb_…); under marketing a list import (mkj_…).

Errors

  • 404Job not found
curl -X POST 'https://api.cactive.com.au/v1/agent/jobs/{jobId}/heartbeat'
Send it from this page with your session or a key.

Response 200

{
  cancel: boolean
}
POST/v1/agent/jobs/:jobId/upload-url

Returns a fresh results upload URL for a job the device is still running.

Auth
An agent device token, as Authorization: Bearer.
Install an agent

Path parameters

  • jobId

    Job id: an agent job (job_…), under pipelines a pipeline job (pjb_…), or under crm an import or export (cjb_…); under marketing a list import (mkj_…).

Errors

  • 404Job not found
curl -X POST 'https://api.cactive.com.au/v1/agent/jobs/{jobId}/upload-url' \
  -H "Authorization: Bearer $AGENT_DEVICE_TOKEN"

Try it isn't offered here: these routes take an agent device's own token.

Response 200

{
  uploadUrl: string
}
POST/v1/agent/code/:jobId/events

A Code mode session's events from the machine running it, in order (seq from 1). Secrets are taken out again; an event sent twice is kept once.

Auth
An agent device token, as Authorization: Bearer.
Install an agent

Path parameters

  • jobId

    Job id: an agent job (job_…), under pipelines a pipeline job (pjb_…), or under crm an import or export (cjb_…); under marketing a list import (mkj_…).

Request body

  • eventsany JSON[]required

    Up to 100 items.

Errors

  • 401Unauthorized
curl -X POST 'https://api.cactive.com.au/v1/agent/code/{jobId}/events' \
  -H "Authorization: Bearer $AGENT_DEVICE_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "events": [
      {}
    ]
  }'

Try it isn't offered here: these routes take an agent device's own token.

Response 200

{
  stored: number
  ok: true
}
POST/v1/agent/code/:jobId/streams

Pieces of a Code mode session's replies and terminal output from the machine running it (at most 64 of 256 KB), kept an hour; a terminal's output has known kinds of keys taken out again.

Auth
An agent device token, as Authorization: Bearer.
Install an agent

Path parameters

  • jobId

    Job id: an agent job (job_…), under pipelines a pipeline job (pjb_…), or under crm an import or export (cjb_…); under marketing a list import (mkj_…).

Request body

  • chunksany JSON[]required

    Up to 64 items.

Errors

  • 401Unauthorized
curl -X POST 'https://api.cactive.com.au/v1/agent/code/{jobId}/streams' \
  -H "Authorization: Bearer $AGENT_DEVICE_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "chunks": [
      {}
    ]
  }'

Try it isn't offered here: these routes take an agent device's own token.

Response 200

{
  stored: number
}
POST/v1/agent/code/:jobId/commands

A Code mode session's commands for the machine after after (their seq). Only the device holding the session's job gets them.

Auth
An agent device token, as Authorization: Bearer.
Install an agent

Path parameters

  • jobId

    Job id: an agent job (job_…), under pipelines a pipeline job (pjb_…), or under crm an import or export (cjb_…); under marketing a list import (mkj_…).

Request body

  • afterintegerrequired

    ≥ 0.

Errors

  • 401Unauthorized
curl -X POST 'https://api.cactive.com.au/v1/agent/code/{jobId}/commands' \
  -H "Authorization: Bearer $AGENT_DEVICE_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "after": 1
  }'

Try it isn't offered here: these routes take an agent device's own token.

Response 200

{
  commands: {
    type: "turn.start"
    text: string
    images?: {
      mime: "image/png" | "image/jpeg" | "image/webp" | "image/gif"
      data: string
    }[]
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "turn.steer"
    text: string
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "turn.interrupt"
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "queue.cancel"
    queued: string
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "session.configure"
    settings: {
      mode?: "ask" | "reads" | "app" | "auto"
      plan?: boolean
      model?: null | string
      effort?: null | "low" | "medium" | "high" | "max"
    }
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "approval.respond"
    requestId: string
    decision: "allow" | "deny"
    always?: boolean
    feedback?: string
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "checkpoint.diff"
    fromTurn: number
    toTurn: number
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "checkpoint.restore"
    turn: number
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "session.stop"
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "files.list"
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "files.read"
    path: string
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "files.write"
    path: string
    content: string
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "changes.diff"
    fromTurn: number
    toTurn?: number
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "changes.revert"
    path: string
    fromTurn: number
    hunk?: string
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "terminal.open"
    cols: number
    rows: number
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "terminal.input"
    terminalId: string
    data: string
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "terminal.resize"
    terminalId: string
    cols: number
    rows: number
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "terminal.close"
    terminalId: string
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "git.status"
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "git.diff"
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "git.branch"
    name: string
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "git.commit"
    message: string
    commandId: string
    seq: number
    at: number
    by: string
  } | {
    type: "git.push"
    commandId: string
    seq: number
    at: number
    by: string
  }[]
}
POST/v1/agent/code/:jobId/model

A model step for a session on Caity's Bedrock provider (docs/caity/code.md → Providers), billed to its person.

Auth
An agent device token, as Authorization: Bearer.
Install an agent

Path parameters

  • jobId

    Job id: an agent job (job_…), under pipelines a pipeline job (pjb_…), or under crm an import or export (cjb_…); under marketing a list import (mkj_…).

Errors

  • 401Unauthorized
  • 413The step is too large: trim older tool results.
curl -X POST 'https://api.cactive.com.au/v1/agent/code/{jobId}/model' \
  -H "Authorization: Bearer $AGENT_DEVICE_TOKEN"

Try it isn't offered here: these routes take an agent device's own token.

Response 200

{
  [key: string]: unknown
}
POST/v1/agent/code/:jobId/checkout

A cloud session's build: its repository's git URL and a short credential (pull, push its work branch only).

Auth
None.

Path parameters

  • jobId

    Job id: an agent job (job_…), under pipelines a pipeline job (pjb_…), or under crm an import or export (cjb_…); under marketing a list import (mkj_…).

curl -X POST 'https://api.cactive.com.au/v1/agent/code/{jobId}/checkout'
Send it from this page with your session or a key.

Response 200

{
  session: {
    sessionId: string
    provider: string
    model: null | string
    mode: string
    title: null | string
    deadline: number
    stopped: boolean
  }
  repo: {
    url: string
    authorization: string
    name: string
    branch: string
    workBranch: string
  }
  author: {
    name: string
    email: string
  }
}
POST/v1/agent/code/:jobId/finish

A cloud session's build pushed its work: the pull request opens and the session ends.

Auth
None.

Path parameters

  • jobId

    Job id: an agent job (job_…), under pipelines a pipeline job (pjb_…), or under crm an import or export (cjb_…); under marketing a list import (mkj_…).

curl -X POST 'https://api.cactive.com.au/v1/agent/code/{jobId}/finish'
Send it from this page with your session or a key.

Response 200

{
  error?: string
  pullRequest: null | {
    number: number
    url: string
  }
}
POST/v1/agent/network-requests

Asks for access to a host outside the device's allowlist. Shows up in Cloud → Agents.

Auth
An agent device token, as Authorization: Bearer.
Install an agent

Request body

  • hoststringrequired

    3–253 characters.

  • reasonstring

    Up to 500 characters.

curl -X POST 'https://api.cactive.com.au/v1/agent/network-requests' \
  -H "Authorization: Bearer $AGENT_DEVICE_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "host": "example"
  }'

Try it isn't offered here: these routes take an agent device's own token.

Response 200

{
  ok: true
}