API reference

One origin, one namespace

Everything lives under https://api.agentsky.dev/v1 with a Bearer token. Management is request/response; conversation is a 202 send plus one standing SSE stream.

The reference below is rendered from the machine-readable spec — the same schemas the routes validate with: https://api.agentsky.dev/v1/openapi.json.

Authentication

Every request sends Authorization: Bearer ast_…. Tokens are minted in Developer → API keys or by sky auth login — never by other tokens. Scopes are ordered read ⊂ write ⊂ admin; a token is personal (acts as you everywhere) or scoped to one universe. Pass X-Universe: <slug> to act inside a non-personal universe.

Errors

Every non-2xx body is { "error": { "code", "message" } }:

HTTPcodeWhen
400invalid_requestmalformed JSON / validation failure
400invalid_memoryinvalid memory operation or memory limit reached
401invalid_tokenmissing, unknown, revoked, or expired token
402insufficient_creditsthe spend gate blocked the turn
403insufficient_scope · universe_mismatch · forbiddenscope too low; X-Universe conflicts with a scoped token; agent has no API binding
403personal_memory_onlycaller or universe is not eligible for personal memory
404not_foundunknown agent/universe (also masks unauthorized ids)
409conflictversion conflict
409memory_conflictmemory changed; read the current version before writing
422invalid_specvalid JSON, invalid domain rules (e.g. llm not allowed for type)
429rate_limited100,000 requests/min per token exceeded — honor Retry-After

Billing

GET/billingread

Read credit balance and card availability

Returns the caller's credit balance and whether a card is on file. No card details are returned.

Response · 200

balance_usdnumberrequired
card_on_filebooleanrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/billing' \
  -H "Authorization: Bearer ast_..."

Start saving a payment card

Returns a hosted card form URL to open in a browser. Saving the card does not charge it; auto top-up can charge it when a later session starts below the configured threshold. No request body is required.

Response · 200

urlstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/billing/card-setup \
  -H "Authorization: Bearer ast_..."

Credit campaigns

List live and recent credit campaigns

Response · 200

Campaign result

campaignsstring[]required

Response · 400

Invalid request

Response · 401

Authentication required

Response · 403

Admin token scope and administrator allowlist membership required

Response · 404

Unknown campaign

Response · 503

Campaign migrations required

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/credit-campaigns' \
  -H "Authorization: Bearer ast_..."

Issue a public credit link or personal email invitations

Only allowlisted administrators can use these operations. Use one UUID requestId per campaign and reuse the identical body after timeouts. Personal emails are deduplicated and each gets a distinct, email-bound single-use code. Existing verified, unbanned recipients are credited immediately. sendEmail explicitly authorizes product email. Code creation is atomic; delivery/credit failures are per recipient. Retry the same request for retry_needed credit results; never change requestId just to retry. Email status sent means SES accepted, not inbox delivery. Sending/uncertain attempts are not automatically resent; use the returned personal link for manual delivery. Responses contain bearer codes: keep private. A different body with the same requestId returns 409.

Body · application/json

requestIdstringrequired

pattern ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$

amountUsdnumberrequired
expiresInDaysintegerrequired
notestringrequired

max length 200

audienceobjectrequired
▸ Show child attributes
option 1object
▸ Show child attributes
kind"anyone"required
slotsintegerrequired
option 2object
▸ Show child attributes
kind"recipients"required
emailsstring[]required

pattern ^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$

sendEmailboolean

default: false

Response · 201

Campaign result

campaignIdstringrequired
recipientsobject[]required
▸ Show child attributes
idstringrequired
emailstring | nullrequired
codestringrequired
urlstringrequired
claimstringrequired
emailStatusstringrequired
notifiedAtstring | nullrequired

Response · 400

Invalid request

Response · 401

Authentication required

Response · 403

Admin token scope and administrator allowlist membership required

Response · 404

Unknown campaign

Response · 409

requestId reused with different settings

Response · 415

Content-Type must be application/json

Response · 503

Campaign migrations required

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/credit-campaigns \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"requestId":"40a9ae2a-4ea5-4a50-987e-d8b3c99c96f0","amountUsd":20,"expiresInDays":30,"note":"Launch invitations","audience":{"kind":"recipients","emails":["recipient@example.com"]},"sendEmail":true}'

Read claim, email and recipient usage results

Returns grantedUsd, claimed, activeRecipients, agentUsageUsd and individual link states. Usage is agent/runtime ledger spend since first claim, excludes API gateway and is not attribution to the gifted credit pool.

Path parameters

idstringrequired

Response · 200

Campaign result

campaignIdstringrequired
notestringrequired
amountUsdnumberrequired
maxRedemptionsintegerrequired
claimedintegerrequired
grantedUsdnumberrequired
activeRecipientsintegerrequired
agentUsageUsdnumberrequired
usageBasisstringrequired
linksobject[]required
▸ Show child attributes
idstringrequired
emailstring | nullrequired
stateenum<string>required

"active" · "disabled" · "expired" · "exhausted"

claimedintegerrequired
emailStatusstringrequired
expiresAtstringrequired
notifiedAtstring | nullrequired
urlstring | nullrequired

Response · 400

Invalid request

Response · 401

Authentication required

Response · 403

Admin token scope and administrator allowlist membership required

Response · 404

Unknown campaign

Response · 503

Campaign migrations required

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/credit-campaigns/sess_cmtb7q2j' \
  -H "Authorization: Bearer ast_..."

Disable all unclaimed campaign codes

Already granted credit stays in recipients' accounts.

Path parameters

idstringrequired

Response · 200

Campaign result

disabledintegerrequired

Response · 400

Invalid request

Response · 401

Authentication required

Response · 403

Admin token scope and administrator allowlist membership required

Response · 404

Unknown campaign

Response · 503

Campaign migrations required

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/credit-campaigns/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."

Memory stores

List memory stores

Query parameters

include_archivedboolean
afterstring
limitinteger

Response · 200

List of memory stores

memory_storesobject[]required
▸ Show child attributes
idstringrequired

memstore_…

objectenum<string>required

"memory_store"

namestringrequired
descriptionstringrequired
attach_by_defaultenum<string>required

"none" · "read_only"

created_atstringrequired
updated_atstringrequired
archived_atstring | nullrequired
has_morebooleanrequired
next_cursorstring

Opaque cursor; pass as `after` on the next request.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/memory_stores' \
  -H "Authorization: Bearer ast_..."

Create a memory store

Body · application/json

namestringrequired

max length 255

descriptionstring

max length 4096

attach_by_defaultenum<string>

"none" · "read_only"

Response · 201

Created memory store

memory_storeobjectrequired
▸ Show child attributes
idstringrequired

memstore_…

objectenum<string>required

"memory_store"

namestringrequired
descriptionstringrequired
attach_by_defaultenum<string>required

"none" · "read_only"

created_atstringrequired
updated_atstringrequired
archived_atstring | nullrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/memory_stores \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"name":"team-notes","description":"Shared team knowledge base"}'

Get a memory store

Path parameters

store_idstringrequired

The memory store id (memstore_…)

Response · 200

Memory store

memory_storeobjectrequired
▸ Show child attributes
idstringrequired

memstore_…

objectenum<string>required

"memory_store"

namestringrequired
descriptionstringrequired
attach_by_defaultenum<string>required

"none" · "read_only"

created_atstringrequired
updated_atstringrequired
archived_atstring | nullrequired

Response · 404

Error — { error: { code, message } }

errorobject
▸ Show child attributes
codestring
messagestring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/memory_stores/memstore_cmtc5q1x' \
  -H "Authorization: Bearer ast_..."

Update a memory store

Path parameters

store_idstringrequired

The memory store id (memstore_…)

Body · application/json

namestring

max length 255

descriptionstring

max length 4096

attach_by_defaultenum<string>

"none" · "read_only"

Response · 200

Updated memory store

memory_storeobjectrequired
▸ Show child attributes
idstringrequired

memstore_…

objectenum<string>required

"memory_store"

namestringrequired
descriptionstringrequired
attach_by_defaultenum<string>required

"none" · "read_only"

created_atstringrequired
updated_atstringrequired
archived_atstring | nullrequired

Response · 404

Error — { error: { code, message } }

errorobject
▸ Show child attributes
codestring
messagestring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/memory_stores/memstore_cmtc5q1x \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"name":"team-notes-v2","description":"Updated description"}'

Delete a memory store

Path parameters

store_idstringrequired

The memory store id (memstore_…)

Response · 204

Deleted

Response · 404

Error — { error: { code, message } }

errorobject
▸ Show child attributes
codestring
messagestring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/memory_stores/memstore_cmtc5q1x \
  -H "Authorization: Bearer ast_..."

Archive a memory store (one-way, idempotent)

Path parameters

store_idstringrequired

The memory store id (memstore_…)

Response · 200

Archived memory store

memory_storeobjectrequired
▸ Show child attributes
idstringrequired

memstore_…

objectenum<string>required

"memory_store"

namestringrequired
descriptionstringrequired
attach_by_defaultenum<string>required

"none" · "read_only"

created_atstringrequired
updated_atstringrequired
archived_atstring | nullrequired

Response · 404

Error — { error: { code, message } }

errorobject
▸ Show child attributes
codestring
messagestring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/memory_stores/memstore_cmtc5q1x/archive \
  -H "Authorization: Bearer ast_..."

List memories in a store

Path parameters

store_idstringrequired

The memory store id (memstore_…)

Query parameters

path_prefixstring

Must end with / (default: /)

depthinteger
afterstring
limitinteger

Response · 200

List of memories

memoriesobject[]required
▸ Show child attributes
option 1object

Memory without content — returned in list responses.

▸ Show child attributes
idstringrequired

mem_…

typeenum<string>required

Discriminator for the memories list union. — "memory"

objectenum<string>required

"memory"

memory_store_idstringrequired
pathstringrequired

Absolute path starting with /

content_sha256stringrequired
content_bytesintegerrequired
created_atstringrequired
updated_atstringrequired
option 2object
▸ Show child attributes
typeenum<string>required

"memory_prefix"

pathstringrequired

Common path prefix ending with /

has_morebooleanrequired
next_cursorstring

Opaque cursor; pass as `after` on the next request.

Response · 404

Error — { error: { code, message } }

errorobject
▸ Show child attributes
codestring
messagestring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/memory_stores/memstore_cmtc5q1x/memories' \
  -H "Authorization: Bearer ast_..."

Create a memory

Path parameters

store_idstringrequired

The memory store id (memstore_…)

Body · application/json

pathstringrequired

Absolute path starting with /

contentstring

max length 102400

Response · 201

Created memory

memoryobjectrequired

Memory with content — returned by single-get, create, and update responses.

▸ Show child attributes
idstringrequired

mem_…

objectenum<string>required

"memory"

memory_store_idstringrequired
pathstringrequired

Absolute path starting with /

contentstringrequired
content_sha256stringrequired
content_bytesintegerrequired
created_atstringrequired
updated_atstringrequired
version_idstringrequired

Response · 409

Error — { error: { code, message } }

errorobject
▸ Show child attributes
codestring
messagestring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/memory_stores/memstore_cmtc5q1x/memories \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"path":"/notes/hello","content":"Hello, world"}'

Get a memory with content

Path parameters

store_idstringrequired

The memory store id (memstore_…)

memory_idstringrequired

The memory id (mem_…)

Response · 200

Memory with content

memoryobjectrequired

Memory with content — returned by single-get, create, and update responses.

▸ Show child attributes
idstringrequired

mem_…

objectenum<string>required

"memory"

memory_store_idstringrequired
pathstringrequired

Absolute path starting with /

contentstringrequired
content_sha256stringrequired
content_bytesintegerrequired
created_atstringrequired
updated_atstringrequired

Response · 404

Error — { error: { code, message } }

errorobject
▸ Show child attributes
codestring
messagestring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/memory_stores/memstore_cmtc5q1x/memories/mem_cmtc5q1y' \
  -H "Authorization: Bearer ast_..."

Update a memory

Path parameters

store_idstringrequired

The memory store id (memstore_…)

memory_idstringrequired

The memory id (mem_…)

Body · application/json

contentstring

max length 102400

pathstring

Rename the memory to this path

preconditionobject
▸ Show child attributes
typeenum<string>required

"content_sha256"

content_sha256stringrequired

Response · 200

Updated memory

memoryobjectrequired

Memory with content — returned by single-get, create, and update responses.

▸ Show child attributes
idstringrequired

mem_…

objectenum<string>required

"memory"

memory_store_idstringrequired
pathstringrequired

Absolute path starting with /

contentstringrequired
content_sha256stringrequired
content_bytesintegerrequired
created_atstringrequired
updated_atstringrequired
version_idstringrequired

Response · 404

Error — { error: { code, message } }

errorobject
▸ Show child attributes
codestring
messagestring

Response · 409

Error — { error: { code, message } }

errorobject
▸ Show child attributes
codestring
messagestring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/memory_stores/memstore_cmtc5q1x/memories/mem_cmtc5q1y \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"content":"Hello, world v2","precondition":{"type":"content_sha256","content_sha256":"b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"}}'

Delete a memory

Path parameters

store_idstringrequired

The memory store id (memstore_…)

memory_idstringrequired

The memory id (mem_…)

Response · 204

Deleted

Response · 404

Error — { error: { code, message } }

errorobject
▸ Show child attributes
codestring
messagestring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/memory_stores/memstore_cmtc5q1x/memories/mem_cmtc5q1y \
  -H "Authorization: Bearer ast_..."

List memory versions for a store

Path parameters

store_idstringrequired

The memory store id (memstore_…)

Query parameters

memory_idstring

Filter to a single memory

afterstring
limitinteger

Response · 200

List of memory versions

memory_versionsobject[]required
▸ Show child attributes
idstringrequired

memver_…

objectenum<string>required

"memory_version"

memory_store_idstringrequired
memory_idstringrequired
pathstringrequired
contentstring | nullrequired

null when redacted

content_sha256string | nullrequired
operationenum<string>required

"create" · "update" · "delete"

actor_typeenum<string>required

"user" · "session"

actor_idstringrequired
redacted_atstring | nullrequired
created_atstringrequired
has_morebooleanrequired
next_cursorstring

Opaque cursor; pass as `after` on the next request.

Response · 404

Error — { error: { code, message } }

errorobject
▸ Show child attributes
codestring
messagestring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/memory_stores/memstore_cmtc5q1x/memory_versions' \
  -H "Authorization: Bearer ast_..."

Get a single memory version

Path parameters

store_idstringrequired

The memory store id (memstore_…)

version_idstringrequired

The memory version id (memver_…)

Response · 200

Memory version

memory_versionobjectrequired
▸ Show child attributes
idstringrequired

memver_…

objectenum<string>required

"memory_version"

memory_store_idstringrequired
memory_idstringrequired
pathstringrequired
contentstring | nullrequired

null when redacted

content_sha256string | nullrequired
operationenum<string>required

"create" · "update" · "delete"

actor_typeenum<string>required

"user" · "session"

actor_idstringrequired
redacted_atstring | nullrequired
created_atstringrequired

Response · 404

Error — { error: { code, message } }

errorobject
▸ Show child attributes
codestring
messagestring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/memory_stores/memstore_cmtc5q1x/memory_versions/memver_cmtc5q1z' \
  -H "Authorization: Bearer ast_..."

Redact the content of a memory version

Path parameters

store_idstringrequired

The memory store id (memstore_…)

version_idstringrequired

The memory version id (memver_…)

Response · 200

Redacted memory version

memory_versionobjectrequired
▸ Show child attributes
idstringrequired

memver_…

objectenum<string>required

"memory_version"

memory_store_idstringrequired
memory_idstringrequired
pathstringrequired
contentstring | nullrequired

null when redacted

content_sha256string | nullrequired
operationenum<string>required

"create" · "update" · "delete"

actor_typeenum<string>required

"user" · "session"

actor_idstringrequired
redacted_atstring | nullrequired
created_atstringrequired

Response · 404

Error — { error: { code, message } }

errorobject
▸ Show child attributes
codestring
messagestring

Response · 409

Error — { error: { code, message } }

errorobject
▸ Show child attributes
codestring
messagestring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/memory_stores/memstore_cmtc5q1x/memory_versions/memver_cmtc5q1z/redact \
  -H "Authorization: Bearer ast_..."

Memory

GET/memoryread

Read your personal cross-session memory

Requires read scope. Only unrestricted owner-facing credentials in the authenticated owner's personal universe are supported; restricted tokens, delegated callers, and team universes return 403.

Response · 200

Saved entries and the opaque version required for the next write.

entriesobject[]required
▸ Show child attributes
indexintegerrequired
textstringrequired
versionstring | nullrequired

Response · 401

Authentication required

Response · 403

insufficient_scope or personal_memory_only: caller or universe is not eligible

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/memory' \
  -H "Authorization: Bearer ast_..."
POST/memorywrite

Save, edit, remove or clear a personal memory

Requires write scope and unrestricted owner-facing credentials in your personal universe. Read GET /memory first and copy its version exactly into expectedVersion, even when entries is empty. The sample uses null for a store before its first write; replace it with the returned version for an existing document. Stale writes return 409; reload and resolve the change instead of overwriting. Entries are limited to 2048 UTF-8 bytes and the complete recall context to 4000 characters. A state-changing clear advances the version; a no-op on an existing document retains it. Clear preserves allocated indexes.

Body · application/json

option 1object
▸ Show child attributes
op"save"required
textstringrequired

max length 8192

expectedVersionstring | nullrequired

max length 128

option 2object
▸ Show child attributes
op"update"required
indexintegerrequired
textstringrequired

max length 8192

expectedVersionstring | nullrequired

max length 128

option 3object
▸ Show child attributes
op"remove"required
indexintegerrequired
expectedVersionstring | nullrequired

max length 128

option 4object
▸ Show child attributes
op"clear"required
expectedVersionstring | nullrequired

max length 128

Response · 200

Saved entries and the opaque version required for the next write.

entriesobject[]required
▸ Show child attributes
indexintegerrequired
textstringrequired
versionstring | nullrequired

Response · 400

invalid_memory: invalid operation or memory limit reached

Response · 401

Authentication required

Response · 403

insufficient_scope or personal_memory_only: caller or universe is not eligible

Response · 409

memory_conflict: reload before writing

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/memory \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"op":"save","text":"Use Celsius for temperatures.","expectedVersion":null}'

Read a saved memory or conversation reference

Rechecks personal ownership and deletion. Accepts memory and session_message references from search. Memory returns the current entry and flags version changes; it does not preserve old versions. Message reads return bounded text and adjacent references for surrounding context. Use nextOffset for a long main message; follow adjacent refs to continue reading. All text together is bounded to 20,000 characters per page.

Query parameters

refstringrequired

URL-encoded JSON source reference copied from a search hit.

offsetinteger

Response · 200

Current reference, text, nextOffset, truncated, updated, adjacent references and coverage.

refobject
textstring
nextOffsetinteger | null
truncatedboolean
updatedboolean
coveragestring
adjacentobject[]
▸ Show child attributes
refobject
textstring
truncatedboolean

Response · 400

Invalid query, source reference, cursor or text offset

Response · 401

Authentication required

Response · 403

The caller lacks personal-context authority or read scope

Response · 404

Source unavailable or not owned by this caller

Response · 409

Memory changed while paging; read again from offset zero

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/context/read?ref=%7B%22kind%22%3A%22memory%22%2C%22index%22%3A0%2C%22version%22%3Anull%7D' \
  -H "Authorization: Bearer ast_..."

Identity

GET/whoamiread

Caller identity, resolved universe, effective scopes

Response · 200

userobjectrequired
▸ Show child attributes
idstring
emailstring
namestring | null
universeobjectrequired
▸ Show child attributes
slugstring
namestring
isPersonalboolean
scopesenum<string>[]required

"read" · "write" · "admin"

authenum<string>required

"token" · "session"

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/whoami' \
  -H "Authorization: Bearer ast_..."

Universes

GET/universesread

List universes

Response · 200

universesobject[]required
▸ Show child attributes
slugstring
namestring
isPersonalboolean

The workspace is its owner's default workspace

isDefaultboolean

The workspace is the caller's own default workspace

createdAtstring

ISO 8601

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/universes' \
  -H "Authorization: Bearer ast_..."
POST/universeswrite, personal tokens only

Create a universe

Body · application/json

slugstringrequired

max length 40 — pattern ^[a-z0-9][a-z0-9-]*[a-z0-9]$

namestring

max length 80

Response · 201

universeobjectrequired
▸ Show child attributes
slugstring
namestring
isPersonalboolean

The workspace is its owner's default workspace

isDefaultboolean

The workspace is the caller's own default workspace

createdAtstring

ISO 8601

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/universes \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"slug":"acme","name":"Acme"}'

Universe detail

Path parameters

slugstringrequired

The universe slug

Response · 200

universeobjectrequired
▸ Show child attributes
slugstring
namestring
isPersonalboolean

The workspace is its owner's default workspace

isDefaultboolean

The workspace is the caller's own default workspace

createdAtstring

ISO 8601

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/universes/acme' \
  -H "Authorization: Bearer ast_..."

People in the workspace and, for owners and admins, waiting invitations

Path parameters

slugstringrequired

The universe slug

Response · 200

roleenum<string>required

"owner" · "admin" · "member"

membersobject[]required
▸ Show child attributes
user_idstring
emailstring
namestring
roleenum<string>

"owner" · "admin" · "member"

joined_atstring
invitesobject[]required
▸ Show child attributes
idstring
emailstring
roleenum<string>

"admin" · "member"

invited_bystring
expires_atstring
created_atstring
limit_requestsobject[]

Members' tasks that wait for a higher monthly limit, oldest first

▸ Show child attributes
idstring
session_idstring
titlestring
memberobject
▸ Show child attributes
user_idstring
namestring
emailstring
raise_toobject
▸ Show child attributes
amountstringrequired

Whole US cents

currencyenum<string>required

"USD"

heldinteger

Messages the task holds and will run when the limit is raised

created_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/universes/acme/members' \
  -H "Authorization: Bearer ast_..."

Remove a non-owner from the workspace, or leave it

The owner removes anyone but themselves. Anyone else may name only themselves (their id, or me), which is how a person leaves; naming someone else is 403, and the owner cannot leave (400). Ends membership access, stops sharing every connection the person shared with the workspace, and closes pending and accepted invitation links. Accounts and threads remain; workspace-visible threads owned by the removed person become read-only for remaining members.

Path parameters

slugstringrequired

The universe slug

userIdstringrequired

Response · 200

oktruerequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/universes/acme/members/cmtb3u5r7k2p9x01s6q8n4w2 \
  -H "Authorization: Bearer ast_..."

Make someone an admin or a member

Path parameters

slugstringrequired

The universe slug

userIdstringrequired

Body · application/json

roleenum<string>required

"admin" · "member"

Response · 200

oktruerequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PATCH https://api.agentsky.dev/v1/universes/acme/members/cmtb3u5r7k2p9x01s6q8n4w2 \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"role":"admin"}'
POST/universes/{slug}/inviteswrite, owner or admin

Add people to the workspace by email

Set send_email to true to send invitation mail and include per-email delivery results. sent means provider acceptance; unavailable leaves a usable link to share. No email is sent and no delivery field is returned by default. The response carries one link token per new invitation (shown only here; links are /join/{token} on the consumer app). Each person joins through the link, or the next time they use AgentSky signed in with that verified email; an invitation lasts 30 days.

Path parameters

slugstringrequired

The universe slug

Body · application/json

emailsstring[]required
send_emailboolean

default: false

roleenum<string>

"admin" · "member" — default: "member"

Response · 201

invitesobject[]
linksobject[]
▸ Show child attributes
emailstring
tokenstring
deliveryobject[]
▸ Show child attributes
emailstring
statusenum<string>

"sent" · "unavailable"

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/universes/acme/invites \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"emails":["teammate@acme.com"],"role":"member","send_email":true}'
DELETE/universes/{slug}/invites/{inviteId}write, owner or admin

Withdraw an invitation that has not been taken up

Path parameters

slugstringrequired

The universe slug

inviteIdstringrequired

Response · 200

oktruerequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/universes/acme/invites/cmtb4i7v2n6q8z01s6k3m5p1 \
  -H "Authorization: Bearer ast_..."
GET/universes/{slug}/walletread, owner or admin

A workspace's own wallet: balance, each member's spending this month, limits, members waiting for a higher limit

404 where workspace wallets are not switched on for the workspace, 400 for a person's default workspace that has no wallet and nobody else in it, 403 for a plain member.

Path parameters

slugstringrequired

The universe slug

Response · 200

walletobject | nullrequired

Null until the workspace is given a wallet

month_startstringrequired

The first instant (UTC) of the month the spending below is counted from

membersobject[]required
▸ Show child attributes
user_idstring
emailstring
namestring
roleenum<string>

"owner" · "admin" · "member"

spentobject
▸ Show child attributes
amountstringrequired

Whole US cents

currencyenum<string>required

"USD"

monthly_limitobject
▸ Show child attributes
amountstringrequired

Whole US cents

currencyenum<string>required

"USD"

fundingobject[]required

The latest additions to the wallet, newest first

▸ Show child attributes
idstring
amountobject
▸ Show child attributes
amountstringrequired

Whole US cents

currencyenum<string>required

"USD"

added_bystring
created_atstring
limit_requestsobject[]required

Members' tasks that wait for a higher monthly limit, oldest first

▸ Show child attributes
idstring
session_idstring
titlestring
memberobject
▸ Show child attributes
user_idstring
namestring
emailstring
raise_toobject
▸ Show child attributes
amountstringrequired

Whole US cents

currencyenum<string>required

"USD"

heldinteger

Messages the task holds and will run when the limit is raised

created_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/universes/acme/wallet' \
  -H "Authorization: Bearer ast_..."
POST/universes/{slug}/walletwrite, owner or admin

Give the workspace a wallet of its own

From then on a new session a member starts in the workspace is paid from this wallet unless its request names payer personal. Sessions that already exist keep the payer recorded for them. Repeating the call returns the wallet that exists.

Path parameters

slugstringrequired

The universe slug

Response · 201

walletobject | nullrequired

Null until the workspace is given a wallet

month_startstringrequired

The first instant (UTC) of the month the spending below is counted from

membersobject[]required
▸ Show child attributes
user_idstring
emailstring
namestring
roleenum<string>

"owner" · "admin" · "member"

spentobject
▸ Show child attributes
amountstringrequired

Whole US cents

currencyenum<string>required

"USD"

monthly_limitobject
▸ Show child attributes
amountstringrequired

Whole US cents

currencyenum<string>required

"USD"

fundingobject[]required

The latest additions to the wallet, newest first

▸ Show child attributes
idstring
amountobject
▸ Show child attributes
amountstringrequired

Whole US cents

currencyenum<string>required

"USD"

added_bystring
created_atstring
limit_requestsobject[]required

Members' tasks that wait for a higher monthly limit, oldest first

▸ Show child attributes
idstring
session_idstring
titlestring
memberobject
▸ Show child attributes
user_idstring
namestring
emailstring
raise_toobject
▸ Show child attributes
amountstringrequired

Whole US cents

currencyenum<string>required

"USD"

heldinteger

Messages the task holds and will run when the limit is raised

created_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/universes/acme/wallet \
  -H "Authorization: Bearer ast_..."
POST/universes/{slug}/wallet/transferswrite, owner or admin

Move some of your own purchased credit into the workspace wallet

All or nothing. Only credit the caller bought moves; free credit stays. 402 insufficient_purchased_credit when the caller holds less purchased credit than the amount, 409 workspace_wallet_missing before the wallet exists. request_id makes a repeat of the same request land once (200 instead of 201); the same id with another amount is 409 idempotency_conflict.

Path parameters

slugstringrequired

The universe slug

Body · application/json

amountobjectrequired
▸ Show child attributes
amountstringrequired

Whole US cents

currencyenum<string>required

"USD"

request_idstringrequired

max length 100

Response · 201

Moved

transferredboolean
balanceobject
▸ Show child attributes
amountstringrequired

Whole US cents

currencyenum<string>required

"USD"

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/universes/acme/wallet/transfers \
  -H "Authorization: Bearer ast_..."
POST/universes/{slug}/wallet/topupswrite, owner or admin

Buy credit for the workspace wallet with your own saved card

Charges the caller's own saved card the credit plus the card processing fee and adds the credit to the workspace wallet. The caller's own balance, card and auto top-up are not changed. amount is 1000, 2000, 5000 or 10000 cents. request_id makes a repeat of the same request charge once (200 instead of 201). 409 card_required when the caller has no saved card (add one to your own account first), 402 card_declined, 409 workspace_wallet_missing before the wallet exists, 503 payments_unavailable where card payments are not set up. A workspace key or a restricted credential cannot buy credit.

Path parameters

slugstringrequired

The universe slug

Body · application/json

amountobjectrequired
▸ Show child attributes
amountstringrequired

Whole US cents

currencyenum<string>required

"USD"

request_idstringrequired

max length 100

Response · 201

Bought

chargedboolean
balanceobject
▸ Show child attributes
amountstringrequired

Whole US cents

currencyenum<string>required

"USD"

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/universes/acme/wallet/topups \
  -H "Authorization: Bearer ast_..."

Answer a member's request for a higher monthly limit

A member who reaches their monthly limit is not only refused: the task they started or wrote to waits, holding what it was given, and a request is raised (limit_requests on the wallet, and a spend request on the task). raise sets the member's limit to the amount the request offered and sends on what every waiting task of theirs was holding; decline closes this request and drops what its task held. 404 when the request is not open.

Path parameters

slugstringrequired

The universe slug

requestIdstringrequired

Body · application/json

answerenum<string>required

"raise" · "decline"

Response · 200

okboolean
message_idstring

The first message sent on to a waiting task, when one was

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/universes/acme/wallet/limit-requests/requestId \
  -H "Authorization: Bearer ast_..."

Set or clear a member's monthly limit on workspace wallet spending

The limit counts what the sessions that member started were charged to the workspace wallet in the calendar month (UTC), their helpers included. At the limit a message to a session the workspace pays for, a helper, a handoff and a fork are refused with 402 member_limit_reached, and a new session is created waiting; other members are not affected. monthly_limit null removes the limit. When the new limit lets the member spend again their waiting tasks continue by themselves: resumed counts the messages that were sent on.

Path parameters

slugstringrequired

The universe slug

userIdstringrequired

Body · application/json

monthly_limitobjectrequired
▸ Show child attributes
amountstringrequired

Whole US cents

currencyenum<string>required

"USD"

Response · 200

okboolean
resumedinteger

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PUT https://api.agentsky.dev/v1/universes/acme/wallet/limits/cmtb3u5r7k2p9x01s6q8n4w2 \
  -H "Authorization: Bearer ast_..."

Connected apps people share with the workspace, and the ones it owns

sharing says whether members can share connected apps with this workspace; while it is on, can_connect says whether the caller may connect an app for the workspace itself, and a connection the workspace owns carries workspace_owned. A person's default workspace takes shared connections only once someone besides its owner is in it. Agents in the workspace's sessions can call through a shared connection whoever started the session; nobody but the person who shared it holds its sign-in.

Path parameters

slugstringrequired

The universe slug

Response · 200

sharingbooleanrequired

Whether members can share connected apps with this workspace.

can_connectboolean

While sharing is on: whether the caller may connect an app for the workspace itself.

connectionsobject[]required
▸ Show child attributes
connection_idstring
appstring
app_namestring
labelstring
shared_byobject
▸ Show child attributes
user_idstring
namestring
shared_atstring
mineboolean

True when the caller is the person who shared it.

workspace_ownedboolean

Present and true when the workspace itself owns the connection.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/universes/acme/connections' \
  -H "Authorization: Bearer ast_..."

Share one of your own connections with the workspace, or start connecting an app for it

With connection_id: only a connection of the caller's can be shared; answers 201 with the workspace's connections. With app, success_url and error_url (owner or admin): starts connecting an app for the workspace itself and answers 200 with the address to open in a browser; record the result with POST /universes/{slug}/connections/complete. A connection made this way belongs to the workspace, not to the person who made it, and stays when they leave. Mail and calendar apps stay personal either way (400 personal_only).

Path parameters

slugstringrequired

The universe slug

Body · application/json

connection_idstring
appstring
success_urlstring
error_urlstring

Response · 200

Started

urlstring

Response · 201

sharingbooleanrequired

Whether members can share connected apps with this workspace.

can_connectboolean

While sharing is on: whether the caller may connect an app for the workspace itself.

connectionsobject[]required
▸ Show child attributes
connection_idstring
appstring
app_namestring
labelstring
shared_byobject
▸ Show child attributes
user_idstring
namestring
shared_atstring
mineboolean

True when the caller is the person who shared it.

workspace_ownedboolean

Present and true when the workspace itself owns the connection.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/universes/acme/connections \
  -H "Authorization: Bearer ast_..."

Record an app connected for the workspace itself

The account is checked against the workspace's own accounts at the provider; without account_id its newest one for the app is used. From then on agents in every session of the workspace can call through it. 404 when the workspace has no such account.

Path parameters

slugstringrequired

The universe slug

Body · application/json

appstringrequired
account_idstring

Response · 201

sharingbooleanrequired

Whether members can share connected apps with this workspace.

can_connectboolean

While sharing is on: whether the caller may connect an app for the workspace itself.

connectionsobject[]required
▸ Show child attributes
connection_idstring
appstring
app_namestring
labelstring
shared_byobject
▸ Show child attributes
user_idstring
namestring
shared_atstring
mineboolean

True when the caller is the person who shared it.

workspace_ownedboolean

Present and true when the workspace itself owns the connection.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/universes/acme/connections/complete \
  -H "Authorization: Bearer ast_..."
DELETE/universes/{slug}/connections/{connectionId}write, the sharer, owner or admin

Stop sharing a connection with the workspace

Agents lose it at once. A connection the workspace owns itself is disconnected for good, by an owner or admin only.

Path parameters

slugstringrequired

The universe slug

connectionIdstringrequired

Response · 200

oktruerequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/universes/acme/connections/connectionId \
  -H "Authorization: Bearer ast_..."
GET/universes/{slug}/keysread, owner or admin

Keys that belong to the workspace

A workspace key belongs to the workspace, not to the person who made it, and keeps working after they leave. It acts through the workspace owner's account, whose wallet pays for the sessions it starts, and reaches only the workspace's agents, sessions, files, skills and environments. The listing never carries a secret.

Path parameters

slugstringrequired

The universe slug

Response · 200

keysobject[]required
▸ Show child attributes
idstringrequired
namestringrequired
prefixstringrequired

The start of the secret, to tell one key from another.

scopesenum<string>[]required

"read" · "write" · "admin"

created_byobjectrequired
▸ Show child attributes
user_idstring
namestring
created_atstringrequired
last_used_atstring
expires_atstring
revoked_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/universes/acme/keys' \
  -H "Authorization: Bearer ast_..."
POST/universes/{slug}/keysadmin, owner or admin

Make a workspace key

The secret is returned only in this response. The key carries no more scope than the credential that makes it.

Path parameters

slugstringrequired

The universe slug

Body · application/json

namestringrequired

max length 80

scopesenum<string>[]required

"read" · "write" · "admin"

expires_atstring

Response · 201

keyobjectrequired
▸ Show child attributes
idstringrequired
namestringrequired
prefixstringrequired

The start of the secret, to tell one key from another.

scopesenum<string>[]required

"read" · "write" · "admin"

created_byobjectrequired
▸ Show child attributes
user_idstring
namestring
created_atstringrequired
last_used_atstring
expires_atstring
revoked_atstring
secretstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/universes/acme/keys \
  -H "Authorization: Bearer ast_..."
DELETE/universes/{slug}/keys/{keyId}admin, owner or admin

Revoke a workspace key

Path parameters

slugstringrequired

The universe slug

keyIdstringrequired

Response · 200

oktruerequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/universes/acme/keys/keyId \
  -H "Authorization: Bearer ast_..."

Get workspace shared hooks

Path parameters

slugstringrequired

The universe slug

Response · 200

hooksany[]

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/universes/acme/hooks' \
  -H "Authorization: Bearer ast_..."

Replace workspace shared hooks (owner only)

Path parameters

slugstringrequired

The universe slug

Body · application/json

hooksany[]required

Response · 200

hooksany[]

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PUT https://api.agentsky.dev/v1/universes/acme/hooks \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"hooks":[{"event":"pre_tool_use","matcher":"Bash","command":"./.agentsky/check-command.sh","timeout_s":30}]}'

List workspace policy rules

Path parameters

slugstringrequired

The universe slug

Response · 200

rulesobject[]
▸ Show child attributes
idstringrequired
namestringrequired
kindenum<string>required

"TOOL_CALL" · "SPEND_CAP" · "CALL_COUNT" · "CAPABILITY"

enabledbooleanrequired
configobjectrequired
layerenum<string>required

"workspace" · "agent" · "session"

positionintegerrequired
createdAtstringrequired
updatedAtstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/universes/acme/policies' \
  -H "Authorization: Bearer ast_..."

Create a workspace policy rule (owner only)

A rule {name, kind: "CAPABILITY", config: {"platform.orchestration": "deny"}} stops every session of the workspace from bringing in other agents as helpers (403 hiring_disabled to the agent; helpers it already has can still be listed, collected and stopped), and sessions created afterwards are not told how to hire. Disable or delete the rule to turn hiring back on.

Path parameters

slugstringrequired

The universe slug

Body · application/json

option 1object
▸ Show child attributes
namestringrequired

max length 128

enabledboolean

default: true

positioninteger

default: 0

kind"TOOL_CALL"required
configobjectrequired
▸ Show child attributes
actionenum<string>required

"allow" · "ask" · "deny"

matcherstring

max length 255

commandPatternsstring[]

max length 500

option 2object
▸ Show child attributes
namestringrequired

max length 128

enabledboolean

default: true

positioninteger

default: 0

kind"SPEND_CAP"required
configobjectrequired
▸ Show child attributes
warnUsdMicrosinteger | null
hardCapUsdMicrosintegerrequired
option 3object
▸ Show child attributes
namestringrequired

max length 128

enabledboolean

default: true

positioninteger

default: 0

kind"CALL_COUNT"required
configobjectrequired
▸ Show child attributes
limitPerSessionintegerrequired
option 4object
▸ Show child attributes
namestringrequired

max length 128

enabledboolean

default: true

positioninteger

default: 0

kind"CAPABILITY"required
configmap<string, enum<string>>required

"allow" · "ask" · "deny"

Response · 201

ruleobject
▸ Show child attributes
idstringrequired
namestringrequired
kindenum<string>required

"TOOL_CALL" · "SPEND_CAP" · "CALL_COUNT" · "CAPABILITY"

enabledbooleanrequired
configobjectrequired
layerenum<string>required

"workspace" · "agent" · "session"

positionintegerrequired
createdAtstringrequired
updatedAtstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/universes/acme/policies \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"name":"Block destructive shell commands","kind":"TOOL_CALL","config":{"action":"deny","matcher":"Bash","commandPatterns":["rm -rf *"]}}'

Get a workspace policy rule

Path parameters

slugstringrequired

The universe slug

ruleIdstringrequired

The policy rule id

Response · 200

ruleobject
▸ Show child attributes
idstringrequired
namestringrequired
kindenum<string>required

"TOOL_CALL" · "SPEND_CAP" · "CALL_COUNT" · "CAPABILITY"

enabledbooleanrequired
configobjectrequired
layerenum<string>required

"workspace" · "agent" · "session"

positionintegerrequired
createdAtstringrequired
updatedAtstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/universes/acme/policies/cmtb5p0l3r8w2k01s6x7n9q4' \
  -H "Authorization: Bearer ast_..."

Update a workspace policy rule (owner only)

Path parameters

slugstringrequired

The universe slug

ruleIdstringrequired

The policy rule id

Body · application/json

namestring

max length 128

enabledboolean
positioninteger
configobject | map<string, enum<string>>
▸ Show child attributes
option 1object
▸ Show child attributes
actionenum<string>required

"allow" · "ask" · "deny"

matcherstring

max length 255

commandPatternsstring[]

max length 500

option 2object
▸ Show child attributes
warnUsdMicrosinteger | null
hardCapUsdMicrosintegerrequired
option 3object
▸ Show child attributes
limitPerSessionintegerrequired
option 4map<string, enum<string>>

"allow" · "ask" · "deny"

Response · 200

ruleobject
▸ Show child attributes
idstringrequired
namestringrequired
kindenum<string>required

"TOOL_CALL" · "SPEND_CAP" · "CALL_COUNT" · "CAPABILITY"

enabledbooleanrequired
configobjectrequired
layerenum<string>required

"workspace" · "agent" · "session"

positionintegerrequired
createdAtstringrequired
updatedAtstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PATCH https://api.agentsky.dev/v1/universes/acme/policies/cmtb5p0l3r8w2k01s6x7n9q4 \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"enabled":false}'

Delete a workspace policy rule (owner only)

Path parameters

slugstringrequired

The universe slug

ruleIdstringrequired

The policy rule id

Response · 200

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/universes/acme/policies/cmtb5p0l3r8w2k01s6x7n9q4 \
  -H "Authorization: Bearer ast_..."

Products and Runs

GET/productsread

Products, permitted inputs and configuration, prices and certified capabilities

Every agent in the catalog (GET /catalog/agents) is also listed, as `@handle`; it is available when its latest check run passed the required checks.

Response · 200

Executable product catalog

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/products' \
  -H "Authorization: Bearer ast_..."
POST/runswrite

Run a product

String input is a shortcut. Agent objects preserve one user message and optional system message. Direct Agent Runs prepare a Session with platform billing; an existing Session retains its payer and billing settings. Non-streaming waits up to ten seconds. SSE begins with the durable Run identity. Disconnect never cancels execution. A catalog handle (`@handle`) runs that agent as one turn of a new session of it, charged as that session is: `addons` may set `model`, within the agent's engine, and `instructions`, files added after the agent's own, and nothing else; a `user.message` sent to the Run (POST /runs/{id}/events) is the next turn of that session and a Run of its own. When a Run of a handle ends, each webhook endpoint of the workspace subscribed to `run.completed`, `run.interrupted`, `run.failed` or `run.blocked` receives that event once, signed like every other webhook. A handle whose agent has not passed its checks is refused with `listing_not_checked` or `listing_checks_failed`.

Body · application/json

productstringrequired

max length 240

inputanyrequired
addonsmap<string, any>
session_idstring
streamboolean
metadatamap<string, any>

Response · 200

Durable Run identity, status, output and references to authoritative billing.

runobject
▸ Show child attributes
idstringrequired
productstring | nullrequired
session_idstring | nullrequired
statusenum<string>required

"queued" · "running" · "waiting_input" · "stopping" · "completed" · "interrupted" · "failed" · "blocked" · "reconciling"

outputanyrequired
output_availableboolean
usageanyrequired
billinganyrequired
erroranyrequired
artifactobject
▸ Show child attributes
idstringrequired
mediaTypestringrequired
urlstringrequired
sourceobject
▸ Show child attributes
goal_idstring
iterationinteger
routine_run_idstring
routine_idstring
created_atstringrequired
completed_atstring | nullrequired

Response · 202

Durable Run identity, status, output and references to authoritative billing.

runobject
▸ Show child attributes
idstringrequired
productstring | nullrequired
session_idstring | nullrequired
statusenum<string>required

"queued" · "running" · "waiting_input" · "stopping" · "completed" · "interrupted" · "failed" · "blocked" · "reconciling"

outputanyrequired
output_availableboolean
usageanyrequired
billinganyrequired
erroranyrequired
artifactobject
▸ Show child attributes
idstringrequired
mediaTypestringrequired
urlstringrequired
sourceobject
▸ Show child attributes
goal_idstring
iterationinteger
routine_run_idstring
routine_idstring
created_atstringrequired
completed_atstring | nullrequired

Response · 409

Session busy or conflicting idempotency key

Response · 422

The product cannot be run: a listed agent that has not passed its checks, or an override that is not allowed

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/runs \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"product":"@claude_code","input":"Summarize the repository."}'
GET/runs/{id}read

Read a Run

Path parameters

idstringrequired

Response · 200

Durable Run identity, status, output and references to authoritative billing.

runobject
▸ Show child attributes
idstringrequired
productstring | nullrequired
session_idstring | nullrequired
statusenum<string>required

"queued" · "running" · "waiting_input" · "stopping" · "completed" · "interrupted" · "failed" · "blocked" · "reconciling"

outputanyrequired
output_availableboolean
usageanyrequired
billinganyrequired
erroranyrequired
artifactobject
▸ Show child attributes
idstringrequired
mediaTypestringrequired
urlstringrequired
sourceobject
▸ Show child attributes
goal_idstring
iterationinteger
routine_run_idstring
routine_idstring
created_atstringrequired
completed_atstring | nullrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/runs/sess_cmtb7q2j' \
  -H "Authorization: Bearer ast_..."

Read durable Run events, or observe with Accept: text/event-stream

A Run of a catalog handle reports `run.running`, each `agent.message` with its text, and how it ended.

Path parameters

idstringrequired

Query parameters

cursorstring

Response · 200

Opaque Run cursor, separate from the Session transcript cursor

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/runs/sess_cmtb7q2j/events' \
  -H "Authorization: Bearer ast_..."

Target steering or an interrupt to this Run

For a Run of a catalog handle, one `user.message` starts the next turn of the Run's session as a new Run and is answered with `{ run_id, status }` naming that new Run (also in `Location`); it follows the idempotency rules of starting a Run, and is refused with 409 `session_busy` while a turn of the session is still going and 409 `session_archived` once the session has ended. One `user.interrupt` stops this Run's turn and is answered with `{ run_id, status }` for this Run; a Run that has already ended is answered with the status it ended in. A system message is not accepted.

Path parameters

idstringrequired

Body · application/json

eventsobject[]required
▸ Show child attributes
type: "user.message"object
▸ Show child attributes
type"user.message"required
contentobject[]required
▸ Show child attributes
type: "text"object
▸ Show child attributes
type"text"required
textstringrequired
type: "image"object
▸ Show child attributes
type"image"required
sourceobjectrequired
▸ Show child attributes
type: "base64"object
▸ Show child attributes
type"base64"required
media_typestringrequired
datastringrequired
type: "url"object
▸ Show child attributes
type"url"required
urlstringrequired
type: "file"object
▸ Show child attributes
type"file"required
file_idstringrequired
type: "document"object
▸ Show child attributes
type"document"required
sourceobjectrequired
▸ Show child attributes
type: "base64"object
▸ Show child attributes
type"base64"required
media_typestringrequired
datastringrequired
type: "text"object
▸ Show child attributes
type"text"required
media_type"text/plain"

default: "text/plain"

datastringrequired
type: "url"object
▸ Show child attributes
type"url"required
urlstringrequired
type: "file"object
▸ Show child attributes
type"file"required
file_idstringrequired
titlestring | null
contextstring | null
interaction_modeenum<string> | null

"plan" · "build"

type: "system.message"object
▸ Show child attributes
type"system.message"required
contentobject[]required
▸ Show child attributes
type"text"required
textstringrequired
type: "user.interrupt"object
▸ Show child attributes
type"user.interrupt"required

Response · 202

Control admitted; runtime confirmation is separate

Response · 409

Run is terminal or input conflicts

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/runs/sess_cmtb7q2j/events \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"events":[{"type":"user.interrupt"}]}'

Agents

GET/agentsread

List agents in the resolved universe

Response · 200

agentsobject[]required
▸ Show child attributes
idstring

The agent id (agent_…) — the only address

namestring
displayNamestring
agentTypestring

Engine — hermes · claude_code · codex · openclaw · pi · dsh · kimi_code · opencode · jev, or any ACP harness (the full vocabulary is the enum on CreateAgent)

llmstring
harnessVersionstring | null

The engine CLI version this agent's sessions run; PATCH to move to the platform's current version

reasoningEffortstring | null

Harness-native reasoning effort; null = model-compatible fallback for constrained models, otherwise harness default. Applies from the next provision/restart. Allowed values depend on agentType — agoragentic_acp: not supported; amp_acp: not supported; auggie: not supported; autohand: not supported; cline: not supported; codebuddy_code: not supported; cortex_code: not supported; corust_agent: not supported; crow_cli: not supported; cursor: not supported; deepagents: not supported; devin: not supported; dimcode: not supported; dirac: not supported; factory_droid: not supported; fast_agent: not supported; gemini: not supported; github_copilot_cli: not supported; glm_acp_agent: not supported; antigravity_acp: not supported; goose: not supported; grok_build: not supported; harn: not supported; junie: not supported; kilo: not supported; kimchi: not supported; minimax_code: not supported; minion_code: not supported; mistral_vibe: not supported; nova: not supported; poolside: not supported; qoder: not supported; qwen_code: not supported; sigit: not supported; stakpak: not supported; vtcode: not supported; code_assistant: not supported; docker_cagent: not supported; kiro: not supported; muse_code: not supported; openhands: not supported; hermes: none/minimal/low/medium/high/xhigh/max/ultra; claude_code: low/medium/high/xhigh/max; codex: none/minimal/low/medium/high/xhigh/max; openclaw: not supported; jev: not supported; pi: off/minimal/low/medium/high/xhigh/max; dsh: not supported; kimi_code: not supported; opencode: none/minimal/low/medium/high/xhigh/max; workspace_acp: not supported; models: claude-haiku-4-5: not supported; gemini-3.8-flash: low/medium/high; gemini-3.5-flash: low/medium/high; glm-5.3: low/high/max; glm-5.3-flash: low/high/max; grok-4.6: low/medium/high; grok-4.7: low/medium/high/xhigh; codex/hermes + gpt-6.1-sol: low/medium/high/xhigh/max — "none" · "off" · "minimal" · "low" · "medium" · "high" · "xhigh" · "max" · "ultra" · null

capabilitiesenum<string>[]

The built-in capabilities this agent is granted — the exact set its sessions may execute (enforced; empty = none). Ids are listed at /docs/capabilities. — "embedding.openai" · "embedding.voyage" · "rerank.voyage" · "ocr.mistral" · "exa.search" · "exa.contents" · "tinyfish.fetch" · "tinyfish.browser" · "tinyfish.agent" · "dataforseo.serp" · "dataforseo.ai-keywords" · "dataforseo.llm-responses" · "dataforseo.app-info" · "dataforseo.app-search" · "dataforseo.backlinks" · "dataforseo.business-reviews" · "dataforseo.business-pinterest" · "dataforseo.content-analysis" · "dataforseo.technologies" · "dataforseo.keyword-data" · "dataforseo.labs" · "dataforseo.amazon" · "dataforseo.onpage" · "gptimage.generate" · "rembg.remove-background" · "seedance.generate" · "mm.i2v" · "wan.t2v" · "wan.i2v" · "happyhorse.t2v" · "minimax.h3" · "fish-audio.transcribe" · "code-review" · "exa.answer" · "googlemap.geocode" · "googlemap.places" · "agentmail.list-inboxes" · "tinyfish.search" · "tinyfish.profile-list" · "meta.transcribe" · "minimax.tts" · "elevenlabs.sound" · "zai.transcribe" · "openai.transcribe" · "fish-audio.tts" · "google.image" · "openai.image-2.5" · "wan.image" · "logo.lookup" · "openmeteo.weather" · "frankfurter.fx" · "dictionary.define" · "openlibrary.search" · "googledns.resolve" · "qrserver.create" · "social-boost.catalog"

versioninteger

Bumped on every update; see expectedVersion

archivedboolean
sessionCountinteger
createdAtstring

ISO 8601

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/agents' \
  -H "Authorization: Bearer ast_..."
POST/agentswrite

Create an agent

An agent is a reusable configuration — engine, prompt, capabilities, secrets. Every field is optional: an empty body creates the default pi agent with no built-in capabilities (capabilities are explicit opt-in; unknown ids → 400). The response's `id` (agent_…) is the agent's only address. One agent can run many sessions; creating the agent provisions nothing — session creation provisions the pod by default (POST /v1/sessions supports deferred provisioning). Optional Idempotency-Key safely replays the original 201 response within the same user and universe; changing the body with the same key returns 409 idempotency_conflict. Keys do not expire.

Body · application/json

namestring

Prompt label only — not an address. An agent is addressed by the `id` in the response (agent_…); names are free and need not be unique — max length 60

descriptionstring

max length 500

agentTypeenum<string>

"hermes" · "claude_code" · "codex" · "openclaw" · "pi" · "dsh" · "kimi_code" · "opencode" · "jev" · "agoragentic_acp" · "amp_acp" · "auggie" · "autohand" · "cline" · "codebuddy_code" · "cortex_code" · "corust_agent" · "crow_cli" · "cursor" · "deepagents" · "devin" · "dimcode" · "dirac" · "factory_droid" · "fast_agent" · "gemini" · "github_copilot_cli" · "glm_acp_agent" · "antigravity_acp" · "goose" · "grok_build" · "harn" · "junie" · "kilo" · "kimchi" · "minimax_code" · "minion_code" · "mistral_vibe" · "nova" · "poolside" · "qoder" · "qwen_code" · "sigit" · "stakpak" · "vtcode" · "code_assistant" · "docker_cagent" · "kiro" · "openhands" · "muse_code" · "workspace_acp"

llmstring
reasoningEffortenum<string>

Harness/model-compatible reasoning effort; omitted = model-compatible fallback for constrained models, otherwise harness default. Explicit values must fit both agentType and llm — agoragentic_acp: not supported; amp_acp: not supported; auggie: not supported; autohand: not supported; cline: not supported; codebuddy_code: not supported; cortex_code: not supported; corust_agent: not supported; crow_cli: not supported; cursor: not supported; deepagents: not supported; devin: not supported; dimcode: not supported; dirac: not supported; factory_droid: not supported; fast_agent: not supported; gemini: not supported; github_copilot_cli: not supported; glm_acp_agent: not supported; antigravity_acp: not supported; goose: not supported; grok_build: not supported; harn: not supported; junie: not supported; kilo: not supported; kimchi: not supported; minimax_code: not supported; minion_code: not supported; mistral_vibe: not supported; nova: not supported; poolside: not supported; qoder: not supported; qwen_code: not supported; sigit: not supported; stakpak: not supported; vtcode: not supported; code_assistant: not supported; docker_cagent: not supported; kiro: not supported; muse_code: not supported; openhands: not supported; hermes: none/minimal/low/medium/high/xhigh/max/ultra; claude_code: low/medium/high/xhigh/max; codex: none/minimal/low/medium/high/xhigh/max; openclaw: not supported; jev: not supported; pi: off/minimal/low/medium/high/xhigh/max; dsh: not supported; kimi_code: not supported; opencode: none/minimal/low/medium/high/xhigh/max; workspace_acp: not supported; models: claude-haiku-4-5: not supported; gemini-3.8-flash: low/medium/high; gemini-3.5-flash: low/medium/high; glm-5.3: low/high/max; glm-5.3-flash: low/high/max; grok-4.6: low/medium/high; grok-4.7: low/medium/high/xhigh; codex/hermes + gpt-6.1-sol: low/medium/high/xhigh/max — "none" · "off" · "minimal" · "low" · "medium" · "high" · "xhigh" · "max" · "ultra"

promptstring

max length 100000

displayNamestring

What the agent is called in the console and in channels; omitted = an auto-generated asteroid name — max length 60

capabilitiesenum<string>[]

"embedding.openai" · "embedding.voyage" · "rerank.voyage" · "ocr.mistral" · "exa.search" · "exa.contents" · "tinyfish.fetch" · "tinyfish.browser" · "tinyfish.agent" · "dataforseo.serp" · "dataforseo.ai-keywords" · "dataforseo.llm-responses" · "dataforseo.app-info" · "dataforseo.app-search" · "dataforseo.backlinks" · "dataforseo.business-reviews" · "dataforseo.business-pinterest" · "dataforseo.content-analysis" · "dataforseo.technologies" · "dataforseo.keyword-data" · "dataforseo.labs" · "dataforseo.amazon" · "dataforseo.onpage" · "gptimage.generate" · "rembg.remove-background" · "seedance.generate" · "mm.i2v" · "wan.t2v" · "wan.i2v" · "happyhorse.t2v" · "minimax.h3" · "fish-audio.transcribe" · "code-review" · "exa.answer" · "googlemap.geocode" · "googlemap.places" · "agentmail.list-inboxes" · "tinyfish.search" · "tinyfish.profile-list" · "meta.transcribe" · "minimax.tts" · "elevenlabs.sound" · "zai.transcribe" · "openai.transcribe" · "fish-audio.tts" · "google.image" · "openai.image-2.5" · "wan.image" · "logo.lookup" · "openmeteo.weather" · "frankfurter.fx" · "dictionary.define" · "openlibrary.search" · "googledns.resolve" · "qrserver.create" · "social-boost.catalog"

instructionsobject[]
▸ Show child attributes
namestringrequired

pattern .*\.md$

contentstring

default: ""

skillsobject[]

RFC-0073 skill attachments: store references ({type:'skill', skillId, version?: 'latest'|skr_…}) and GitHub shortcuts ({type:'github', url, ref?, tokenSecretRef?}). Max 20.

▸ Show child attributes
type: "skill"object
▸ Show child attributes
type"skill"required
skillIdstringrequired
versionstring

default: "latest"

type: "github"object
▸ Show child attributes
type"github"required
urlstringrequired
refstring

Branch or commit SHA; default branch when omitted.

tokenSecretRefstring

Agent secret key holding a clone token for private repos.

mcpServersobject[]

Remote streamable-HTTP MCP servers this agent connects to.

▸ Show child attributes
type"url"

default: "url"

namestringrequired

max length 255

urlstringrequired
toolsobject
▸ Show child attributes
includestring[]

default: []

excludestring[]

default: []

hooksobject[]

Shell commands run in the session's pod at lifecycle events ({event, command, matcher?, timeout_s?}). Every harness accepts every event; a hook can stop a prompt or a tool call only on a harness whose own hook system fires that event. Max 20.

▸ Show child attributes
eventenum<string>required

"pre_session_start" · "session_start" · "user_prompt_submit" · "pre_tool_use" · "post_tool_use" · "stop" · "session_end"

commandstringrequired

max length 4000

matcherstring

max length 255

timeout_sinteger
customDataobject[]
▸ Show child attributes
idstringrequired
namestringrequired

pattern ^[a-z0-9_]+$

kindenum<string>required

"spreadsheet" · "doc" · "private_api" · "other"

scopeenum<string>

"creator" · "user" — default: "creator"

descriptionstring
uristring
configmap<string, string>

default: {}

metadatamap<string, any>
environmentIdstring

The workspace environment a session of this agent boots in when its create names no `environment_id`; ahead of the workspace default. Omitted = no agent default.

vaultIdstring

A workspace vault every session of this agent carries: after the vaults the session create names, ahead of the workspace default. Omitted = no agent vault.

capabilityPoliciesmap<string, enum<string>>

"always_allow" · "always_ask" · "auto"

nativeToolPolicyenum<string>

Owner-only permission for native pod tools; omitted defaults to always_allow. Supported by Claude Code and Codex after native approval rollout. — "always_allow" · "always_ask"

hiringPolicyenum<string>

Whether this agent's sessions may bring in other agents as helpers; omitted defaults to allow. deny makes the agent work alone. — "allow" · "deny"

harnessstring

workspace_acp only: the public id (hrn_…) of the workspace harness to pin. Required when agentType is workspace_acp.

Response · 201

agentobjectrequired

Everything in the list item, plus configuration state.

▸ Show child attributes
idstring

The agent id (agent_…) — the only address

namestring
displayNamestring
agentTypestring
llmstring
harnessVersionstring | null
reasoningEffortstring | null

"none" · "off" · "minimal" · "low" · "medium" · "high" · "xhigh" · "max" · "ultra" · null

versioninteger
archivedboolean
sessionCountinteger
createdAtstring
descriptionstring | null
promptstring | null

The user prompt layer

promptVersioninteger | null
capabilitiesenum<string>[]

The built-in capabilities this agent is granted — the exact set its sessions may execute (enforced; empty = none). Ids are listed at /docs/capabilities. — "embedding.openai" · "embedding.voyage" · "rerank.voyage" · "ocr.mistral" · "exa.search" · "exa.contents" · "tinyfish.fetch" · "tinyfish.browser" · "tinyfish.agent" · "dataforseo.serp" · "dataforseo.ai-keywords" · "dataforseo.llm-responses" · "dataforseo.app-info" · "dataforseo.app-search" · "dataforseo.backlinks" · "dataforseo.business-reviews" · "dataforseo.business-pinterest" · "dataforseo.content-analysis" · "dataforseo.technologies" · "dataforseo.keyword-data" · "dataforseo.labs" · "dataforseo.amazon" · "dataforseo.onpage" · "gptimage.generate" · "rembg.remove-background" · "seedance.generate" · "mm.i2v" · "wan.t2v" · "wan.i2v" · "happyhorse.t2v" · "minimax.h3" · "fish-audio.transcribe" · "code-review" · "exa.answer" · "googlemap.geocode" · "googlemap.places" · "agentmail.list-inboxes" · "tinyfish.search" · "tinyfish.profile-list" · "meta.transcribe" · "minimax.tts" · "elevenlabs.sound" · "zai.transcribe" · "openai.transcribe" · "fish-audio.tts" · "google.image" · "openai.image-2.5" · "wan.image" · "logo.lookup" · "openmeteo.weather" · "frankfurter.fx" · "dictionary.define" · "openlibrary.search" · "googledns.resolve" · "qrserver.create" · "social-boost.catalog"

capabilityPoliciesmap<string, enum<string>>

Per-capability permission policy map; omitted when no entries exist. always_allow: invoke without user confirmation. always_ask: prompt the session owner before every invocation. auto: reserved for future policy evaluation; currently prompts the session owner like always_ask. — "always_allow" · "always_ask" · "auto"

nativeToolPolicyenum<string>

Native pod-tool permission, independent of capabilities. Returned on create and detail responses; omitted legacy settings mean always_allow. Only the agent owner can change it, while sessions are idle. — "always_allow" · "always_ask"

hiringPolicyenum<string>

Whether this agent's sessions may bring in other agents as helpers. allow unless set to deny. Returned on create and detail responses. — "allow" · "deny"

mcpServersobject[]

Declared remote MCP server references, including tool filters; runtime authentication fields are never returned

▸ Show child attributes
type"url"

default: "url"

namestringrequired

max length 255

urlstringrequired
toolsobject
▸ Show child attributes
includestring[]

default: []

excludestring[]

default: []

hooksobject[]

Shell commands run in the session's pod at lifecycle events

▸ Show child attributes
eventenum<string>required

"pre_session_start" · "session_start" · "user_prompt_submit" · "pre_tool_use" · "post_tool_use" · "stop" · "session_end"

commandstringrequired

max length 4000

matcherstring

max length 255

timeout_sinteger
metadataobject

Your key-merged client metadata

environmentIdstring | null

The environment sessions of this agent boot in when their create names none; ahead of the workspace default

vaultIdstring | null

The vault every session of this agent carries, after the vaults its create names and ahead of the workspace default

defaultSessionIdstring | null

The session conversation verbs target when addressed by agent id

universestring

Resolved universe slug

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/agents \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"displayName":"Research Agent","agentType":"hermes","llm":"deepseek-v4-pro","capabilities":["exa.search"]}'
Response · 201 Created
{
  "agent": {
    "id": "agent_cmtb2f0a8m9k7x51q4ez6r0d",
    "name": "Research Agent",
    "displayName": "Research Agent",
    "agentType": "hermes",
    "llm": "deepseek-v4-pro",
    "version": 1,
    "capabilities": [
      "exa.search"
    ],
    "defaultSessionId": null,
    "universe": "acme"
  }
}

Agent detail

Path parameters

idstringrequired

The agent id (agent_…)

Response · 200

agentobjectrequired

Everything in the list item, plus configuration state.

▸ Show child attributes
idstring

The agent id (agent_…) — the only address

namestring
displayNamestring
agentTypestring
llmstring
harnessVersionstring | null
reasoningEffortstring | null

"none" · "off" · "minimal" · "low" · "medium" · "high" · "xhigh" · "max" · "ultra" · null

versioninteger
archivedboolean
sessionCountinteger
createdAtstring
descriptionstring | null
promptstring | null

The user prompt layer

promptVersioninteger | null
capabilitiesenum<string>[]

The built-in capabilities this agent is granted — the exact set its sessions may execute (enforced; empty = none). Ids are listed at /docs/capabilities. — "embedding.openai" · "embedding.voyage" · "rerank.voyage" · "ocr.mistral" · "exa.search" · "exa.contents" · "tinyfish.fetch" · "tinyfish.browser" · "tinyfish.agent" · "dataforseo.serp" · "dataforseo.ai-keywords" · "dataforseo.llm-responses" · "dataforseo.app-info" · "dataforseo.app-search" · "dataforseo.backlinks" · "dataforseo.business-reviews" · "dataforseo.business-pinterest" · "dataforseo.content-analysis" · "dataforseo.technologies" · "dataforseo.keyword-data" · "dataforseo.labs" · "dataforseo.amazon" · "dataforseo.onpage" · "gptimage.generate" · "rembg.remove-background" · "seedance.generate" · "mm.i2v" · "wan.t2v" · "wan.i2v" · "happyhorse.t2v" · "minimax.h3" · "fish-audio.transcribe" · "code-review" · "exa.answer" · "googlemap.geocode" · "googlemap.places" · "agentmail.list-inboxes" · "tinyfish.search" · "tinyfish.profile-list" · "meta.transcribe" · "minimax.tts" · "elevenlabs.sound" · "zai.transcribe" · "openai.transcribe" · "fish-audio.tts" · "google.image" · "openai.image-2.5" · "wan.image" · "logo.lookup" · "openmeteo.weather" · "frankfurter.fx" · "dictionary.define" · "openlibrary.search" · "googledns.resolve" · "qrserver.create" · "social-boost.catalog"

capabilityPoliciesmap<string, enum<string>>

Per-capability permission policy map; omitted when no entries exist. always_allow: invoke without user confirmation. always_ask: prompt the session owner before every invocation. auto: reserved for future policy evaluation; currently prompts the session owner like always_ask. — "always_allow" · "always_ask" · "auto"

nativeToolPolicyenum<string>

Native pod-tool permission, independent of capabilities. Returned on create and detail responses; omitted legacy settings mean always_allow. Only the agent owner can change it, while sessions are idle. — "always_allow" · "always_ask"

hiringPolicyenum<string>

Whether this agent's sessions may bring in other agents as helpers. allow unless set to deny. Returned on create and detail responses. — "allow" · "deny"

mcpServersobject[]

Declared remote MCP server references, including tool filters; runtime authentication fields are never returned

▸ Show child attributes
type"url"

default: "url"

namestringrequired

max length 255

urlstringrequired
toolsobject
▸ Show child attributes
includestring[]

default: []

excludestring[]

default: []

hooksobject[]

Shell commands run in the session's pod at lifecycle events

▸ Show child attributes
eventenum<string>required

"pre_session_start" · "session_start" · "user_prompt_submit" · "pre_tool_use" · "post_tool_use" · "stop" · "session_end"

commandstringrequired

max length 4000

matcherstring

max length 255

timeout_sinteger
metadataobject

Your key-merged client metadata

environmentIdstring | null

The environment sessions of this agent boot in when their create names none; ahead of the workspace default

vaultIdstring | null

The vault every session of this agent carries, after the vaults its create names and ahead of the workspace default

defaultSessionIdstring | null

The session conversation verbs target when addressed by agent id

universestring

Resolved universe slug

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/agents/agent_cmtb2f0a8m9k7x51q4ez6r0d' \
  -H "Authorization: Bearer ast_..."
PATCH/agents/{id}write

Update displayName / capabilities / metadata

Omitted fields preserved; capabilities replaced whole (explicit [] revokes all; effective on the next capability call, no restart); metadata key-merged (null deletes a key); optional expectedVersion → 409 version_conflict on mismatch.

Path parameters

idstringrequired

The agent id (agent_…)

Body · application/json

displayNamestring

max length 60

capabilitiesenum<string>[]

"embedding.openai" · "embedding.voyage" · "rerank.voyage" · "ocr.mistral" · "exa.search" · "exa.contents" · "tinyfish.fetch" · "tinyfish.browser" · "tinyfish.agent" · "dataforseo.serp" · "dataforseo.ai-keywords" · "dataforseo.llm-responses" · "dataforseo.app-info" · "dataforseo.app-search" · "dataforseo.backlinks" · "dataforseo.business-reviews" · "dataforseo.business-pinterest" · "dataforseo.content-analysis" · "dataforseo.technologies" · "dataforseo.keyword-data" · "dataforseo.labs" · "dataforseo.amazon" · "dataforseo.onpage" · "gptimage.generate" · "rembg.remove-background" · "seedance.generate" · "mm.i2v" · "wan.t2v" · "wan.i2v" · "happyhorse.t2v" · "minimax.h3" · "fish-audio.transcribe" · "code-review" · "exa.answer" · "googlemap.geocode" · "googlemap.places" · "agentmail.list-inboxes" · "tinyfish.search" · "tinyfish.profile-list" · "meta.transcribe" · "minimax.tts" · "elevenlabs.sound" · "zai.transcribe" · "openai.transcribe" · "fish-audio.tts" · "google.image" · "openai.image-2.5" · "wan.image" · "logo.lookup" · "openmeteo.weather" · "frankfurter.fx" · "dictionary.define" · "openlibrary.search" · "googledns.resolve" · "qrserver.create" · "social-boost.catalog"

metadatamap<string, any>
environmentIdstring | null

The environment sessions of this agent boot in when they name none; null clears, omitted preserves. Applies to sessions created afterwards.

vaultIdstring | null

The vault every session of this agent carries; null clears, omitted preserves. Applies to sessions created afterwards.

capabilityPoliciesmap<string, enum<string>>

"always_allow" · "always_ask" · "auto"

nativeToolPolicyenum<string>

Owner-only permission for native pod tools. Omitted preserves; changing permission requires idle sessions. There is no session override. — "always_allow" · "always_ask"

hiringPolicyenum<string>

Whether this agent's sessions may bring in other agents as helpers. Omitted preserves. deny refuses the next helper a session tries to start; sessions created afterwards are not told how to hire. — "allow" · "deny"

harnessVersionstring
reasoningEffortenum<string> | null

Harness-native reasoning effort; null clears the pin and applies model-compatible normalization. Applies from the next provision/restart. Allowed values depend on agentType — agoragentic_acp: not supported; amp_acp: not supported; auggie: not supported; autohand: not supported; cline: not supported; codebuddy_code: not supported; cortex_code: not supported; corust_agent: not supported; crow_cli: not supported; cursor: not supported; deepagents: not supported; devin: not supported; dimcode: not supported; dirac: not supported; factory_droid: not supported; fast_agent: not supported; gemini: not supported; github_copilot_cli: not supported; glm_acp_agent: not supported; antigravity_acp: not supported; goose: not supported; grok_build: not supported; harn: not supported; junie: not supported; kilo: not supported; kimchi: not supported; minimax_code: not supported; minion_code: not supported; mistral_vibe: not supported; nova: not supported; poolside: not supported; qoder: not supported; qwen_code: not supported; sigit: not supported; stakpak: not supported; vtcode: not supported; code_assistant: not supported; docker_cagent: not supported; kiro: not supported; muse_code: not supported; openhands: not supported; hermes: none/minimal/low/medium/high/xhigh/max/ultra; claude_code: low/medium/high/xhigh/max; codex: none/minimal/low/medium/high/xhigh/max; openclaw: not supported; jev: not supported; pi: off/minimal/low/medium/high/xhigh/max; dsh: not supported; kimi_code: not supported; opencode: none/minimal/low/medium/high/xhigh/max; workspace_acp: not supported; models: claude-haiku-4-5: not supported; gemini-3.8-flash: low/medium/high; gemini-3.5-flash: low/medium/high; glm-5.3: low/high/max; glm-5.3-flash: low/high/max; grok-4.6: low/medium/high; grok-4.7: low/medium/high/xhigh; codex/hermes + gpt-6.1-sol: low/medium/high/xhigh/max — "none" · "off" · "minimal" · "low" · "medium" · "high" · "xhigh" · "max" · "ultra"

skillsobject[]

Replaces the whole skills array; omitted preserves. Applies from the next provision.

▸ Show child attributes
type: "skill"object
▸ Show child attributes
type"skill"required
skillIdstringrequired
versionstring

default: "latest"

type: "github"object
▸ Show child attributes
type"github"required
urlstringrequired
refstring

Branch or commit SHA; default branch when omitted.

tokenSecretRefstring

Agent secret key holding a clone token for private repos.

mcpServersobject[]

Replaces the whole MCP server list; omitted preserves. Applies from the next provision.

▸ Show child attributes
type"url"

default: "url"

namestringrequired

max length 255

urlstringrequired
toolsobject
▸ Show child attributes
includestring[]

default: []

excludestring[]

default: []

hooksobject[]

Replaces the whole hook list; omitted preserves. Applies from the next provision.

▸ Show child attributes
eventenum<string>required

"pre_session_start" · "session_start" · "user_prompt_submit" · "pre_tool_use" · "post_tool_use" · "stop" · "session_end"

commandstringrequired

max length 4000

matcherstring

max length 255

timeout_sinteger
expectedVersioninteger

Response · 200

agentobjectrequired

Everything in the list item, plus configuration state.

▸ Show child attributes
idstring

The agent id (agent_…) — the only address

namestring
displayNamestring
agentTypestring
llmstring
harnessVersionstring | null
reasoningEffortstring | null

"none" · "off" · "minimal" · "low" · "medium" · "high" · "xhigh" · "max" · "ultra" · null

versioninteger
archivedboolean
sessionCountinteger
createdAtstring
descriptionstring | null
promptstring | null

The user prompt layer

promptVersioninteger | null
capabilitiesenum<string>[]

The built-in capabilities this agent is granted — the exact set its sessions may execute (enforced; empty = none). Ids are listed at /docs/capabilities. — "embedding.openai" · "embedding.voyage" · "rerank.voyage" · "ocr.mistral" · "exa.search" · "exa.contents" · "tinyfish.fetch" · "tinyfish.browser" · "tinyfish.agent" · "dataforseo.serp" · "dataforseo.ai-keywords" · "dataforseo.llm-responses" · "dataforseo.app-info" · "dataforseo.app-search" · "dataforseo.backlinks" · "dataforseo.business-reviews" · "dataforseo.business-pinterest" · "dataforseo.content-analysis" · "dataforseo.technologies" · "dataforseo.keyword-data" · "dataforseo.labs" · "dataforseo.amazon" · "dataforseo.onpage" · "gptimage.generate" · "rembg.remove-background" · "seedance.generate" · "mm.i2v" · "wan.t2v" · "wan.i2v" · "happyhorse.t2v" · "minimax.h3" · "fish-audio.transcribe" · "code-review" · "exa.answer" · "googlemap.geocode" · "googlemap.places" · "agentmail.list-inboxes" · "tinyfish.search" · "tinyfish.profile-list" · "meta.transcribe" · "minimax.tts" · "elevenlabs.sound" · "zai.transcribe" · "openai.transcribe" · "fish-audio.tts" · "google.image" · "openai.image-2.5" · "wan.image" · "logo.lookup" · "openmeteo.weather" · "frankfurter.fx" · "dictionary.define" · "openlibrary.search" · "googledns.resolve" · "qrserver.create" · "social-boost.catalog"

capabilityPoliciesmap<string, enum<string>>

Per-capability permission policy map; omitted when no entries exist. always_allow: invoke without user confirmation. always_ask: prompt the session owner before every invocation. auto: reserved for future policy evaluation; currently prompts the session owner like always_ask. — "always_allow" · "always_ask" · "auto"

nativeToolPolicyenum<string>

Native pod-tool permission, independent of capabilities. Returned on create and detail responses; omitted legacy settings mean always_allow. Only the agent owner can change it, while sessions are idle. — "always_allow" · "always_ask"

hiringPolicyenum<string>

Whether this agent's sessions may bring in other agents as helpers. allow unless set to deny. Returned on create and detail responses. — "allow" · "deny"

mcpServersobject[]

Declared remote MCP server references, including tool filters; runtime authentication fields are never returned

▸ Show child attributes
type"url"

default: "url"

namestringrequired

max length 255

urlstringrequired
toolsobject
▸ Show child attributes
includestring[]

default: []

excludestring[]

default: []

hooksobject[]

Shell commands run in the session's pod at lifecycle events

▸ Show child attributes
eventenum<string>required

"pre_session_start" · "session_start" · "user_prompt_submit" · "pre_tool_use" · "post_tool_use" · "stop" · "session_end"

commandstringrequired

max length 4000

matcherstring

max length 255

timeout_sinteger
metadataobject

Your key-merged client metadata

environmentIdstring | null

The environment sessions of this agent boot in when their create names none; ahead of the workspace default

vaultIdstring | null

The vault every session of this agent carries, after the vaults its create names and ahead of the workspace default

defaultSessionIdstring | null

The session conversation verbs target when addressed by agent id

universestring

Resolved universe slug

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PATCH https://api.agentsky.dev/v1/agents/agent_cmtb2f0a8m9k7x51q4ez6r0d \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"displayName":"Research Agent","expectedVersion":1}'
DELETE/agents/{id}admin

Delete the agent — only with zero sessions (409 agent_has_sessions)

Path parameters

idstringrequired

The agent id (agent_…)

Response · 200

oktruerequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/agents/agent_cmtb2f0a8m9k7x51q4ez6r0d \
  -H "Authorization: Bearer ast_..."

Archive the agent — read-only, sessions keep running, new sessions rejected

Path parameters

idstringrequired

The agent id (agent_…)

Response · 200

agentobjectrequired

Everything in the list item, plus configuration state.

▸ Show child attributes
idstring

The agent id (agent_…) — the only address

namestring
displayNamestring
agentTypestring
llmstring
harnessVersionstring | null
reasoningEffortstring | null

"none" · "off" · "minimal" · "low" · "medium" · "high" · "xhigh" · "max" · "ultra" · null

versioninteger
archivedboolean
sessionCountinteger
createdAtstring
descriptionstring | null
promptstring | null

The user prompt layer

promptVersioninteger | null
capabilitiesenum<string>[]

The built-in capabilities this agent is granted — the exact set its sessions may execute (enforced; empty = none). Ids are listed at /docs/capabilities. — "embedding.openai" · "embedding.voyage" · "rerank.voyage" · "ocr.mistral" · "exa.search" · "exa.contents" · "tinyfish.fetch" · "tinyfish.browser" · "tinyfish.agent" · "dataforseo.serp" · "dataforseo.ai-keywords" · "dataforseo.llm-responses" · "dataforseo.app-info" · "dataforseo.app-search" · "dataforseo.backlinks" · "dataforseo.business-reviews" · "dataforseo.business-pinterest" · "dataforseo.content-analysis" · "dataforseo.technologies" · "dataforseo.keyword-data" · "dataforseo.labs" · "dataforseo.amazon" · "dataforseo.onpage" · "gptimage.generate" · "rembg.remove-background" · "seedance.generate" · "mm.i2v" · "wan.t2v" · "wan.i2v" · "happyhorse.t2v" · "minimax.h3" · "fish-audio.transcribe" · "code-review" · "exa.answer" · "googlemap.geocode" · "googlemap.places" · "agentmail.list-inboxes" · "tinyfish.search" · "tinyfish.profile-list" · "meta.transcribe" · "minimax.tts" · "elevenlabs.sound" · "zai.transcribe" · "openai.transcribe" · "fish-audio.tts" · "google.image" · "openai.image-2.5" · "wan.image" · "logo.lookup" · "openmeteo.weather" · "frankfurter.fx" · "dictionary.define" · "openlibrary.search" · "googledns.resolve" · "qrserver.create" · "social-boost.catalog"

capabilityPoliciesmap<string, enum<string>>

Per-capability permission policy map; omitted when no entries exist. always_allow: invoke without user confirmation. always_ask: prompt the session owner before every invocation. auto: reserved for future policy evaluation; currently prompts the session owner like always_ask. — "always_allow" · "always_ask" · "auto"

nativeToolPolicyenum<string>

Native pod-tool permission, independent of capabilities. Returned on create and detail responses; omitted legacy settings mean always_allow. Only the agent owner can change it, while sessions are idle. — "always_allow" · "always_ask"

hiringPolicyenum<string>

Whether this agent's sessions may bring in other agents as helpers. allow unless set to deny. Returned on create and detail responses. — "allow" · "deny"

mcpServersobject[]

Declared remote MCP server references, including tool filters; runtime authentication fields are never returned

▸ Show child attributes
type"url"

default: "url"

namestringrequired

max length 255

urlstringrequired
toolsobject
▸ Show child attributes
includestring[]

default: []

excludestring[]

default: []

hooksobject[]

Shell commands run in the session's pod at lifecycle events

▸ Show child attributes
eventenum<string>required

"pre_session_start" · "session_start" · "user_prompt_submit" · "pre_tool_use" · "post_tool_use" · "stop" · "session_end"

commandstringrequired

max length 4000

matcherstring

max length 255

timeout_sinteger
metadataobject

Your key-merged client metadata

environmentIdstring | null

The environment sessions of this agent boot in when their create names none; ahead of the workspace default

vaultIdstring | null

The vault every session of this agent carries, after the vaults its create names and ahead of the workspace default

defaultSessionIdstring | null

The session conversation verbs target when addressed by agent id

universestring

Resolved universe slug

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/agents/agent_cmtb2f0a8m9k7x51q4ez6r0d/archive \
  -H "Authorization: Bearer ast_..."

Save the user prompt layer; applies to sessions started after the save

Path parameters

idstringrequired

The agent id (agent_…)

Body · application/json

promptstringrequired

max length 100000

Response · 200

versioninteger
unchangedboolean

Content identical to the active version

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PUT https://api.agentsky.dev/v1/agents/agent_cmtb2f0a8m9k7x51q4ez6r0d/prompt \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"prompt":"You are a meticulous research agent…"}'

Prompt version history

Path parameters

idstringrequired

The agent id (agent_…)

Response · 200

versionsobject[]required
▸ Show child attributes
versioninteger
notestring | null
createdAtstring
activeboolean
contentstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/agents/agent_cmtb2f0a8m9k7x51q4ez6r0d/prompt/versions' \
  -H "Authorization: Bearer ast_..."

Declared secret keys + set/unset — never values

Path parameters

idstringrequired

The agent id (agent_…)

Response · 200

secretsobject[]required
▸ Show child attributes
keystring
descriptionstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/agents/agent_cmtb2f0a8m9k7x51q4ez6r0d/secrets' \
  -H "Authorization: Bearer ast_..."

Set a declared secret's value (write-only)

Path parameters

idstringrequired

The agent id (agent_…)

keystringrequired

Body · application/json

valuestringrequired

max length 10000

descriptionstring

max length 500

Response · 200

oktruerequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PUT https://api.agentsky.dev/v1/agents/agent_cmtb2f0a8m9k7x51q4ez6r0d/secrets/NOTION_TOKEN \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"value":"secret_…"}'

Unset a secret

Path parameters

idstringrequired

The agent id (agent_…)

keystringrequired

Response · 200

oktruerequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/agents/agent_cmtb2f0a8m9k7x51q4ez6r0d/secrets/NOTION_TOKEN \
  -H "Authorization: Bearer ast_..."

Skills

GET/skillsread

List skills in the resolved universe

Query parameters

cursorstring
limitinteger

Response · 200

skillsobject[]required
▸ Show child attributes
idstringrequired
displayNamestringrequired
latestRevisionIdstring | nullrequired

What `latest` references resolve to.

attachByDefaultbooleanrequired

Whether every new session in the workspace starts with this skill's latest revision.

createdAtstringrequired
updatedAtstringrequired
nextCursorstring | null

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/skills' \
  -H "Authorization: Bearer ast_..."
POST/skillswrite

Create a skill (uploads revision 1)

A skill is a universe-scoped, immutably-revisioned file bundle agents load on demand (RFC-0073). Attach it to agents via the `skills` array on create/patch.

Response · 201

skillobjectrequired
▸ Show child attributes
idstringrequired
displayNamestringrequired
latestRevisionIdstring | nullrequired

What `latest` references resolve to.

attachByDefaultbooleanrequired

Whether every new session in the workspace starts with this skill's latest revision.

createdAtstringrequired
updatedAtstringrequired
revisionobjectrequired
▸ Show child attributes
idstringrequired
skillIdstringrequired
namestringrequired

Frontmatter name — the skill's identity name.

descriptionstringrequired
filesobject[]required
▸ Show child attributes
pathstringrequired
sizeintegerrequired
sha256stringrequired
executablebooleanrequired
createdAtstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/skills \
  -H "Authorization: Bearer ast_..."

Skill detail

Path parameters

skillIdstringrequired

The skill id (skill_…)

Response · 200

skillobjectrequired
▸ Show child attributes
idstringrequired
displayNamestringrequired
latestRevisionIdstring | nullrequired

What `latest` references resolve to.

attachByDefaultbooleanrequired

Whether every new session in the workspace starts with this skill's latest revision.

createdAtstringrequired
updatedAtstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/skills/skillId' \
  -H "Authorization: Bearer ast_..."

Make a skill always available, or stop

With `attachByDefault: true`, every session created in the workspace from then on is provisioned with the skill's latest revision, unless the session is created with `defaults: "none"`. Sessions of agents that cannot take skills start without it.

Path parameters

skillIdstringrequired

The skill id (skill_…)

Body · application/json

attachByDefaultbooleanrequired

Response · 200

skillobjectrequired
▸ Show child attributes
idstringrequired
displayNamestringrequired
latestRevisionIdstring | nullrequired

What `latest` references resolve to.

attachByDefaultbooleanrequired

Whether every new session in the workspace starts with this skill's latest revision.

createdAtstringrequired
updatedAtstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PATCH https://api.agentsky.dev/v1/skills/skillId \
  -H "Authorization: Bearer ast_..."

Delete a skill and all its revisions

409 skill_in_use while any agent references the skill.

Path parameters

skillIdstringrequired

The skill id (skill_…)

Response · 200

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/skills/skillId \
  -H "Authorization: Bearer ast_..."

List a skill's revisions, newest first

Path parameters

skillIdstringrequired

The skill id (skill_…)

Response · 200

revisionsobject[]required
▸ Show child attributes
idstringrequired
skillIdstringrequired
namestringrequired

Frontmatter name — the skill's identity name.

descriptionstringrequired
filesobject[]required
▸ Show child attributes
pathstringrequired
sizeintegerrequired
sha256stringrequired
executablebooleanrequired
createdAtstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/skills/skillId/revisions' \
  -H "Authorization: Bearer ast_..."

Create a revision — a complete snapshot

Omitted files are not carried over. The new SKILL.md name must match the skill's name (400 name_mismatch).

Response · 201

revisionobjectrequired
▸ Show child attributes
idstringrequired
skillIdstringrequired
namestringrequired

Frontmatter name — the skill's identity name.

descriptionstringrequired
filesobject[]required
▸ Show child attributes
pathstringrequired
sizeintegerrequired
sha256stringrequired
executablebooleanrequired
createdAtstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/skills/skillId/revisions \
  -H "Authorization: Bearer ast_..."

Skill revision detail (metadata + file manifest)

Path parameters

skillIdstringrequired

The skill id (skill_…)

revisionIdstringrequired

The skill revision id (skr_…)

Response · 200

revisionobjectrequired
▸ Show child attributes
idstringrequired
skillIdstringrequired
namestringrequired

Frontmatter name — the skill's identity name.

descriptionstringrequired
filesobject[]required
▸ Show child attributes
pathstringrequired
sizeintegerrequired
sha256stringrequired
executablebooleanrequired
createdAtstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/skills/skillId/revisions/revisionId' \
  -H "Authorization: Bearer ast_..."

Delete one revision

400 last_revision for a skill's only revision; 409 revision_in_use while pinned by an agent; deleting the latest repoints latestRevisionId.

Path parameters

skillIdstringrequired

The skill id (skill_…)

revisionIdstringrequired

The skill revision id (skr_…)

Response · 200

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/skills/skillId/revisions/revisionId \
  -H "Authorization: Bearer ast_..."

Read a UTF-8 skill file

Reads only a file in the authorized immutable revision. Binary files return 415; absent files return 404. Responses are not cached.

Path parameters

skillIdstringrequired

The skill id (skill_…)

revisionIdstringrequired

The skill revision id (skr_…)

Query parameters

pathstringrequired

Exact relative file path, such as SKILL.md

Response · 200

pathstringrequired
contentstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/skills/skillId/revisions/revisionId/content?path=report.md' \
  -H "Authorization: Bearer ast_..."

Files

POST/fileswrite

Upload a file — universe-scoped; images are readable back, other uploads are write-once

multipart/form-data with a `file` part and an optional `expires_in_seconds` (3600–7776000). 32 MiB per file (413 file_too_large). Reference the returned id from a message as `{"type":"image","source":{"type":"file","file_id":"file_…"}}` or a `document` block.

Response · 200

typeenum<string>required

"file"

idstringrequired

file_…

created_atstringrequired
filenamestringrequired
mime_typestringrequired
size_bytesintegerrequired
downloadablebooleanrequired

true for image uploads (readable within the workspace) and for the per-session copies minted when a file rides a message; false for other uploads (write-once)

attach_by_defaultbooleanrequired

Whether every new session in the workspace starts with a read-only copy under /workspace/shared/

expires_atstring | nullrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/files \
  -H "Authorization: Bearer ast_..." \
  -F "file=@report.pdf"
Response · 200 OK
{
  "type": "file",
  "id": "file_cmtb9x4p",
  "created_at": "2026-09-10T18:00:00.000Z",
  "filename": "design.pdf",
  "mime_type": "application/pdf",
  "size_bytes": 102400,
  "downloadable": false,
  "expires_at": null
}
GET/filesread

List files — your universe's uploads, or one session's files

Without `scope_id`, the universe's uploads. `scope_id=sess_…` lists that session's files: the copies minted from message content, channel attachments, and agent-stored files. `ids[]` (≤100) returns exactly those files in one page and cannot be combined with page/limit.

Query parameters

limitinteger
pagestring

A next_page cursor

ids[]array
scope_idstring

sess_…

Response · 200

dataobject[]required

Newest first

▸ Show child attributes
typeenum<string>required

"file"

idstringrequired

file_…

created_atstringrequired
filenamestringrequired
mime_typestringrequired
size_bytesintegerrequired
downloadablebooleanrequired

true for image uploads (readable within the workspace) and for the per-session copies minted when a file rides a message; false for other uploads (write-once)

attach_by_defaultbooleanrequired

Whether every new session in the workspace starts with a read-only copy under /workspace/shared/

expires_atstring | nullrequired
next_pagestring | nullrequired

Pass back as ?page= for the next page

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/files' \
  -H "Authorization: Bearer ast_..."
Response · 200 OK
{
  "data": [
    {
      "type": "file",
      "id": "file_cmtb9x4p",
      "created_at": "2026-09-10T18:00:00.000Z",
      "filename": "design.pdf",
      "mime_type": "application/pdf",
      "size_bytes": 102400,
      "downloadable": false,
      "expires_at": null
    }
  ],
  "next_page": null
}

File metadata

Path parameters

file_idstringrequired

The file id (file_…)

Response · 200

typeenum<string>required

"file"

idstringrequired

file_…

created_atstringrequired
filenamestringrequired
mime_typestringrequired
size_bytesintegerrequired
downloadablebooleanrequired

true for image uploads (readable within the workspace) and for the per-session copies minted when a file rides a message; false for other uploads (write-once)

attach_by_defaultbooleanrequired

Whether every new session in the workspace starts with a read-only copy under /workspace/shared/

expires_atstring | nullrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/files/file_cmtb9x4p' \
  -H "Authorization: Bearer ast_..."

Make an upload always available, or stop

With `attach_by_default: true`, every session created in the workspace from then on starts with a read-only copy at `/workspace/shared/<filename>`, unless the session is created with `defaults: "none"`. Only a workspace upload that does not expire can carry the flag (400 otherwise). A file whose name is already taken in a session, or that would take the set past 64 MiB or 50 files, is skipped for that session; the session still starts.

Path parameters

file_idstringrequired

The file id (file_…)

Body · application/json

attach_by_defaultbooleanrequired

Response · 200

typeenum<string>required

"file"

idstringrequired

file_…

created_atstringrequired
filenamestringrequired
mime_typestringrequired
size_bytesintegerrequired
downloadablebooleanrequired

true for image uploads (readable within the workspace) and for the per-session copies minted when a file rides a message; false for other uploads (write-once)

attach_by_defaultbooleanrequired

Whether every new session in the workspace starts with a read-only copy under /workspace/shared/

expires_atstring | nullrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PATCH https://api.agentsky.dev/v1/files/file_cmtb9x4p \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"attach_by_default":true}'
DELETE/files/{file_id}write

Delete a file

Soft delete: the file stops resolving everywhere; sessions that already received a copy keep it.

Path parameters

file_idstringrequired

The file id (file_…)

Response · 200

typeenum<string>required

"file_deleted"

idstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/files/file_cmtb9x4p \
  -H "Authorization: Bearer ast_..."
Response · 200 OK
{
  "type": "file_deleted",
  "id": "file_cmtb9x4p"
}

Download a file's bytes

Only `downloadable` files (an image upload, readable within the workspace, and every session-scoped file: message copies, channel attachments, agent outputs); other uploads answer 400 not_downloadable. 404 once the file has expired.

Path parameters

file_idstringrequired

The file id (file_…)

Response · 200

The bytes, with content-type and content-disposition

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/files/file_cmtb9x4p/content' \
  -H "Authorization: Bearer ast_..."

Environments

List the universe's environments, oldest first

Response · 200

environmentsobject[]required
▸ Show child attributes
idstringrequired

env_…

namestringrequired
configobjectrequired

`packages` are installed into the image at build time — an environment is built when it is created and rebuilt when its config changes, so a session starting from it pays no install cost. `networking` is the egress policy its sessions run under; `limited` needs `allow_package_managers` when packages are declared, or the install could never succeed.

▸ Show child attributes
type"cloud"

default: "cloud"

packagesobject
▸ Show child attributes
aptstring[]

default: [] — max length 512

pipstring[]

default: [] — max length 512

npmstring[]

default: [] — max length 512

networkingobject
▸ Show child attributes
type: "unrestricted"object
▸ Show child attributes
type"unrestricted"required
type: "limited"object
▸ Show child attributes
type"limited"required
allowed_hostsstring[]

default: [] — max length 253 — pattern ^(\*\.)?([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?$

allow_mcp_serversboolean

default: false

allow_package_managersboolean

default: false

is_defaultbooleanrequired

Whether a new session that names no environment uses this one. At most one per workspace; setting it on one clears it on the others.

extendsstring | nullrequired

The env_… id of the parent environment this one extends, or null. Immutable after create. Child packages, tools.disabled and networking compose on the parent's at write time.

created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/environments' \
  -H "Authorization: Bearer ast_..."
POST/environmentswrite

Create an environment

The image build starts immediately; the environment is usable as `environment_id` on POST /sessions as soon as it exists, and a session created against a still-building environment waits for the build. Supplying `extends` (an `env_…` id in the same workspace) composes packages, tools.disabled and networking from the parent at write time and records the lineage. `extends` is immutable after create; chain depth is capped at 16.

Body · application/json

namestringrequired

max length 128

configobject

default: {"type":"cloud"}

▸ Show child attributes
type"cloud"

default: "cloud"

packagesobject
▸ Show child attributes
aptstring[]

default: [] — max length 512

pipstring[]

default: [] — max length 512

npmstring[]

default: [] — max length 512

networkingobject
▸ Show child attributes
type: "unrestricted"object
▸ Show child attributes
type"unrestricted"required
type: "limited"object
▸ Show child attributes
type"limited"required
allowed_hostsstring[]

default: [] — max length 253 — pattern ^(\*\.)?([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?$

allow_mcp_serversboolean

default: false

allow_package_managersboolean

default: false

extendsstring

Response · 201

environmentobjectrequired
▸ Show child attributes
idstringrequired

env_…

namestringrequired
configobjectrequired

`packages` are installed into the image at build time — an environment is built when it is created and rebuilt when its config changes, so a session starting from it pays no install cost. `networking` is the egress policy its sessions run under; `limited` needs `allow_package_managers` when packages are declared, or the install could never succeed.

▸ Show child attributes
type"cloud"

default: "cloud"

packagesobject
▸ Show child attributes
aptstring[]

default: [] — max length 512

pipstring[]

default: [] — max length 512

npmstring[]

default: [] — max length 512

networkingobject
▸ Show child attributes
type: "unrestricted"object
▸ Show child attributes
type"unrestricted"required
type: "limited"object
▸ Show child attributes
type"limited"required
allowed_hostsstring[]

default: [] — max length 253 — pattern ^(\*\.)?([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?$

allow_mcp_serversboolean

default: false

allow_package_managersboolean

default: false

is_defaultbooleanrequired

Whether a new session that names no environment uses this one. At most one per workspace; setting it on one clears it on the others.

extendsstring | nullrequired

The env_… id of the parent environment this one extends, or null. Immutable after create. Child packages, tools.disabled and networking compose on the parent's at write time.

created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/environments \
  -H "Authorization: Bearer ast_..."

One environment

Path parameters

idstringrequired

The environment id (env_…)

Response · 200

environmentobjectrequired
▸ Show child attributes
idstringrequired

env_…

namestringrequired
configobjectrequired

`packages` are installed into the image at build time — an environment is built when it is created and rebuilt when its config changes, so a session starting from it pays no install cost. `networking` is the egress policy its sessions run under; `limited` needs `allow_package_managers` when packages are declared, or the install could never succeed.

▸ Show child attributes
type"cloud"

default: "cloud"

packagesobject
▸ Show child attributes
aptstring[]

default: [] — max length 512

pipstring[]

default: [] — max length 512

npmstring[]

default: [] — max length 512

networkingobject
▸ Show child attributes
type: "unrestricted"object
▸ Show child attributes
type"unrestricted"required
type: "limited"object
▸ Show child attributes
type"limited"required
allowed_hostsstring[]

default: [] — max length 253 — pattern ^(\*\.)?([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?$

allow_mcp_serversboolean

default: false

allow_package_managersboolean

default: false

is_defaultbooleanrequired

Whether a new session that names no environment uses this one. At most one per workspace; setting it on one clears it on the others.

extendsstring | nullrequired

The env_… id of the parent environment this one extends, or null. Immutable after create. Child packages, tools.disabled and networking compose on the parent's at write time.

created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/environments/sess_cmtb7q2j' \
  -H "Authorization: Bearer ast_..."

Rename an environment or change its config

Omitted fields are left as they are. A changed `config` rebuilds the image; sessions already running keep the image they started on.

Path parameters

idstringrequired

The environment id (env_…)

Body · application/json

namestring

max length 128

configobject
▸ Show child attributes
type"cloud"

default: "cloud"

packagesobject
▸ Show child attributes
aptstring[]

default: [] — max length 512

pipstring[]

default: [] — max length 512

npmstring[]

default: [] — max length 512

networkingobject
▸ Show child attributes
type: "unrestricted"object
▸ Show child attributes
type"unrestricted"required
type: "limited"object
▸ Show child attributes
type"limited"required
allowed_hostsstring[]

default: [] — max length 253 — pattern ^(\*\.)?([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?$

allow_mcp_serversboolean

default: false

allow_package_managersboolean

default: false

Response · 200

environmentobjectrequired
▸ Show child attributes
idstringrequired

env_…

namestringrequired
configobjectrequired

`packages` are installed into the image at build time — an environment is built when it is created and rebuilt when its config changes, so a session starting from it pays no install cost. `networking` is the egress policy its sessions run under; `limited` needs `allow_package_managers` when packages are declared, or the install could never succeed.

▸ Show child attributes
type"cloud"

default: "cloud"

packagesobject
▸ Show child attributes
aptstring[]

default: [] — max length 512

pipstring[]

default: [] — max length 512

npmstring[]

default: [] — max length 512

networkingobject
▸ Show child attributes
type: "unrestricted"object
▸ Show child attributes
type"unrestricted"required
type: "limited"object
▸ Show child attributes
type"limited"required
allowed_hostsstring[]

default: [] — max length 253 — pattern ^(\*\.)?([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?$

allow_mcp_serversboolean

default: false

allow_package_managersboolean

default: false

is_defaultbooleanrequired

Whether a new session that names no environment uses this one. At most one per workspace; setting it on one clears it on the others.

extendsstring | nullrequired

The env_… id of the parent environment this one extends, or null. Immutable after create. Child packages, tools.disabled and networking compose on the parent's at write time.

created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PATCH https://api.agentsky.dev/v1/environments/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."

Delete an environment

Path parameters

idstringrequired

The environment id (env_…)

Response · 204

Deleted — no body

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/environments/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."

Publish one of your own environments as a listing

Creates or replaces the listing for this environment on the shelf. The environment must belong to the caller's workspace. Answers 404 when the shelf is not enabled for this workspace or the environment is not found. Answers 503 `not_migrated` until the shelf migration is applied.

Path parameters

idstringrequired

The environment id (env_…)

Body · application/json

handlestringrequired

2 to 40 lower-case letters, digits or underscores; unique across environment listings

namestringrequired

max length 128

taglinestring

max length 140

descriptionstring

max length 4000

categoriesenum<string>[]

Defaults to general — "development" · "data" · "ml" · "security" · "web" · "general"

visibilityenum<string>

Only workspace is supported in this release — "workspace" — default: "workspace"

Response · 200

listingobjectrequired
▸ Show child attributes
idstringrequired

The listing id (lst_…)

handlestringrequired

Globally unique within environment listings; lower-case letters, digits and underscores

namestringrequired
taglinestringrequired

One line, at most 140 characters

descriptionstringrequired
categoriesenum<string>[]required

"development" · "data" · "ml" · "security" · "web" · "general"

packagesobject | nullrequired

The listed environment's package configuration, or null when it has none

toolsobject | nullrequired

The listed environment's tool policy, or null when it has none

networkingobject | nullrequired

The listed environment's networking configuration, or null when it has none

installsintegerrequired

How many workspaces have installed this listing

sellerobjectrequired

The workspace that published the listing

▸ Show child attributes
namestringrequired
visibilityenum<string>required

workspace = visible only to the owning workspace; public = visible to all — "workspace" · "public"

conformancenullrequired

Reserved; always null in this release

created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PUT https://api.agentsky.dev/v1/environments/sess_cmtb7q2j/listing \
  -H "Authorization: Bearer ast_..."

Remove the listing for one of your own environments

Delists the environment; the environment itself and any installed copies in other workspaces are not touched. Answers 404 when the shelf is not enabled, the environment is not found, or it has no listing. Answers 503 `not_migrated` until the shelf migration is applied.

Path parameters

idstringrequired

The environment id (env_…)

Response · 204

Delisted

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/environments/sess_cmtb7q2j/listing \
  -H "Authorization: Bearer ast_..."

Harnesses

GET/harnessesread

List workspace harnesses, oldest first

Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.

Response · 200

harnessesobject[]required
▸ Show child attributes
idstringrequired

hrn_… — the public id

handlestringrequired

Short slug within the workspace (e.g. my-harness)

namestringrequired
profileobjectrequired

The runtime description of a workspace harness: the distribution spec (npx, uvx or binary), optional auth command, bundled MCP servers, tools, features and other catalog fields the installer reads when it builds the template image.

▸ Show child attributes
idstringrequired

pattern ^[a-z0-9][a-z0-9_-]{1,39}$

namestringrequired

max length 200

versionstringrequired

max length 128

distributionmap<string, any>required
auth_commandstring[]
bundled_mcp_serversmap<string, any>[]
configuration_filesmap<string, any>[]
credential_argsmap<string, any>
graceful_exit_timeout_secondsnumber
home_directoriesstring[]
managed_model_id_templatestring
native_provider_setupmap<string, any>
pipelinestring
prerequisitesmap<string, any>
request_timeout_secondsnumber
requirementsstring[]
session_close_before_exitboolean
session_config_optionsmap<string, any>
session_load_supportedboolean
session_parametersmap<string, any>
subscription_filesboolean
docker_targetstring
toolsobject[]
▸ Show child attributes
idstringrequired
kindstringrequired
titlestring
requiresmap<string, any>
featuresstring[]
model_billingenum<string>required

gateway: model calls are billed through the platform wallet. external: the harness manages billing itself. — "gateway" · "external"

created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/harnesses' \
  -H "Authorization: Bearer ast_..."
POST/harnesseswrite

Create a harness

Creates a workspace harness with the given handle, name and profile. After creating, add a version with POST /harnesses/{id}/versions, then promote it with POST /harnesses/{id}/versions/{v}/current before creating agents that reference it. Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.

Body · application/json

handlestringrequired

pattern ^[a-z0-9][a-z0-9-]{1,38}[a-z0-9]$

namestringrequired

max length 200

profileobjectrequired
▸ Show child attributes
idstringrequired

pattern ^[a-z0-9][a-z0-9_-]{1,39}$

namestringrequired

max length 200

versionstringrequired

max length 128

distributionmap<string, any>required
auth_commandstring[]
bundled_mcp_serversmap<string, any>[]
configuration_filesmap<string, any>[]
credential_argsmap<string, any>
graceful_exit_timeout_secondsnumber
home_directoriesstring[]
managed_model_id_templatestring
native_provider_setupmap<string, any>
pipelinestring
prerequisitesmap<string, any>
request_timeout_secondsnumber
requirementsstring[]
session_close_before_exitboolean
session_config_optionsmap<string, any>
session_load_supportedboolean
session_parametersmap<string, any>
subscription_filesboolean
docker_targetstring
toolsobject[]
▸ Show child attributes
idstringrequired
kindstringrequired
titlestring
requiresmap<string, any>
featuresstring[]
model_billingenum<string>

"gateway" · "external" — default: "external"

Response · 201

harnessobjectrequired
▸ Show child attributes
idstringrequired

hrn_… — the public id

handlestringrequired

Short slug within the workspace (e.g. my-harness)

namestringrequired
profileobjectrequired

The runtime description of a workspace harness: the distribution spec (npx, uvx or binary), optional auth command, bundled MCP servers, tools, features and other catalog fields the installer reads when it builds the template image.

▸ Show child attributes
idstringrequired

pattern ^[a-z0-9][a-z0-9_-]{1,39}$

namestringrequired

max length 200

versionstringrequired

max length 128

distributionmap<string, any>required
auth_commandstring[]
bundled_mcp_serversmap<string, any>[]
configuration_filesmap<string, any>[]
credential_argsmap<string, any>
graceful_exit_timeout_secondsnumber
home_directoriesstring[]
managed_model_id_templatestring
native_provider_setupmap<string, any>
pipelinestring
prerequisitesmap<string, any>
request_timeout_secondsnumber
requirementsstring[]
session_close_before_exitboolean
session_config_optionsmap<string, any>
session_load_supportedboolean
session_parametersmap<string, any>
subscription_filesboolean
docker_targetstring
toolsobject[]
▸ Show child attributes
idstringrequired
kindstringrequired
titlestring
requiresmap<string, any>
featuresstring[]
model_billingenum<string>required

gateway: model calls are billed through the platform wallet. external: the harness manages billing itself. — "gateway" · "external"

created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/harnesses \
  -H "Authorization: Bearer ast_..."

One harness

Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.

Path parameters

idstringrequired

The harness id (hrn_…)

Response · 200

harnessobjectrequired
▸ Show child attributes
idstringrequired

hrn_… — the public id

handlestringrequired

Short slug within the workspace (e.g. my-harness)

namestringrequired
profileobjectrequired

The runtime description of a workspace harness: the distribution spec (npx, uvx or binary), optional auth command, bundled MCP servers, tools, features and other catalog fields the installer reads when it builds the template image.

▸ Show child attributes
idstringrequired

pattern ^[a-z0-9][a-z0-9_-]{1,39}$

namestringrequired

max length 200

versionstringrequired

max length 128

distributionmap<string, any>required
auth_commandstring[]
bundled_mcp_serversmap<string, any>[]
configuration_filesmap<string, any>[]
credential_argsmap<string, any>
graceful_exit_timeout_secondsnumber
home_directoriesstring[]
managed_model_id_templatestring
native_provider_setupmap<string, any>
pipelinestring
prerequisitesmap<string, any>
request_timeout_secondsnumber
requirementsstring[]
session_close_before_exitboolean
session_config_optionsmap<string, any>
session_load_supportedboolean
session_parametersmap<string, any>
subscription_filesboolean
docker_targetstring
toolsobject[]
▸ Show child attributes
idstringrequired
kindstringrequired
titlestring
requiresmap<string, any>
featuresstring[]
model_billingenum<string>required

gateway: model calls are billed through the platform wallet. external: the harness manages billing itself. — "gateway" · "external"

created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/harnesses/sess_cmtb7q2j' \
  -H "Authorization: Bearer ast_..."
PATCH/harnesses/{id}write

Rename a harness or change its model_billing

Omitted fields are left unchanged. Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.

Path parameters

idstringrequired

The harness id (hrn_…)

Body · application/json

namestring

max length 200

model_billingenum<string>

"gateway" · "external"

Response · 200

harnessobjectrequired
▸ Show child attributes
idstringrequired

hrn_… — the public id

handlestringrequired

Short slug within the workspace (e.g. my-harness)

namestringrequired
profileobjectrequired

The runtime description of a workspace harness: the distribution spec (npx, uvx or binary), optional auth command, bundled MCP servers, tools, features and other catalog fields the installer reads when it builds the template image.

▸ Show child attributes
idstringrequired

pattern ^[a-z0-9][a-z0-9_-]{1,39}$

namestringrequired

max length 200

versionstringrequired

max length 128

distributionmap<string, any>required
auth_commandstring[]
bundled_mcp_serversmap<string, any>[]
configuration_filesmap<string, any>[]
credential_argsmap<string, any>
graceful_exit_timeout_secondsnumber
home_directoriesstring[]
managed_model_id_templatestring
native_provider_setupmap<string, any>
pipelinestring
prerequisitesmap<string, any>
request_timeout_secondsnumber
requirementsstring[]
session_close_before_exitboolean
session_config_optionsmap<string, any>
session_load_supportedboolean
session_parametersmap<string, any>
subscription_filesboolean
docker_targetstring
toolsobject[]
▸ Show child attributes
idstringrequired
kindstringrequired
titlestring
requiresmap<string, any>
featuresstring[]
model_billingenum<string>required

gateway: model calls are billed through the platform wallet. external: the harness manages billing itself. — "gateway" · "external"

created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PATCH https://api.agentsky.dev/v1/harnesses/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."
DELETE/harnesses/{id}write

Delete a harness

Deletes the harness and all its versions. Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.

Path parameters

idstringrequired

The harness id (hrn_…)

Response · 204

Deleted — no body

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/harnesses/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."

List versions for a harness, oldest first

Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.

Path parameters

idstringrequired

The harness id (hrn_…)

Response · 200

versionsobject[]required
▸ Show child attributes
idstringrequired

hrnv_… — internal version row id

harness_idstringrequired

hrn_… — the parent harness

versionstringrequired

Version string, e.g. v1-4096m

statusenum<string>required

pending: registered, build not started. building: E2B template build in progress. ready: build succeeded; can be promoted. current: the version agents are created against; at most one per harness. revoked: explicitly withdrawn; cannot be promoted or used for new sessions. — "pending" · "building" · "ready" · "current" · "revoked"

profileobjectrequired

The runtime description of a workspace harness: the distribution spec (npx, uvx or binary), optional auth command, bundled MCP servers, tools, features and other catalog fields the installer reads when it builds the template image.

▸ Show child attributes
idstringrequired

pattern ^[a-z0-9][a-z0-9_-]{1,39}$

namestringrequired

max length 200

versionstringrequired

max length 128

distributionmap<string, any>required
auth_commandstring[]
bundled_mcp_serversmap<string, any>[]
configuration_filesmap<string, any>[]
credential_argsmap<string, any>
graceful_exit_timeout_secondsnumber
home_directoriesstring[]
managed_model_id_templatestring
native_provider_setupmap<string, any>
pipelinestring
prerequisitesmap<string, any>
request_timeout_secondsnumber
requirementsstring[]
session_close_before_exitboolean
session_config_optionsmap<string, any>
session_load_supportedboolean
session_parametersmap<string, any>
subscription_filesboolean
docker_targetstring
toolsobject[]
▸ Show child attributes
idstringrequired
kindstringrequired
titlestring
requiresmap<string, any>
featuresstring[]
created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/harnesses/sess_cmtb7q2j/versions' \
  -H "Authorization: Bearer ast_..."

Register a new harness version

Registers the version string and triggers an E2B template build. Poll the version's status until it reaches ready, then promote with POST /harnesses/{id}/versions/{v}/current. If profile is omitted, the parent harness's profile is used. Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.

Path parameters

idstringrequired

The harness id (hrn_…)

Body · application/json

versionstringrequired

max length 128

profileobject
▸ Show child attributes
idstringrequired

pattern ^[a-z0-9][a-z0-9_-]{1,39}$

namestringrequired

max length 200

versionstringrequired

max length 128

distributionmap<string, any>required
auth_commandstring[]
bundled_mcp_serversmap<string, any>[]
configuration_filesmap<string, any>[]
credential_argsmap<string, any>
graceful_exit_timeout_secondsnumber
home_directoriesstring[]
managed_model_id_templatestring
native_provider_setupmap<string, any>
pipelinestring
prerequisitesmap<string, any>
request_timeout_secondsnumber
requirementsstring[]
session_close_before_exitboolean
session_config_optionsmap<string, any>
session_load_supportedboolean
session_parametersmap<string, any>
subscription_filesboolean
docker_targetstring
toolsobject[]
▸ Show child attributes
idstringrequired
kindstringrequired
titlestring
requiresmap<string, any>
featuresstring[]

Response · 201

versionobjectrequired
▸ Show child attributes
idstringrequired

hrnv_… — internal version row id

harness_idstringrequired

hrn_… — the parent harness

versionstringrequired

Version string, e.g. v1-4096m

statusenum<string>required

pending: registered, build not started. building: E2B template build in progress. ready: build succeeded; can be promoted. current: the version agents are created against; at most one per harness. revoked: explicitly withdrawn; cannot be promoted or used for new sessions. — "pending" · "building" · "ready" · "current" · "revoked"

profileobjectrequired

The runtime description of a workspace harness: the distribution spec (npx, uvx or binary), optional auth command, bundled MCP servers, tools, features and other catalog fields the installer reads when it builds the template image.

▸ Show child attributes
idstringrequired

pattern ^[a-z0-9][a-z0-9_-]{1,39}$

namestringrequired

max length 200

versionstringrequired

max length 128

distributionmap<string, any>required
auth_commandstring[]
bundled_mcp_serversmap<string, any>[]
configuration_filesmap<string, any>[]
credential_argsmap<string, any>
graceful_exit_timeout_secondsnumber
home_directoriesstring[]
managed_model_id_templatestring
native_provider_setupmap<string, any>
pipelinestring
prerequisitesmap<string, any>
request_timeout_secondsnumber
requirementsstring[]
session_close_before_exitboolean
session_config_optionsmap<string, any>
session_load_supportedboolean
session_parametersmap<string, any>
subscription_filesboolean
docker_targetstring
toolsobject[]
▸ Show child attributes
idstringrequired
kindstringrequired
titlestring
requiresmap<string, any>
featuresstring[]
created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/harnesses/sess_cmtb7q2j/versions \
  -H "Authorization: Bearer ast_..."

One harness version

Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.

Path parameters

idstringrequired

The harness id (hrn_…)

vstringrequired

The harness version string, e.g. v1-4096m

Response · 200

versionobjectrequired
▸ Show child attributes
idstringrequired

hrnv_… — internal version row id

harness_idstringrequired

hrn_… — the parent harness

versionstringrequired

Version string, e.g. v1-4096m

statusenum<string>required

pending: registered, build not started. building: E2B template build in progress. ready: build succeeded; can be promoted. current: the version agents are created against; at most one per harness. revoked: explicitly withdrawn; cannot be promoted or used for new sessions. — "pending" · "building" · "ready" · "current" · "revoked"

profileobjectrequired

The runtime description of a workspace harness: the distribution spec (npx, uvx or binary), optional auth command, bundled MCP servers, tools, features and other catalog fields the installer reads when it builds the template image.

▸ Show child attributes
idstringrequired

pattern ^[a-z0-9][a-z0-9_-]{1,39}$

namestringrequired

max length 200

versionstringrequired

max length 128

distributionmap<string, any>required
auth_commandstring[]
bundled_mcp_serversmap<string, any>[]
configuration_filesmap<string, any>[]
credential_argsmap<string, any>
graceful_exit_timeout_secondsnumber
home_directoriesstring[]
managed_model_id_templatestring
native_provider_setupmap<string, any>
pipelinestring
prerequisitesmap<string, any>
request_timeout_secondsnumber
requirementsstring[]
session_close_before_exitboolean
session_config_optionsmap<string, any>
session_load_supportedboolean
session_parametersmap<string, any>
subscription_filesboolean
docker_targetstring
toolsobject[]
▸ Show child attributes
idstringrequired
kindstringrequired
titlestring
requiresmap<string, any>
featuresstring[]
created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/harnesses/sess_cmtb7q2j/versions/v' \
  -H "Authorization: Bearer ast_..."

Promote a version to current

Marks this version as the current one for the harness. The previous current version moves back to ready. New agents created against this harness will pin this version. The version must be in ready or current status; a revoked version cannot be promoted. Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.

Path parameters

idstringrequired

The harness id (hrn_…)

vstringrequired

The harness version string, e.g. v1-4096m

Response · 200

versionobjectrequired
▸ Show child attributes
idstringrequired

hrnv_… — internal version row id

harness_idstringrequired

hrn_… — the parent harness

versionstringrequired

Version string, e.g. v1-4096m

statusenum<string>required

pending: registered, build not started. building: E2B template build in progress. ready: build succeeded; can be promoted. current: the version agents are created against; at most one per harness. revoked: explicitly withdrawn; cannot be promoted or used for new sessions. — "pending" · "building" · "ready" · "current" · "revoked"

profileobjectrequired

The runtime description of a workspace harness: the distribution spec (npx, uvx or binary), optional auth command, bundled MCP servers, tools, features and other catalog fields the installer reads when it builds the template image.

▸ Show child attributes
idstringrequired

pattern ^[a-z0-9][a-z0-9_-]{1,39}$

namestringrequired

max length 200

versionstringrequired

max length 128

distributionmap<string, any>required
auth_commandstring[]
bundled_mcp_serversmap<string, any>[]
configuration_filesmap<string, any>[]
credential_argsmap<string, any>
graceful_exit_timeout_secondsnumber
home_directoriesstring[]
managed_model_id_templatestring
native_provider_setupmap<string, any>
pipelinestring
prerequisitesmap<string, any>
request_timeout_secondsnumber
requirementsstring[]
session_close_before_exitboolean
session_config_optionsmap<string, any>
session_load_supportedboolean
session_parametersmap<string, any>
subscription_filesboolean
docker_targetstring
toolsobject[]
▸ Show child attributes
idstringrequired
kindstringrequired
titlestring
requiresmap<string, any>
featuresstring[]
created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/harnesses/sess_cmtb7q2j/versions/v/current \
  -H "Authorization: Bearer ast_..."

Revoke a harness version

Permanently withdraws a version; it cannot be promoted or used for new sessions. Sessions already running on this version continue until they terminate. Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.

Path parameters

idstringrequired

The harness id (hrn_…)

vstringrequired

The harness version string, e.g. v1-4096m

Response · 200

versionobjectrequired
▸ Show child attributes
idstringrequired

hrnv_… — internal version row id

harness_idstringrequired

hrn_… — the parent harness

versionstringrequired

Version string, e.g. v1-4096m

statusenum<string>required

pending: registered, build not started. building: E2B template build in progress. ready: build succeeded; can be promoted. current: the version agents are created against; at most one per harness. revoked: explicitly withdrawn; cannot be promoted or used for new sessions. — "pending" · "building" · "ready" · "current" · "revoked"

profileobjectrequired

The runtime description of a workspace harness: the distribution spec (npx, uvx or binary), optional auth command, bundled MCP servers, tools, features and other catalog fields the installer reads when it builds the template image.

▸ Show child attributes
idstringrequired

pattern ^[a-z0-9][a-z0-9_-]{1,39}$

namestringrequired

max length 200

versionstringrequired

max length 128

distributionmap<string, any>required
auth_commandstring[]
bundled_mcp_serversmap<string, any>[]
configuration_filesmap<string, any>[]
credential_argsmap<string, any>
graceful_exit_timeout_secondsnumber
home_directoriesstring[]
managed_model_id_templatestring
native_provider_setupmap<string, any>
pipelinestring
prerequisitesmap<string, any>
request_timeout_secondsnumber
requirementsstring[]
session_close_before_exitboolean
session_config_optionsmap<string, any>
session_load_supportedboolean
session_parametersmap<string, any>
subscription_filesboolean
docker_targetstring
toolsobject[]
▸ Show child attributes
idstringrequired
kindstringrequired
titlestring
requiresmap<string, any>
featuresstring[]
created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/harnesses/sess_cmtb7q2j/versions/v/revoke \
  -H "Authorization: Bearer ast_..."

Record the E2B template listing for a version

Stores the E2B sandbox listing string for the built template. Called by the build pipeline after a successful build; advances the version status to ready. Returns 404 when the WORKSPACE_HARNESSES feature switch is off for this workspace. Returns 503 not_migrated when the backing tables are not yet present.

Path parameters

idstringrequired

The harness id (hrn_…)

vstringrequired

The harness version string, e.g. v1-4096m

Body · application/json

listingstringrequired

Response · 200

versionobjectrequired
▸ Show child attributes
idstringrequired

hrnv_… — internal version row id

harness_idstringrequired

hrn_… — the parent harness

versionstringrequired

Version string, e.g. v1-4096m

statusenum<string>required

pending: registered, build not started. building: E2B template build in progress. ready: build succeeded; can be promoted. current: the version agents are created against; at most one per harness. revoked: explicitly withdrawn; cannot be promoted or used for new sessions. — "pending" · "building" · "ready" · "current" · "revoked"

profileobjectrequired

The runtime description of a workspace harness: the distribution spec (npx, uvx or binary), optional auth command, bundled MCP servers, tools, features and other catalog fields the installer reads when it builds the template image.

▸ Show child attributes
idstringrequired

pattern ^[a-z0-9][a-z0-9_-]{1,39}$

namestringrequired

max length 200

versionstringrequired

max length 128

distributionmap<string, any>required
auth_commandstring[]
bundled_mcp_serversmap<string, any>[]
configuration_filesmap<string, any>[]
credential_argsmap<string, any>
graceful_exit_timeout_secondsnumber
home_directoriesstring[]
managed_model_id_templatestring
native_provider_setupmap<string, any>
pipelinestring
prerequisitesmap<string, any>
request_timeout_secondsnumber
requirementsstring[]
session_close_before_exitboolean
session_config_optionsmap<string, any>
session_load_supportedboolean
session_parametersmap<string, any>
subscription_filesboolean
docker_targetstring
toolsobject[]
▸ Show child attributes
idstringrequired
kindstringrequired
titlestring
requiresmap<string, any>
featuresstring[]
created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/harnesses/sess_cmtb7q2j/versions/v/verify \
  -H "Authorization: Bearer ast_..."

Vaults

GET/vaultsread

List the universe's vaults, oldest first

Response · 200

vaultsobject[]required
▸ Show child attributes
typeenum<string>required

"vault"

idstringrequired

vlt_…

display_namestringrequired
created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/vaults' \
  -H "Authorization: Bearer ast_..."
POST/vaultswrite

Create a vault

Pass its id in `vault_ids` on POST /sessions to grant a session its secrets.

Body · application/json

display_namestringrequired

max length 128

Response · 201

vaultobjectrequired
▸ Show child attributes
typeenum<string>required

"vault"

idstringrequired

vlt_…

display_namestringrequired
created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/vaults \
  -H "Authorization: Bearer ast_..."

One vault

Path parameters

idstringrequired

The vault id (vlt_…)

Response · 200

vaultobjectrequired
▸ Show child attributes
typeenum<string>required

"vault"

idstringrequired

vlt_…

display_namestringrequired
created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/vaults/sess_cmtb7q2j' \
  -H "Authorization: Bearer ast_..."
DELETE/vaults/{id}write

Delete a vault and every secret in it

The revocation is pushed to the pods of any sessions the vault was attached to — they lose the credentials without restarting.

Path parameters

idstringrequired

The vault id (vlt_…)

Response · 204

Deleted — no body

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/vaults/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."

List a vault's secrets

Path parameters

idstringrequired

The vault id (vlt_…)

Response · 200

secretsobject[]required
▸ Show child attributes
typeenum<string>required

"vault_secret"

idstringrequired

vsec_…

display_namestringrequired
auth_typeenum<string>required

"static_bearer" · "mcp_oauth" · "environment_variable"

mcp_server_urlstring
secret_namestring

The environment variable the pod sees

statusstringrequired
expires_atstring
created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/vaults/sess_cmtb7q2j/secrets' \
  -H "Authorization: Bearer ast_..."

Add a secret to a vault

`auth.type` picks the kind: static_bearer and mcp_oauth authenticate an MCP server at `mcp_server_url`; environment_variable exposes `secret_name` to the pod. The value is encrypted at rest and never returned.

Path parameters

idstringrequired

The vault id (vlt_…)

Body · application/json

display_namestringrequired

max length 128

authobjectrequired
▸ Show child attributes
type: "static_bearer"object
▸ Show child attributes
type"static_bearer"required
mcp_server_urlstringrequired

https, public host

tokenstringrequired
type: "mcp_oauth"object
▸ Show child attributes
type"mcp_oauth"required
mcp_server_urlstringrequired

https, public host

access_tokenstringrequired
scopestring
expires_atstring
refreshobject
▸ Show child attributes
token_endpointstringrequired
client_idstringrequired
client_secretstring
refresh_tokenstringrequired
token_endpoint_authenum<string>

"none" · "client_secret_basic" · "client_secret_post" — default: "none"

type: "environment_variable"object
▸ Show child attributes
type"environment_variable"required
secret_namestringrequired

A valid environment variable name — max length 128

valuestringrequired
allowed_hostsstring[]

default: []

injection_locationobject

default: {"header":true,"body":false}

▸ Show child attributes
headerboolean
bodyboolean
header_namestring
value_templatestring

max length 256

Response · 201

secretobjectrequired

Metadata only — the secret value is never returned after it is written. `secret_name` is set for environment_variable secrets, `mcp_server_url` for the two MCP kinds.

▸ Show child attributes
typeenum<string>required

"vault_secret"

idstringrequired

vsec_…

display_namestringrequired
auth_typeenum<string>required

"static_bearer" · "mcp_oauth" · "environment_variable"

mcp_server_urlstring
secret_namestring

The environment variable the pod sees

statusstringrequired
expires_atstring
created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/vaults/sess_cmtb7q2j/secrets \
  -H "Authorization: Bearer ast_..."

Move the secrets of other vaults into this one

Moves every secret of the `from` vaults of the same workspace into this vault and answers what happened to each, by name; a value is never returned. A secret is copied and confirmed stored before its source copy is touched, and the source copy is removed only when no session that is not archived still uses that vault without this one (`source` says which). A name this vault already holds with another value is a `clash` and is left alone unless it is listed in `replace`. A secret past this vault's limit, or one that could not be applied together with this vault's secrets, is `blocked` with a `reason`. Calling again moves nothing twice: what is already here answers `already`. With `dry_run` nothing is written and the outcomes are what a real call would do.

Path parameters

idstringrequired

The vault id (vlt_…)

Body · application/json

fromstring[]required

The vaults to move out of (vlt_…) — max length 128

replaceobject[]

Clashing names to overwrite in this vault with the named source's secret

▸ Show child attributes
fromstringrequired

max length 128

namestringrequired

max length 256

dry_runboolean

Response · 200

dry_runbooleanrequired
secretsobject[]required
▸ Show child attributes
fromstringrequired

The vault it was in (vlt_…)

namestringrequired

The environment variable name, or the display name of an MCP secret

auth_typeenum<string>required

"static_bearer" · "mcp_oauth" · "environment_variable"

outcomeenum<string>required

"moved" · "already" · "clash" · "blocked"

sourceenum<string>required

Whether the copy in the source vault was removed — "removed" · "kept"

reasonstring

Why a secret is blocked, e.g. limit_reached or egress_header_conflict

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/vaults/sess_cmtb7q2j/secrets/move \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"from":["vlt_cmtb7q2j"],"dry_run":true}'

Rotate or re-scope a secret in place

The secret keeps its id and its placeholder, so attached pods need no restart — the recompiled policy is pushed to them. Fields not sent are left as they are; `injection_location` merges per field.

Path parameters

idstringrequired

The vault id (vlt_…)

secretIdstringrequired

The secret id (vsec_…)

Body · application/json

display_namestring

max length 128

valuestring
tokenstring
allowed_hostsstring[]
injection_locationobject
▸ Show child attributes
headerboolean
bodyboolean
header_namestring
value_templatestring

max length 256

Response · 200

secretobjectrequired

Metadata only — the secret value is never returned after it is written. `secret_name` is set for environment_variable secrets, `mcp_server_url` for the two MCP kinds.

▸ Show child attributes
typeenum<string>required

"vault_secret"

idstringrequired

vsec_…

display_namestringrequired
auth_typeenum<string>required

"static_bearer" · "mcp_oauth" · "environment_variable"

mcp_server_urlstring
secret_namestring

The environment variable the pod sees

statusstringrequired
expires_atstring
created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PATCH https://api.agentsky.dev/v1/vaults/sess_cmtb7q2j/secrets/secretId \
  -H "Authorization: Bearer ast_..."

Delete a secret

Path parameters

idstringrequired

The vault id (vlt_…)

secretIdstringrequired

The secret id (vsec_…)

Response · 204

Deleted — no body

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/vaults/sess_cmtb7q2j/secrets/secretId \
  -H "Authorization: Bearer ast_..."

Exercise an mcp_oauth grant and report whether it still works

Path parameters

idstringrequired

The vault id (vlt_…)

secretIdstringrequired

The secret id (vsec_…)

Response · 200

resultenum<string>required

"valid" · "invalid" · "unknown"

detailstring
secretobjectrequired

Metadata only — the secret value is never returned after it is written. `secret_name` is set for environment_variable secrets, `mcp_server_url` for the two MCP kinds.

▸ Show child attributes
typeenum<string>required

"vault_secret"

idstringrequired

vsec_…

display_namestringrequired
auth_typeenum<string>required

"static_bearer" · "mcp_oauth" · "environment_variable"

mcp_server_urlstring
secret_namestring

The environment variable the pod sees

statusstringrequired
expires_atstring
created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/vaults/sess_cmtb7q2j/secrets/secretId/validate \
  -H "Authorization: Bearer ast_..."

Sessions

GET/sessionsread

List sessions; ?agent= filters to one spec

Query parameters

agentstring

The agent id (agent_…)

Response · 200

sessionsobject[]required
▸ Show child attributes
idstring

sess_… identifier

agentIdstring | null

The agent id (agent_…)

titlestring | null
statusenum<string>

provisioning = the sandbox is booting or installing the environment's packages (a turn sent meanwhile waits for it); running = a turn is in flight; terminated = archived or the last runtime was destroyed. Use archived for the durable archive receipt — "provisioning" · "idle" · "running" · "terminated"

archivedboolean

True only after this Session's archive mark was durably written; false for an active Session whose runtime was destroyed

agentTypestring
llmstring

The model this session runs on (PATCH to change; the agent's model is unchanged)

harnessVersionstring

Harness release the session runs: the one its serving pod booted, the restored checkpoint's for a native-fork handoff, the agent's pin for ACP harnesses, otherwise the current release

reasoningEffortstring | null

The model-compatible effort resolved from the session pin, then agent pin. Constrained models use an allowed fallback; no-setting models return null. Unpinned unconstrained models return null for the harness default.

subscriptionApiFallbackboolean

Opt-in to paid API continuation after all subscription accounts exhaust, preserving the same supported explicit model and wallet/budget gates

modelBillingenum<string>

Who pays for model calls: platform wallet or the user's connected subscription — "platform" · "account"

idleTimeoutSecondsinteger | null

Seconds the session's machine stays awake after a turn ends before it is paused; null = the platform default of 60. Set it when people use apps on the session's exposed ports after the agent finishes

defaultboolean

Is this the agent's default session

payerobject

Who pays for it, decided once when it was created and never changed. Present only when a payer was recorded, which happens in a team workspace where workspace wallets are on; absent means its owner's own balance pays.

▸ Show child attributes
typeenum<string>required

`workspace`: the team workspace's own wallet. `personal`: the balance of the person who started it. — "workspace" · "personal"

workspaceobject

The paying workspace; only with type workspace

▸ Show child attributes
slugstring
namestring
metadataobject
budgetobject | null

Hard spend cap, or null when the session has none. A reached budget pauses the session (402 budget_reached on new work) until the cap is raised above consumed_cost or removed — removal is one-way.

resourcesobject[]

The files, GitHub repositories, and read-only memory stores mounted into the session, oldest first

▸ Show child attributes
option 1object
▸ Show child attributes
typeenum<string>required

"file"

idstringrequired

sesrsc_…

file_idstringrequired

The per-session copy (file_…), read-only at mount_path

mount_pathstringrequired

Absolute, under /workspace

created_atstringrequired
updated_atstringrequired
option 2object
▸ Show child attributes
typeenum<string>required

"github_repository"

idstringrequired

sesrsc_…

urlstringrequired

https://github.com/{owner}/{repo}

mount_pathstringrequired

Absolute, under /workspace; the clone's root

checkoutobject

{type:"branch", name} or {type:"commit", sha}; absent = the default branch

▸ Show child attributes
typeenum<string>

"branch" · "commit"

namestring
shastring
created_atstringrequired
updated_atstringrequired
option 3object
▸ Show child attributes
typeenum<string>required

"memory_store"

idstringrequired

smsr_…

memory_store_idstringrequired

memstore_…

mount_pathstringrequired

Absolute, under /mnt/memory

accessenum<string>required

"read_only" · "read_write"

instructionsstring

Optional per-session guidance

created_atstringrequired
updated_atstringrequired
workspaceDefaultsobject | null

What the session started with because its workspace made it a default; everything else it carries was named at creation. Null when it took nothing.

hostedBySellerobject

Present only when the session runs on its agent's maker's own server instead of a sandbox: what is sent to the session goes to this host. `agentType` and `llm` then name a stand-in that never runs.

▸ Show child attributes
hoststringrequired
attachmentsobject[]

Everything the session started with: its environment, vaults, mounted files and memory stores, and the workspace's always-available skills. The skills of the session's agent are on the agent and are not repeated here.

▸ Show child attributes
typeenum<string>required

"environment" · "vault" · "file" · "skill" · "memory_store"

idstringrequired

The id of the environment, vault, file, skill or memory store

mountPathstring | nullrequired

Where a file or memory store is mounted; null for the other types

sourceenum<string>required

default = the workspace supplied it; explicit = it was named when the session was created. A memory store on a session created before 2026-10-06 reads as explicit — "default" · "explicit"

createdAtstring

ISO 8601

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/sessions' \
  -H "Authorization: Bearer ast_..."
POST/sessionswrite

Create a session — starts provisioning by default; optionally defer until the first turn

Optional llm and reasoningEffort override the agent's defaults for this session before billing selection or provisioning. A model must be current for the agent's harness; omitted or null reasoningEffort inherits the agent's setting normalized for the target model. Explicit effort must fit both harness and target model. A non-empty initial_events list (user.message only, all-or-nothing) starts the first turn in the same call and provisions in either mode. Without initial events, provision: "deferred" skips the boot: the session reads idle with no pod and costs nothing until its first turn — for a session that waits on a gate or a schedule. Machine shape (vcpus/memoryMb) is per-session.

Body · application/json

agentstringrequired

An agent id, or "@handle" for an agent from the catalog (GET /catalog/agents). A handle that names a platform engine uses the workspace's agent for that engine, created on first use.

llmstring

Model for this session (a current model for the agent's harness). Omitted = the agent's model

reasoningEffortenum<string> | null

Reasoning effort for this session; omitted or null inherits the agent's setting normalized for the target model. Explicit values must fit both harness and target model - agoragentic_acp: not supported; amp_acp: not supported; auggie: not supported; autohand: not supported; cline: not supported; codebuddy_code: not supported; cortex_code: not supported; corust_agent: not supported; crow_cli: not supported; cursor: not supported; deepagents: not supported; devin: not supported; dimcode: not supported; dirac: not supported; factory_droid: not supported; fast_agent: not supported; gemini: not supported; github_copilot_cli: not supported; glm_acp_agent: not supported; antigravity_acp: not supported; goose: not supported; grok_build: not supported; harn: not supported; junie: not supported; kilo: not supported; kimchi: not supported; minimax_code: not supported; minion_code: not supported; mistral_vibe: not supported; nova: not supported; poolside: not supported; qoder: not supported; qwen_code: not supported; sigit: not supported; stakpak: not supported; vtcode: not supported; code_assistant: not supported; docker_cagent: not supported; kiro: not supported; muse_code: not supported; openhands: not supported; hermes: none/minimal/low/medium/high/xhigh/max/ultra; claude_code: low/medium/high/xhigh/max; codex: none/minimal/low/medium/high/xhigh/max; openclaw: not supported; jev: not supported; pi: off/minimal/low/medium/high/xhigh/max; dsh: not supported; kimi_code: not supported; opencode: none/minimal/low/medium/high/xhigh/max; workspace_acp: not supported; models: claude-haiku-4-5: not supported; gemini-3.8-flash: low/medium/high; gemini-3.5-flash: low/medium/high; glm-5.3: low/high/max; glm-5.3-flash: low/high/max; grok-4.6: low/medium/high; grok-4.7: low/medium/high/xhigh; codex/hermes + gpt-6.1-sol: low/medium/high/xhigh/max — "none" · "off" · "minimal" · "low" · "medium" · "high" · "xhigh" · "max" · "ultra"

titlestring

max length 120

metadatamap<string, any>
idleTimeoutSecondsinteger

Seconds this session's machine stays awake after a turn ends before it is paused (60-86400; omitted = the platform default of 60). A paused machine wakes on the next message; apps the agent serves on exposed ports are unreachable while it is paused, so set this to how long people keep using them after the agent finishes

instructionsobject[]
▸ Show child attributes
namestringrequired

pattern .*\.md$

contentstring

default: ""

initial_eventsobject[]
▸ Show child attributes
type"user.message"required
contentobject[]required
▸ Show child attributes
type: "text"object
▸ Show child attributes
type"text"required
textstringrequired
type: "image"object
▸ Show child attributes
type"image"required
sourceobjectrequired
▸ Show child attributes
type: "base64"object
▸ Show child attributes
type"base64"required
media_typestringrequired
datastringrequired
type: "url"object
▸ Show child attributes
type"url"required
urlstringrequired
type: "file"object
▸ Show child attributes
type"file"required
file_idstringrequired
type: "document"object
▸ Show child attributes
type"document"required
sourceobjectrequired
▸ Show child attributes
type: "base64"object
▸ Show child attributes
type"base64"required
media_typestringrequired
datastringrequired
type: "text"object
▸ Show child attributes
type"text"required
media_type"text/plain"

default: "text/plain"

datastringrequired
type: "url"object
▸ Show child attributes
type"url"required
urlstringrequired
type: "file"object
▸ Show child attributes
type"file"required
file_idstringrequired
titlestring | null
contextstring | null
interaction_modeenum<string> | null

"plan" · "build"

provisionenum<string>

eager (default) boots the sandbox as soon as the row exists; deferred leaves the session idle with no pod until its first turn, so a session waiting on a gate or a schedule costs nothing while it waits. Ignored when initial_events start the first turn — "eager" · "deferred"

environment_idstring
vault_idsstring[]
vcpusinteger
memoryMbinteger
subscriptionApiFallbackboolean

After every subscription account is exhausted, continue on the same model using the paid platform API; wallet and session budget still apply

modelBillingenum<string>

Who pays for model calls: platform wallet or the user's connected subscription. Omitted = auto-apply (a connected subscription with "use for new agents" powers eligible compositions) — "platform" · "account"

budgetobject

Hard spend cap for this session. Attachable only at create; changeable or removable later via PATCH (removal is one-way)

▸ Show child attributes
type"limit"required
max_list_costobjectrequired
▸ Show child attributes
amountstringrequired

Whole US cents as an integer decimal string, e.g. "125" for $1.25 — max length 15

currency"USD"required
payerenum<string>

Which balance pays for the session, in a team workspace that has a wallet of its own: "workspace" (the default there) or "personal", the caller's own. Decided once, here, and shown as `payer` on the session and its task. "workspace" where the workspace has no wallet is refused with 409 workspace_wallet_unavailable. — "personal" · "workspace"

defaultsenum<string>

Whether the session also starts with its workspace's defaults: the default environment when none is named, the default vault when it holds a secret, and the always-available files and skills. "none" attaches only what this request names. Omitted means "workspace". — "workspace" · "none"

resourcesobject[]

Files, GitHub repositories, and team Memory Stores attached before the first turn (max 100 create-time resources; max 8 memory stores). `{type:"file", file_id, mount_path?}` copies an upload read-only to `/workspace<mount_path>` (default `/workspace/<file_id>`); `{type:"github_repository", url, authorization_token?, checkout?: {type:"branch", name} | {type:"commit", sha}, mount_path?}` clones `https://github.com/{owner}/{repo}` to `/workspace<mount_path>` (default `/workspace/<repo>`); the token never enters the sandbox. `{type:"memory_store", memory_store_id, access:"read_only"|"read_write", mount_path?, instructions?}` attaches a creation-time snapshot under `/mnt/memory/` (default `/mnt/memory/<memory_store_id>`; 8 MiB total per Session). `read_write` explicitly grants the session-scoped Agent API permission to update this store; the mounted snapshot remains read-only.

▸ Show child attributes
type: "file"object
▸ Show child attributes
type"file"required
file_idstringrequired

max length 128

mount_pathstring | null

max length 4096

type: "github_repository"object
▸ Show child attributes
type"github_repository"required
urlstringrequired

max length 2048

authorization_tokenstring

max length 1024

checkoutobject | null
▸ Show child attributes
type: "branch"object
▸ Show child attributes
type"branch"required
namestringrequired

max length 255

type: "commit"object
▸ Show child attributes
type"commit"required
shastringrequired

max length 64

mount_pathstring | null

max length 4096

type: "memory_store"object
▸ Show child attributes
type"memory_store"required
memory_store_idstringrequired

max length 255

accessenum<string>required

"read_only" · "read_write"

instructionsstring

max length 4096

mount_pathstring | null

max length 4096

Response · 201

sessionobjectrequired
▸ Show child attributes
idstring

sess_… identifier

agentIdstring | null

The agent id (agent_…)

titlestring | null
statusenum<string>

provisioning = the sandbox is booting or installing the environment's packages (a turn sent meanwhile waits for it); running = a turn is in flight; terminated = archived or the last runtime was destroyed. Use archived for the durable archive receipt — "provisioning" · "idle" · "running" · "terminated"

archivedboolean

True only after this Session's archive mark was durably written; false for an active Session whose runtime was destroyed

agentTypestring
llmstring

The model this session runs on (PATCH to change; the agent's model is unchanged)

harnessVersionstring

Harness release the session runs: the one its serving pod booted, the restored checkpoint's for a native-fork handoff, the agent's pin for ACP harnesses, otherwise the current release

reasoningEffortstring | null

The model-compatible effort resolved from the session pin, then agent pin. Constrained models use an allowed fallback; no-setting models return null. Unpinned unconstrained models return null for the harness default.

subscriptionApiFallbackboolean

Opt-in to paid API continuation after all subscription accounts exhaust, preserving the same supported explicit model and wallet/budget gates

modelBillingenum<string>

Who pays for model calls: platform wallet or the user's connected subscription — "platform" · "account"

idleTimeoutSecondsinteger | null

Seconds the session's machine stays awake after a turn ends before it is paused; null = the platform default of 60. Set it when people use apps on the session's exposed ports after the agent finishes

defaultboolean

Is this the agent's default session

payerobject

Who pays for it, decided once when it was created and never changed. Present only when a payer was recorded, which happens in a team workspace where workspace wallets are on; absent means its owner's own balance pays.

▸ Show child attributes
typeenum<string>required

`workspace`: the team workspace's own wallet. `personal`: the balance of the person who started it. — "workspace" · "personal"

workspaceobject

The paying workspace; only with type workspace

▸ Show child attributes
slugstring
namestring
metadataobject
budgetobject | null

Hard spend cap, or null when the session has none. A reached budget pauses the session (402 budget_reached on new work) until the cap is raised above consumed_cost or removed — removal is one-way.

resourcesobject[]

The files, GitHub repositories, and read-only memory stores mounted into the session, oldest first

▸ Show child attributes
option 1object
▸ Show child attributes
typeenum<string>required

"file"

idstringrequired

sesrsc_…

file_idstringrequired

The per-session copy (file_…), read-only at mount_path

mount_pathstringrequired

Absolute, under /workspace

created_atstringrequired
updated_atstringrequired
option 2object
▸ Show child attributes
typeenum<string>required

"github_repository"

idstringrequired

sesrsc_…

urlstringrequired

https://github.com/{owner}/{repo}

mount_pathstringrequired

Absolute, under /workspace; the clone's root

checkoutobject

{type:"branch", name} or {type:"commit", sha}; absent = the default branch

▸ Show child attributes
typeenum<string>

"branch" · "commit"

namestring
shastring
created_atstringrequired
updated_atstringrequired
option 3object
▸ Show child attributes
typeenum<string>required

"memory_store"

idstringrequired

smsr_…

memory_store_idstringrequired

memstore_…

mount_pathstringrequired

Absolute, under /mnt/memory

accessenum<string>required

"read_only" · "read_write"

instructionsstring

Optional per-session guidance

created_atstringrequired
updated_atstringrequired
workspaceDefaultsobject | null

What the session started with because its workspace made it a default; everything else it carries was named at creation. Null when it took nothing.

hostedBySellerobject

Present only when the session runs on its agent's maker's own server instead of a sandbox: what is sent to the session goes to this host. `agentType` and `llm` then name a stand-in that never runs.

▸ Show child attributes
hoststringrequired
attachmentsobject[]

Everything the session started with: its environment, vaults, mounted files and memory stores, and the workspace's always-available skills. The skills of the session's agent are on the agent and are not repeated here.

▸ Show child attributes
typeenum<string>required

"environment" · "vault" · "file" · "skill" · "memory_store"

idstringrequired

The id of the environment, vault, file, skill or memory store

mountPathstring | nullrequired

Where a file or memory store is mounted; null for the other types

sourceenum<string>required

default = the workspace supplied it; explicit = it was named when the session was created. A memory store on a session created before 2026-10-06 reads as explicit — "default" · "explicit"

createdAtstring

ISO 8601

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/sessions \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"agent":"agent_cmtb2f0a8m9k7x51q4ez6r0d","llm":"deepseek-flash","reasoningEffort":"high","title":"Signups digest","resources":[{"type":"file","file_id":"file_cmtb9x4p","mount_path":"/data/signups.csv"},{"type":"github_repository","url":"https://github.com/acme/growth","checkout":{"type":"branch","name":"main"}},{"type":"memory_store","memory_store_id":"memstore_cmtb9x4p","access":"read_only"}],"initial_events":[{"type":"user.message","content":[{"type":"text","text":"Summarize the signups from today"}]}]}'
Response · 201 Created
{
  "session": {
    "id": "sess-8c41f0…",
    "agent": "research-agent",
    "status": "idle",
    "default": true
  }
}

Session detail — status is provisioning (sandbox booting or installing packages) | idle | running | terminated

Path parameters

idstringrequired

The session id

Response · 200

sessionobjectrequired
▸ Show child attributes
idstring

sess_… identifier

agentIdstring | null

The agent id (agent_…)

titlestring | null
statusenum<string>

provisioning = the sandbox is booting or installing the environment's packages (a turn sent meanwhile waits for it); running = a turn is in flight; terminated = archived or the last runtime was destroyed. Use archived for the durable archive receipt — "provisioning" · "idle" · "running" · "terminated"

archivedboolean

True only after this Session's archive mark was durably written; false for an active Session whose runtime was destroyed

agentTypestring
llmstring

The model this session runs on (PATCH to change; the agent's model is unchanged)

harnessVersionstring

Harness release the session runs: the one its serving pod booted, the restored checkpoint's for a native-fork handoff, the agent's pin for ACP harnesses, otherwise the current release

reasoningEffortstring | null

The model-compatible effort resolved from the session pin, then agent pin. Constrained models use an allowed fallback; no-setting models return null. Unpinned unconstrained models return null for the harness default.

subscriptionApiFallbackboolean

Opt-in to paid API continuation after all subscription accounts exhaust, preserving the same supported explicit model and wallet/budget gates

modelBillingenum<string>

Who pays for model calls: platform wallet or the user's connected subscription — "platform" · "account"

idleTimeoutSecondsinteger | null

Seconds the session's machine stays awake after a turn ends before it is paused; null = the platform default of 60. Set it when people use apps on the session's exposed ports after the agent finishes

defaultboolean

Is this the agent's default session

payerobject

Who pays for it, decided once when it was created and never changed. Present only when a payer was recorded, which happens in a team workspace where workspace wallets are on; absent means its owner's own balance pays.

▸ Show child attributes
typeenum<string>required

`workspace`: the team workspace's own wallet. `personal`: the balance of the person who started it. — "workspace" · "personal"

workspaceobject

The paying workspace; only with type workspace

▸ Show child attributes
slugstring
namestring
metadataobject
budgetobject | null

Hard spend cap, or null when the session has none. A reached budget pauses the session (402 budget_reached on new work) until the cap is raised above consumed_cost or removed — removal is one-way.

resourcesobject[]

The files, GitHub repositories, and read-only memory stores mounted into the session, oldest first

▸ Show child attributes
option 1object
▸ Show child attributes
typeenum<string>required

"file"

idstringrequired

sesrsc_…

file_idstringrequired

The per-session copy (file_…), read-only at mount_path

mount_pathstringrequired

Absolute, under /workspace

created_atstringrequired
updated_atstringrequired
option 2object
▸ Show child attributes
typeenum<string>required

"github_repository"

idstringrequired

sesrsc_…

urlstringrequired

https://github.com/{owner}/{repo}

mount_pathstringrequired

Absolute, under /workspace; the clone's root

checkoutobject

{type:"branch", name} or {type:"commit", sha}; absent = the default branch

▸ Show child attributes
typeenum<string>

"branch" · "commit"

namestring
shastring
created_atstringrequired
updated_atstringrequired
option 3object
▸ Show child attributes
typeenum<string>required

"memory_store"

idstringrequired

smsr_…

memory_store_idstringrequired

memstore_…

mount_pathstringrequired

Absolute, under /mnt/memory

accessenum<string>required

"read_only" · "read_write"

instructionsstring

Optional per-session guidance

created_atstringrequired
updated_atstringrequired
workspaceDefaultsobject | null

What the session started with because its workspace made it a default; everything else it carries was named at creation. Null when it took nothing.

hostedBySellerobject

Present only when the session runs on its agent's maker's own server instead of a sandbox: what is sent to the session goes to this host. `agentType` and `llm` then name a stand-in that never runs.

▸ Show child attributes
hoststringrequired
attachmentsobject[]

Everything the session started with: its environment, vaults, mounted files and memory stores, and the workspace's always-available skills. The skills of the session's agent are on the agent and are not repeated here.

▸ Show child attributes
typeenum<string>required

"environment" · "vault" · "file" · "skill" · "memory_store"

idstringrequired

The id of the environment, vault, file, skill or memory store

mountPathstring | nullrequired

Where a file or memory store is mounted; null for the other types

sourceenum<string>required

default = the workspace supplied it; explicit = it was named when the session was created. A memory store on a session created before 2026-10-06 reads as explicit — "default" · "explicit"

createdAtstring

ISO 8601

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j' \
  -H "Authorization: Bearer ast_..."
PATCH/sessions/{id}write

Update title / metadata / model / reasoning effort / billing / budget

llm and reasoningEffort are session settings: they change this session only, never the agent or its other sessions. The model must fit the harness; explicit effort must fit both harness and target model. Inherited effort is normalized for that model. An idle session restarts its engine in place; a running session finishes its turn and applies the change at the next turn (the response is 200 either way). A parked session applies it at its next wake.

Path parameters

idstringrequired

The session id

Body · application/json

titlestring | null

max length 120

metadatamap<string, any>
idleTimeoutSecondsinteger | null

Seconds this session's machine stays awake after a turn ends before it is paused (60-86400; omitted = the platform default of 60). A paused machine wakes on the next message; apps the agent serves on exposed ports are unreachable while it is paused, so set this to how long people keep using them after the agent finishes; null clears back to the platform default. Applies from the next time the session goes idle

llmstring

Switch this session's model (a current model for its harness; the agent's model is unchanged). Applies from the next turn

reasoningEffortenum<string> | null

Session-level reasoning effort; null clears to the agent's setting normalized for the target model. Applies from the next turn. Explicit values must fit both harness and target model — agoragentic_acp: not supported; amp_acp: not supported; auggie: not supported; autohand: not supported; cline: not supported; codebuddy_code: not supported; cortex_code: not supported; corust_agent: not supported; crow_cli: not supported; cursor: not supported; deepagents: not supported; devin: not supported; dimcode: not supported; dirac: not supported; factory_droid: not supported; fast_agent: not supported; gemini: not supported; github_copilot_cli: not supported; glm_acp_agent: not supported; antigravity_acp: not supported; goose: not supported; grok_build: not supported; harn: not supported; junie: not supported; kilo: not supported; kimchi: not supported; minimax_code: not supported; minion_code: not supported; mistral_vibe: not supported; nova: not supported; poolside: not supported; qoder: not supported; qwen_code: not supported; sigit: not supported; stakpak: not supported; vtcode: not supported; code_assistant: not supported; docker_cagent: not supported; kiro: not supported; muse_code: not supported; openhands: not supported; hermes: none/minimal/low/medium/high/xhigh/max/ultra; claude_code: low/medium/high/xhigh/max; codex: none/minimal/low/medium/high/xhigh/max; openclaw: not supported; jev: not supported; pi: off/minimal/low/medium/high/xhigh/max; dsh: not supported; kimi_code: not supported; opencode: none/minimal/low/medium/high/xhigh/max; workspace_acp: not supported; models: claude-haiku-4-5: not supported; gemini-3.8-flash: low/medium/high; gemini-3.5-flash: low/medium/high; glm-5.3: low/high/max; glm-5.3-flash: low/high/max; grok-4.6: low/medium/high; grok-4.7: low/medium/high/xhigh; codex/hermes + gpt-6.1-sol: low/medium/high/xhigh/max — "none" · "off" · "minimal" · "low" · "medium" · "high" · "xhigh" · "max" · "ultra"

subscriptionApiFallbackboolean

After every subscription account is exhausted, continue on the same model using the paid platform API; wallet and session budget still apply

modelBillingenum<string>

Who pays for model calls; switching restarts the agent's engine in place — "platform" · "account"

budgetobject | null

Change the spend cap (must be strictly above consumed cost) or null to remove it — removal is one-way

▸ Show child attributes
type"limit"required
max_list_costobjectrequired
▸ Show child attributes
amountstringrequired

Whole US cents as an integer decimal string, e.g. "125" for $1.25 — max length 15

currency"USD"required

Response · 200

sessionobjectrequired
▸ Show child attributes
idstring

sess_… identifier

agentIdstring | null

The agent id (agent_…)

titlestring | null
statusenum<string>

provisioning = the sandbox is booting or installing the environment's packages (a turn sent meanwhile waits for it); running = a turn is in flight; terminated = archived or the last runtime was destroyed. Use archived for the durable archive receipt — "provisioning" · "idle" · "running" · "terminated"

archivedboolean

True only after this Session's archive mark was durably written; false for an active Session whose runtime was destroyed

agentTypestring
llmstring

The model this session runs on (PATCH to change; the agent's model is unchanged)

harnessVersionstring

Harness release the session runs: the one its serving pod booted, the restored checkpoint's for a native-fork handoff, the agent's pin for ACP harnesses, otherwise the current release

reasoningEffortstring | null

The model-compatible effort resolved from the session pin, then agent pin. Constrained models use an allowed fallback; no-setting models return null. Unpinned unconstrained models return null for the harness default.

subscriptionApiFallbackboolean

Opt-in to paid API continuation after all subscription accounts exhaust, preserving the same supported explicit model and wallet/budget gates

modelBillingenum<string>

Who pays for model calls: platform wallet or the user's connected subscription — "platform" · "account"

idleTimeoutSecondsinteger | null

Seconds the session's machine stays awake after a turn ends before it is paused; null = the platform default of 60. Set it when people use apps on the session's exposed ports after the agent finishes

defaultboolean

Is this the agent's default session

payerobject

Who pays for it, decided once when it was created and never changed. Present only when a payer was recorded, which happens in a team workspace where workspace wallets are on; absent means its owner's own balance pays.

▸ Show child attributes
typeenum<string>required

`workspace`: the team workspace's own wallet. `personal`: the balance of the person who started it. — "workspace" · "personal"

workspaceobject

The paying workspace; only with type workspace

▸ Show child attributes
slugstring
namestring
metadataobject
budgetobject | null

Hard spend cap, or null when the session has none. A reached budget pauses the session (402 budget_reached on new work) until the cap is raised above consumed_cost or removed — removal is one-way.

resourcesobject[]

The files, GitHub repositories, and read-only memory stores mounted into the session, oldest first

▸ Show child attributes
option 1object
▸ Show child attributes
typeenum<string>required

"file"

idstringrequired

sesrsc_…

file_idstringrequired

The per-session copy (file_…), read-only at mount_path

mount_pathstringrequired

Absolute, under /workspace

created_atstringrequired
updated_atstringrequired
option 2object
▸ Show child attributes
typeenum<string>required

"github_repository"

idstringrequired

sesrsc_…

urlstringrequired

https://github.com/{owner}/{repo}

mount_pathstringrequired

Absolute, under /workspace; the clone's root

checkoutobject

{type:"branch", name} or {type:"commit", sha}; absent = the default branch

▸ Show child attributes
typeenum<string>

"branch" · "commit"

namestring
shastring
created_atstringrequired
updated_atstringrequired
option 3object
▸ Show child attributes
typeenum<string>required

"memory_store"

idstringrequired

smsr_…

memory_store_idstringrequired

memstore_…

mount_pathstringrequired

Absolute, under /mnt/memory

accessenum<string>required

"read_only" · "read_write"

instructionsstring

Optional per-session guidance

created_atstringrequired
updated_atstringrequired
workspaceDefaultsobject | null

What the session started with because its workspace made it a default; everything else it carries was named at creation. Null when it took nothing.

hostedBySellerobject

Present only when the session runs on its agent's maker's own server instead of a sandbox: what is sent to the session goes to this host. `agentType` and `llm` then name a stand-in that never runs.

▸ Show child attributes
hoststringrequired
attachmentsobject[]

Everything the session started with: its environment, vaults, mounted files and memory stores, and the workspace's always-available skills. The skills of the session's agent are on the agent and are not repeated here.

▸ Show child attributes
typeenum<string>required

"environment" · "vault" · "file" · "skill" · "memory_store"

idstringrequired

The id of the environment, vault, file, skill or memory store

mountPathstring | nullrequired

Where a file or memory store is mounted; null for the other types

sourceenum<string>required

default = the workspace supplied it; explicit = it was named when the session was created. A memory store on a session created before 2026-10-06 reads as explicit — "default" · "explicit"

createdAtstring

ISO 8601

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PATCH https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"title":"Signups digest","metadata":{"team":"growth"},"llm":"claude-sonnet-5","reasoningEffort":"high"}'
DELETE/sessions/{id}write

Retire a Session and tear down its runtime

Marks the Session deleted and removes operational bindings; durable transcripts and accounting records are retained. GET Session answers 404 afterward. Active execution must stop before cleanup. Works on idle and archived Sessions.

Path parameters

idstringrequired

The session id

Response · 200

oktruerequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."

Who may use the session, and what you are to it

Members of the session's workspace may read and prompt a workspace session; a private session is the owner's alone. People whose verified email is listed may read its message history from any workspace. Viewer emails are returned to the owner only.

Path parameters

idstringrequired

The session id

Response · 200

session_idstringrequired
titlestringrequired
agent_typestringrequired
llmstringrequired
visibilityenum<string>required

"workspace" · "private"

accessenum<string>required

"owner" · "member" · "viewer"

ownerobjectrequired
▸ Show child attributes
idstring
namestring
emailstring
workspaceobjectrequired
▸ Show child attributes
slugstring
namestring
personalboolean
viewersobject[]required
▸ Show child attributes
emailstring
added_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/access' \
  -H "Authorization: Bearer ast_..."
PATCH/sessions/{id}/accesswrite, owner

Make the session private or workspace-visible, and edit its viewers

Path parameters

idstringrequired

The session id

Body · application/json

visibilityenum<string>

"workspace" · "private"

add_viewersstring[]
remove_viewersstring[]

Response · 200

session_idstringrequired
titlestringrequired
agent_typestringrequired
llmstringrequired
visibilityenum<string>required

"workspace" · "private"

accessenum<string>required

"owner" · "member" · "viewer"

ownerobjectrequired
▸ Show child attributes
idstring
namestring
emailstring
workspaceobjectrequired
▸ Show child attributes
slugstring
namestring
personalboolean
viewersobject[]required
▸ Show child attributes
emailstring
added_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PATCH https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/access \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"visibility":"private","add_viewers":["reviewer@acme.com"]}'

Sessions other people shared with you to read, newest first

Viewing is a person's access, so a credential limited to one workspace lists none. A limit that is not an integer from 1 to 100, or a cursor that is not valid, is 400 invalid_request.

Query parameters

limitinteger
cursorstring

next_cursor from the previous page

Response · 200

sessionsobject[]required
▸ Show child attributes
idstring
titlestring
agent_typestring
ownerobject
▸ Show child attributes
namestring
emailstring
workspaceobject
▸ Show child attributes
namestring
shared_atstring
next_cursorstringrequired

Pass back as ?cursor= for the next page; null on the last page

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/shared-sessions' \
  -H "Authorization: Bearer ast_..."

The session's share link, or {"token": null} when sharing is off (owner only)

Path parameters

idstringrequired

The session id

Response · 200

tokenstringrequired
accessenum<string>

"prompt" · "view"

shareUrlstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/share' \
  -H "Authorization: Bearer ast_..."

Turn sharing on and get the share link — idempotent; {"access": "view"} asks for a view-only link; {"rotate": true} replaces it

A guest link (access prompt, the default) has a shareUrl that opens the session's guest page for anyone holding it, with no account; turns sent through it bill the session's owner. A view-only link (access view) has no shareUrl: anyone holding its token reads the conversation's text at GET /links/{token}/events and can do nothing else. A session has one link; asking for the other access level replaces it with a new token, so the old URL dies. Rotating keeps the level and kills the old URL immediately; rotate cannot be combined with access.

Path parameters

idstringrequired

The session id

Body · application/json

rotateboolean

default: false

accessenum<string>

"prompt" · "view" — default: "prompt"

Response · 200

tokenstringrequired
accessenum<string>

"prompt" · "view"

shareUrlstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/share \
  -H "Authorization: Bearer ast_..."

Turn sharing off — the link stops working immediately

Path parameters

idstringrequired

The session id

Response · 200

oktruerequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/share \
  -H "Authorization: Bearer ast_..."

Archive the session — irreversible; blocks new events, history stays readable

Durably marks archived=true and sets status to terminated, tears down the pod and stored context, and refuses further messages (400 session_archived); the record and its events remain readable. A running session is refused with 400 session_running: interrupt and wait for idle first. A changed active Session whose archive mark did not commit returns 409 session_changed. Idempotent when another request already archived it.

Path parameters

idstringrequired

The session id

Response · 200

sessionobjectrequired
▸ Show child attributes
idstring

sess_… identifier

agentIdstring | null

The agent id (agent_…)

titlestring | null
statusenum<string>

provisioning = the sandbox is booting or installing the environment's packages (a turn sent meanwhile waits for it); running = a turn is in flight; terminated = archived or the last runtime was destroyed. Use archived for the durable archive receipt — "provisioning" · "idle" · "running" · "terminated"

archivedboolean

True only after this Session's archive mark was durably written; false for an active Session whose runtime was destroyed

agentTypestring
llmstring

The model this session runs on (PATCH to change; the agent's model is unchanged)

harnessVersionstring

Harness release the session runs: the one its serving pod booted, the restored checkpoint's for a native-fork handoff, the agent's pin for ACP harnesses, otherwise the current release

reasoningEffortstring | null

The model-compatible effort resolved from the session pin, then agent pin. Constrained models use an allowed fallback; no-setting models return null. Unpinned unconstrained models return null for the harness default.

subscriptionApiFallbackboolean

Opt-in to paid API continuation after all subscription accounts exhaust, preserving the same supported explicit model and wallet/budget gates

modelBillingenum<string>

Who pays for model calls: platform wallet or the user's connected subscription — "platform" · "account"

idleTimeoutSecondsinteger | null

Seconds the session's machine stays awake after a turn ends before it is paused; null = the platform default of 60. Set it when people use apps on the session's exposed ports after the agent finishes

defaultboolean

Is this the agent's default session

payerobject

Who pays for it, decided once when it was created and never changed. Present only when a payer was recorded, which happens in a team workspace where workspace wallets are on; absent means its owner's own balance pays.

▸ Show child attributes
typeenum<string>required

`workspace`: the team workspace's own wallet. `personal`: the balance of the person who started it. — "workspace" · "personal"

workspaceobject

The paying workspace; only with type workspace

▸ Show child attributes
slugstring
namestring
metadataobject
budgetobject | null

Hard spend cap, or null when the session has none. A reached budget pauses the session (402 budget_reached on new work) until the cap is raised above consumed_cost or removed — removal is one-way.

resourcesobject[]

The files, GitHub repositories, and read-only memory stores mounted into the session, oldest first

▸ Show child attributes
option 1object
▸ Show child attributes
typeenum<string>required

"file"

idstringrequired

sesrsc_…

file_idstringrequired

The per-session copy (file_…), read-only at mount_path

mount_pathstringrequired

Absolute, under /workspace

created_atstringrequired
updated_atstringrequired
option 2object
▸ Show child attributes
typeenum<string>required

"github_repository"

idstringrequired

sesrsc_…

urlstringrequired

https://github.com/{owner}/{repo}

mount_pathstringrequired

Absolute, under /workspace; the clone's root

checkoutobject

{type:"branch", name} or {type:"commit", sha}; absent = the default branch

▸ Show child attributes
typeenum<string>

"branch" · "commit"

namestring
shastring
created_atstringrequired
updated_atstringrequired
option 3object
▸ Show child attributes
typeenum<string>required

"memory_store"

idstringrequired

smsr_…

memory_store_idstringrequired

memstore_…

mount_pathstringrequired

Absolute, under /mnt/memory

accessenum<string>required

"read_only" · "read_write"

instructionsstring

Optional per-session guidance

created_atstringrequired
updated_atstringrequired
workspaceDefaultsobject | null

What the session started with because its workspace made it a default; everything else it carries was named at creation. Null when it took nothing.

hostedBySellerobject

Present only when the session runs on its agent's maker's own server instead of a sandbox: what is sent to the session goes to this host. `agentType` and `llm` then name a stand-in that never runs.

▸ Show child attributes
hoststringrequired
attachmentsobject[]

Everything the session started with: its environment, vaults, mounted files and memory stores, and the workspace's always-available skills. The skills of the session's agent are on the agent and are not repeated here.

▸ Show child attributes
typeenum<string>required

"environment" · "vault" · "file" · "skill" · "memory_store"

idstringrequired

The id of the environment, vault, file, skill or memory store

mountPathstring | nullrequired

Where a file or memory store is mounted; null for the other types

sourceenum<string>required

default = the workspace supplied it; explicit = it was named when the session was created. A memory store on a session created before 2026-10-06 reads as explicit — "default" · "explicit"

createdAtstring

ISO 8601

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/archive \
  -H "Authorization: Bearer ast_..."

The session's billed usage, newest first

Totals plus one row per billed event — model turns, runtime, capability and connector calls — with the token breakdown, list and billed dollars, basis and duration. `limit` (default 50) pages with an opaque `cursor`; keep following `cursor` until it is null. A row whose `coveredBy` is `subscription` ran on the reader's own Claude or ChatGPT plan: `listCostUsd` is what it was worth, `billedCostUsd` is zero. Dollar amounts here are numbers in USD, not the `{amount, currency}` cents object used elsewhere.

Path parameters

idstringrequired

The session id

Query parameters

cursorstring

A cursor from a previous page

limitinteger

1–500, default 50

Response · 200

sessionstringrequired
totalsobjectrequired

Summed over the whole session, not just this page. `durationComplete` is false while a turn is still running. `tokenCostsUsd` is only present when every model charge carried its original breakdown.

▸ Show child attributes
listCostUsdnumber
billedCostUsdnumber
inputTokensinteger
outputTokensinteger
cachedInputTokensinteger
cacheCreationTokensinteger
modelBilledCostUsdnumber
runtimeCostUsdnumber
capabilityCallCostUsdnumber
connectorCallCostUsdnumber
turnsinteger
durationMsinteger
durationCompleteboolean
coveredBystring | null

"subscription" · null

tokenCostsUsdobject | null
entriesobject[]required
▸ Show child attributes
kindstringrequired
atstringrequired
listCostUsdnumber | null
billedCostUsdnumberrequired
coveredBystring | null

Why a metered turn was booked at $0, when that is known — "subscription" · null

modelstring | null
providerstring | null
basisstring | null
durationMsinteger | null
interruptedboolean | null
tokensobjectrequired
▸ Show child attributes
inputinteger
outputinteger
cachedInputinteger
cacheCreationinteger
budgetobject | null

The session's budget summary — the same shape as `budget` on Session — or null when it has none

cursorstring | nullrequired

Pass as ?cursor= for the next page; null on the last

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/usage' \
  -H "Authorization: Bearer ast_..."

List session-level policy rules

Path parameters

idstringrequired

The session id

Response · 200

rulesobject[]
▸ Show child attributes
idstringrequired
namestringrequired
kindenum<string>required

"TOOL_CALL" · "SPEND_CAP" · "CALL_COUNT" · "CAPABILITY"

enabledbooleanrequired
configobjectrequired
layerenum<string>required

"workspace" · "agent" · "session"

positionintegerrequired
createdAtstringrequired
updatedAtstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/policies' \
  -H "Authorization: Bearer ast_..."

Create a session-level policy rule (owner only)

Path parameters

idstringrequired

The session id

Body · application/json

option 1object
▸ Show child attributes
namestringrequired

max length 128

enabledboolean

default: true

positioninteger

default: 0

kind"TOOL_CALL"required
configobjectrequired
▸ Show child attributes
actionenum<string>required

"allow" · "ask" · "deny"

matcherstring

max length 255

commandPatternsstring[]

max length 500

option 2object
▸ Show child attributes
namestringrequired

max length 128

enabledboolean

default: true

positioninteger

default: 0

kind"SPEND_CAP"required
configobjectrequired
▸ Show child attributes
warnUsdMicrosinteger | null
hardCapUsdMicrosintegerrequired
option 3object
▸ Show child attributes
namestringrequired

max length 128

enabledboolean

default: true

positioninteger

default: 0

kind"CALL_COUNT"required
configobjectrequired
▸ Show child attributes
limitPerSessionintegerrequired
option 4object
▸ Show child attributes
namestringrequired

max length 128

enabledboolean

default: true

positioninteger

default: 0

kind"CAPABILITY"required
configmap<string, enum<string>>required

"allow" · "ask" · "deny"

Response · 201

ruleobject
▸ Show child attributes
idstringrequired
namestringrequired
kindenum<string>required

"TOOL_CALL" · "SPEND_CAP" · "CALL_COUNT" · "CAPABILITY"

enabledbooleanrequired
configobjectrequired
layerenum<string>required

"workspace" · "agent" · "session"

positionintegerrequired
createdAtstringrequired
updatedAtstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/policies \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"name":"Spend cap","kind":"SPEND_CAP","config":{"hardCapUsdMicros":5000000,"warnUsdMicros":4000000}}'

Get a session-level policy rule

Path parameters

idstringrequired

The session id

ruleIdstringrequired

Response · 200

ruleobject
▸ Show child attributes
idstringrequired
namestringrequired
kindenum<string>required

"TOOL_CALL" · "SPEND_CAP" · "CALL_COUNT" · "CAPABILITY"

enabledbooleanrequired
configobjectrequired
layerenum<string>required

"workspace" · "agent" · "session"

positionintegerrequired
createdAtstringrequired
updatedAtstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/policies/cmtb5p0l3r8w2k01s6x7n9q4' \
  -H "Authorization: Bearer ast_..."

Update a session-level policy rule (owner only)

Path parameters

idstringrequired

The session id

ruleIdstringrequired

Body · application/json

namestring

max length 128

enabledboolean
positioninteger
configobject | map<string, enum<string>>
▸ Show child attributes
option 1object
▸ Show child attributes
actionenum<string>required

"allow" · "ask" · "deny"

matcherstring

max length 255

commandPatternsstring[]

max length 500

option 2object
▸ Show child attributes
warnUsdMicrosinteger | null
hardCapUsdMicrosintegerrequired
option 3object
▸ Show child attributes
limitPerSessionintegerrequired
option 4map<string, enum<string>>

"allow" · "ask" · "deny"

Response · 200

ruleobject
▸ Show child attributes
idstringrequired
namestringrequired
kindenum<string>required

"TOOL_CALL" · "SPEND_CAP" · "CALL_COUNT" · "CAPABILITY"

enabledbooleanrequired
configobjectrequired
layerenum<string>required

"workspace" · "agent" · "session"

positionintegerrequired
createdAtstringrequired
updatedAtstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PATCH https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/policies/cmtb5p0l3r8w2k01s6x7n9q4 \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"config":{"hardCapUsdMicros":10000000,"warnUsdMicros":8000000}}'

Delete a session-level policy rule (owner only)

Path parameters

idstringrequired

The session id

ruleIdstringrequired

Response · 200

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/policies/cmtb5p0l3r8w2k01s6x7n9q4 \
  -H "Authorization: Bearer ast_..."

Effective merged policy for a session across all layers

Returns all policy rules for workspace → agent → session, with a note when native tool policies prevent an unsupported runtime from starting.

Path parameters

idstringrequired

The session id

Response · 200

rulesobject[]
▸ Show child attributes
idstringrequired
namestringrequired
kindenum<string>required

"TOOL_CALL" · "SPEND_CAP" · "CALL_COUNT" · "CAPABILITY"

enabledbooleanrequired
configobjectrequired
layerenum<string>required

"workspace" · "agent" · "session"

positionintegerrequired
createdAtstringrequired
updatedAtstringrequired
notestring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/effective-policy' \
  -H "Authorization: Bearer ast_..."

Deprecated: the address of the web app running inside the session's pod

Replaced by `PUT /sessions/{id}/ports/{port}` and `POST …/ports/{port}/grants`; kept for one release while the consumer app moves. Minted once per session and stable afterwards. `port` is what the app inside the pod listens on — 1024–65535, defaulting to the studio's own port. An archived session answers 400 session_archived.

Path parameters

idstringrequired

The session id

Body · application/json

portinteger

Omitted = the studio's default port

Response · 200

urlstringrequired

https://studio-<token>.agentsky.dev — the token is the whole address

portintegerrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/studio \
  -H "Authorization: Bearer ast_..."

The session's exposed ports, oldest first

Every local server the agent runs inside the pod that has been exposed on an origin of its own.

Path parameters

idstringrequired

The session id

Response · 200

portsobject[]required
▸ Show child attributes
portintegerrequired

What the app listens on inside the pod

idstringrequired

Names the origin; not a credential

urlstringrequired

https://app-<id>.agentsky.dev/ — stable for the port's life

visibilityenum<string>required

"private" · "public"

created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/ports' \
  -H "Authorization: Bearer ast_..."

Expose a port the agent's local server listens on

Create-or-get: the port gets a stable origin `https://app-<id>.agentsky.dev/` relayed to the pod (HTTP and WebSocket) while the pod runs; calling again returns the same record, and a `visibility` in the body replaces the stored one in place. `port` is 1024–65535 and never the pod's own (400 invalid_request). A private port (the default) admits a browser only through an entry link from `POST …/grants`; a public port admits anyone with the address. A parked pod answers a paused page and is never woken by a visit. An archived session answers 400 session_archived.

Path parameters

idstringrequired

The session id

portintegerrequired

The port the app listens on inside the pod

Body · application/json

visibilityenum<string>

Omitted = keep the stored value (private for a new port) — "private" · "public"

Response · 200

portintegerrequired

What the app listens on inside the pod

idstringrequired

Names the origin; not a credential

urlstringrequired

https://app-<id>.agentsky.dev/ — stable for the port's life

visibilityenum<string>required

"private" · "public"

created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PUT https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/ports/port \
  -H "Authorization: Bearer ast_..."

One exposed port

Path parameters

idstringrequired

The session id

portintegerrequired

The port the app listens on inside the pod

Response · 200

portintegerrequired

What the app listens on inside the pod

idstringrequired

Names the origin; not a credential

urlstringrequired

https://app-<id>.agentsky.dev/ — stable for the port's life

visibilityenum<string>required

"private" · "public"

created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/ports/port' \
  -H "Authorization: Bearer ast_..."

Stop exposing a port

The origin answers 404 from then on (within a few seconds); browsers that had entered are signed out with it.

Path parameters

idstringrequired

The session id

portintegerrequired

The port the app listens on inside the pod

Response · 204

Revoked

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/ports/port \
  -H "Authorization: Bearer ast_..."

An entry link for an exposed port

For a private port: a single-use link, good for a minute, that signs the browser opening it in to the port's origin (a cookie that lives twelve hours) and lands on `path`; minting again supersedes the previous unused link. For a public port: the plain address. An archived session answers 400 session_archived.

Path parameters

idstringrequired

The session id

portintegerrequired

The port the app listens on inside the pod

Body · application/json

pathstring

Where on the app to land after entering; a path on the port's origin, default /

Response · 200

urlstringrequired

A private port: a single-use entry link, good for a minute; a public port: the plain address

expires_atstring | nullrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/ports/port/grants \
  -H "Authorization: Bearer ast_..."

List the session's resources, oldest first

`limit` (1–1000) pages the list with an opaque `page` cursor; omitted lists every resource in one answer.

Path parameters

idstringrequired

The session id (sess_…)

Query parameters

limitinteger
pagestring

A next_page cursor

Response · 200

dataobject[]required

Oldest first

▸ Show child attributes
option 1object
▸ Show child attributes
typeenum<string>required

"file"

idstringrequired

sesrsc_…

file_idstringrequired

The per-session copy (file_…), read-only at mount_path

mount_pathstringrequired

Absolute, under /workspace

created_atstringrequired
updated_atstringrequired
option 2object
▸ Show child attributes
typeenum<string>required

"github_repository"

idstringrequired

sesrsc_…

urlstringrequired

https://github.com/{owner}/{repo}

mount_pathstringrequired

Absolute, under /workspace; the clone's root

checkoutobject

{type:"branch", name} or {type:"commit", sha}; absent = the default branch

▸ Show child attributes
typeenum<string>

"branch" · "commit"

namestring
shastring
created_atstringrequired
updated_atstringrequired
option 3object
▸ Show child attributes
typeenum<string>required

"memory_store"

idstringrequired

smsr_…

memory_store_idstringrequired

memstore_…

mount_pathstringrequired

Absolute, under /mnt/memory

accessenum<string>required

"read_only" · "read_write"

instructionsstring

Optional per-session guidance

created_atstringrequired
updated_atstringrequired
next_pagestring | nullrequired

Pass back as ?page= for the next page; null when `limit` was omitted or the list ended

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/resources' \
  -H "Authorization: Bearer ast_..."
Response · 200 OK
{
  "data": [
    {
      "type": "file",
      "id": "sesrsc_cmtc1a2b",
      "file_id": "file_cmtc1a2c",
      "mount_path": "/workspace/data/signups.csv",
      "created_at": "2026-09-11T18:00:00.000Z",
      "updated_at": "2026-09-11T18:00:00.000Z"
    },
    {
      "type": "github_repository",
      "id": "sesrsc_cmtc1a2d",
      "url": "https://github.com/acme/growth",
      "mount_path": "/workspace/growth",
      "checkout": {
        "type": "branch",
        "name": "main"
      },
      "created_at": "2026-09-11T18:00:00.000Z",
      "updated_at": "2026-09-11T18:00:00.000Z"
    },
    {
      "type": "memory_store",
      "id": "smsr_cmtc1a2e",
      "memory_store_id": "memstore_cmtb9x4p",
      "mount_path": "/mnt/memory/memstore_cmtb9x4p",
      "access": "read_only",
      "created_at": "2026-09-11T18:00:00.000Z",
      "updated_at": "2026-09-11T18:00:00.000Z"
    }
  ],
  "next_page": null
}

Add a file to a running session

Files only — repositories and memory stores can only be attached at session create. The file is copied read-only to `/workspace<mount_path>` before the session's next turn; `mount_path` follows the create rules (rooted under /workspace, no escape, no overlap with another resource). 400 too_many_resources past 500 per session; 400 session_archived on an archived session.

Path parameters

idstringrequired

The session id (sess_…)

Body · application/json

type: "file"object
▸ Show child attributes
type"file"required
file_idstringrequired

max length 128

mount_pathstring | null

max length 4096

type: "github_repository"object
▸ Show child attributes
type"github_repository"required
urlstringrequired

max length 2048

authorization_tokenstring

max length 1024

checkoutobject | null
▸ Show child attributes
type: "branch"object
▸ Show child attributes
type"branch"required
namestringrequired

max length 255

type: "commit"object
▸ Show child attributes
type"commit"required
shastringrequired

max length 64

mount_pathstring | null

max length 4096

type: "memory_store"object
▸ Show child attributes
type"memory_store"required
memory_store_idstringrequired

max length 255

accessenum<string>required

"read_only" · "read_write"

instructionsstring

max length 4096

mount_pathstring | null

max length 4096

Response · 200

option 1object
▸ Show child attributes
typeenum<string>required

"file"

idstringrequired

sesrsc_…

file_idstringrequired

The per-session copy (file_…), read-only at mount_path

mount_pathstringrequired

Absolute, under /workspace

created_atstringrequired
updated_atstringrequired
option 2object
▸ Show child attributes
typeenum<string>required

"github_repository"

idstringrequired

sesrsc_…

urlstringrequired

https://github.com/{owner}/{repo}

mount_pathstringrequired

Absolute, under /workspace; the clone's root

checkoutobject

{type:"branch", name} or {type:"commit", sha}; absent = the default branch

▸ Show child attributes
typeenum<string>

"branch" · "commit"

namestring
shastring
created_atstringrequired
updated_atstringrequired
option 3object
▸ Show child attributes
typeenum<string>required

"memory_store"

idstringrequired

smsr_…

memory_store_idstringrequired

memstore_…

mount_pathstringrequired

Absolute, under /mnt/memory

accessenum<string>required

"read_only" · "read_write"

instructionsstring

Optional per-session guidance

created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/resources \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"type":"file","file_id":"file_cmtb9x4p","mount_path":"/data/signups.csv"}'
Response · 200 OK
{
  "type": "file",
  "id": "sesrsc_cmtc1a2b",
  "file_id": "file_cmtc1a2c",
  "mount_path": "/workspace/data/signups.csv",
  "created_at": "2026-09-11T18:00:00.000Z",
  "updated_at": "2026-09-11T18:00:00.000Z"
}

One resource

Path parameters

idstringrequired

The session id (sess_…)

ridstringrequired

The resource id (sesrsc_… or smsr_…)

Response · 200

option 1object
▸ Show child attributes
typeenum<string>required

"file"

idstringrequired

sesrsc_…

file_idstringrequired

The per-session copy (file_…), read-only at mount_path

mount_pathstringrequired

Absolute, under /workspace

created_atstringrequired
updated_atstringrequired
option 2object
▸ Show child attributes
typeenum<string>required

"github_repository"

idstringrequired

sesrsc_…

urlstringrequired

https://github.com/{owner}/{repo}

mount_pathstringrequired

Absolute, under /workspace; the clone's root

checkoutobject

{type:"branch", name} or {type:"commit", sha}; absent = the default branch

▸ Show child attributes
typeenum<string>

"branch" · "commit"

namestring
shastring
created_atstringrequired
updated_atstringrequired
option 3object
▸ Show child attributes
typeenum<string>required

"memory_store"

idstringrequired

smsr_…

memory_store_idstringrequired

memstore_…

mount_pathstringrequired

Absolute, under /mnt/memory

accessenum<string>required

"read_only" · "read_write"

instructionsstring

Optional per-session guidance

created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/resources/sesrsc_cmtc1a2d' \
  -H "Authorization: Bearer ast_..."

Rotate a repository's token

Only `github_repository` resources accept an update, and the token is the only field: it is re-encrypted and the session's egress policy is recompiled and pushed to its live pod — nothing changes inside the sandbox. A file or memory store answers 400. A token that conflicts with another secret's Authorization header on github.com answers 400 egress_header_conflict.

Path parameters

idstringrequired

The session id (sess_…)

ridstringrequired

The resource id (sesrsc_… or smsr_…)

Body · application/json

authorization_tokenstringrequired

max length 1024

Response · 200

option 1object
▸ Show child attributes
typeenum<string>required

"file"

idstringrequired

sesrsc_…

file_idstringrequired

The per-session copy (file_…), read-only at mount_path

mount_pathstringrequired

Absolute, under /workspace

created_atstringrequired
updated_atstringrequired
option 2object
▸ Show child attributes
typeenum<string>required

"github_repository"

idstringrequired

sesrsc_…

urlstringrequired

https://github.com/{owner}/{repo}

mount_pathstringrequired

Absolute, under /workspace; the clone's root

checkoutobject

{type:"branch", name} or {type:"commit", sha}; absent = the default branch

▸ Show child attributes
typeenum<string>

"branch" · "commit"

namestring
shastring
created_atstringrequired
updated_atstringrequired
option 3object
▸ Show child attributes
typeenum<string>required

"memory_store"

idstringrequired

smsr_…

memory_store_idstringrequired

memstore_…

mount_pathstringrequired

Absolute, under /mnt/memory

accessenum<string>required

"read_only" · "read_write"

instructionsstring

Optional per-session guidance

created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/resources/sesrsc_cmtc1a2d \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"authorization_token":"github_pat_…"}'

Remove a file from the session

Files only — the resource and its per-session copy are deleted and the pod unlinks the file before the session's next turn. A repository or memory store answers 400: neither can be removed mid-session.

Path parameters

idstringrequired

The session id (sess_…)

ridstringrequired

The resource id (sesrsc_… or smsr_…)

Response · 200

typeenum<string>required

"session_resource_deleted"

idstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/resources/sesrsc_cmtc1a2d \
  -H "Authorization: Bearer ast_..."
Response · 200 OK
{
  "type": "session_resource_deleted",
  "id": "sesrsc_cmtc1a2b"
}

Conversation

Deprecated — use POST /sessions/{id}/events

The legacy input shape ({parts}); accepted for one release and translated to a single user.message, then 410. Optional Idempotency-Key header dedupes retries.

Path parameters

idstringrequired

The session id

Body · application/json

partsobject[]required
▸ Show child attributes
type: "text"object
▸ Show child attributes
indexintegerrequired
type"text"required
textstring

default: ""

stream_idstring | null
stream_indexinteger | null
type: "reasoning"object
▸ Show child attributes
indexintegerrequired
type"reasoning"required
textstring

default: ""

redactedboolean

default: false

stream_idstring | null
stream_indexinteger | null
type: "tool_call"object
▸ Show child attributes
indexintegerrequired
type"tool_call"required
call_idstringrequired
tool_namestringrequired
argsmap<string, any>

default: {}

args_partialstring | null
type: "tool_result"object
▸ Show child attributes
indexintegerrequired
type"tool_result"required
call_idstringrequired
tool_namestringrequired
statusenum<string>

"ok" · "error" — default: "ok"

resultmap<string, any>

default: {}

type: "file"object
▸ Show child attributes
indexintegerrequired
type"file"required
namestringrequired
media_typestringrequired
uristring | null
datastring | null
size_bytesinteger | null
type: "image"object
▸ Show child attributes
indexintegerrequired
type"image"required
media_typestringrequired
uristring | null
datastring | null
altstring | null
widthinteger | null
heightinteger | null
type: "video"object
▸ Show child attributes
indexintegerrequired
type"video"required
media_typestringrequired
uristring | null
datastring | null
altstring | null
widthinteger | null
heightinteger | null
duration_msinteger | null
size_bytesinteger | null
thumbnail_uristring | null
type: "status"object
▸ Show child attributes
indexintegerrequired
type"status"required
levelenum<string>required

"thinking" · "working" · "waiting" · "idle" · "done"

textstring | null
type: "error"object
▸ Show child attributes
indexintegerrequired
type"error"required
codestringrequired
messagestringrequired
retryableboolean

default: false

Response · 202

Accepted — body is {}; output arrives on the stream

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/messages \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"parts":[{"type":"text","index":0,"text":"Summarize the signups from today"}]}'
Response · 202 Accepted
{}

Send events — the one input: user.message, user.interrupt, system.message

The conversation plane (edge-routed to the chat-proxy). Body {events: [...]} (1–50), optionally requireIdle: true for one user.message (and optional trailing system.message). Exclusive admission refuses a busy session with 409 before persisting or delivering the message; a successful echo's user id names the admitted run. Its admission field is created only when this POST committed the exclusive input; an idempotent replay returns replayed. This field is not part of history or SSE. This is a Session admission receipt, not proof that another client's earlier queued joined input has finished on the Pod. Ordinary sends may join an open run. validated all-or-nothing. A user.message carries content blocks: text, image and document with base64 / url / file sources (inline base64 ≤ 20 MiB per request; larger content goes through POST /files). A system.message (text only) must be last and follow the user.message it accompanies: privileged context for that turn and, through the agent's transcript, later turns. user.interrupt stops the in-flight turn; with mode: "save" it instead asks the run to start no new work, save what it has (files plus a progress note in the working directory) and end its turn with a reply listing what was saved, and stops it only if it is still running after a 10 minute grace window (echo status saving, or no_turn when nothing is running). A later user.message continues in the same session. Every event echoes back in the history shape with a stable id; sources are echoed as file sources naming per-session copies (never base64). Optional Idempotency-Key header: a replay returns the original echo. 402 insufficient_credits / budget_reached, 503 egress_policy_failed, 400 session_archived refuse the whole request before any row is written.

Path parameters

idstringrequired

The session id

Body · application/json

eventsobject[]required
▸ Show child attributes
type: "user.message"object
▸ Show child attributes
type"user.message"required
contentobject[]required
▸ Show child attributes
type: "text"object
▸ Show child attributes
type"text"required
textstringrequired
type: "image"object
▸ Show child attributes
type"image"required
sourceobjectrequired
▸ Show child attributes
type: "base64"object
▸ Show child attributes
type"base64"required
media_typestringrequired
datastringrequired
type: "url"object
▸ Show child attributes
type"url"required
urlstringrequired
type: "file"object
▸ Show child attributes
type"file"required
file_idstringrequired
type: "document"object
▸ Show child attributes
type"document"required
sourceobjectrequired
▸ Show child attributes
type: "base64"object
▸ Show child attributes
type"base64"required
media_typestringrequired
datastringrequired
type: "text"object
▸ Show child attributes
type"text"required
media_type"text/plain"

default: "text/plain"

datastringrequired
type: "url"object
▸ Show child attributes
type"url"required
urlstringrequired
type: "file"object
▸ Show child attributes
type"file"required
file_idstringrequired
titlestring | null
contextstring | null
interaction_modeenum<string> | null

"plan" · "build"

type: "system.message"object
▸ Show child attributes
type"system.message"required
contentobject[]required
▸ Show child attributes
type"text"required
textstringrequired
type: "user.interrupt"object
▸ Show child attributes
type"user.interrupt"required
modeenum<string>

"immediate" · "save"

requireIdleboolean

Response · 200

OK — one echo per event, in order

dataany[]required

One echo per event, in order, in the events-history shape

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/events \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"requireIdle":true,"events":[{"type":"user.message","content":[{"type":"text","text":"What is in this screenshot?"},{"type":"image","source":{"type":"file","file_id":"file_cmtb9x4p"}}]},{"type":"system.message","content":[{"type":"text","text":"Answer in one paragraph."}]}]}'
Response · 200 OK
{
  "data": [
    {
      "id": "api-user-3f2c…",
      "type": "user.message",
      "admission": "created",
      "sessionId": "sess_cmtb7q2j",
      "agentId": "agent_cmtb2f0a8m9k7x51q4ez6r0d",
      "at": "2026-09-10T18:00:00.000Z",
      "content": [
        {
          "type": "text",
          "text": "What is in this screenshot?"
        },
        {
          "type": "image",
          "source": {
            "type": "file",
            "file_id": "file_cmtb9y1q"
          }
        }
      ]
    },
    {
      "id": "api-user-3f2c…#system",
      "type": "system.message",
      "sessionId": "sess_cmtb7q2j",
      "agentId": "agent_cmtb2f0a8m9k7x51q4ez6r0d",
      "at": "2026-09-10T18:00:00.000Z",
      "content": [
        {
          "type": "text",
          "text": "Answer in one paragraph."
        }
      ]
    }
  ]
}

The event history — the same event objects the stream delivers

The session's history, one event per message: user.message and system.message (with content), agent.message (with parts), user.interrupt, and the turn marks session.status_running, session.status_idle (stop_reason.type is end_turn, retries_exhausted, provider_lost or budget_reached) and session.error. agent.reasoning, agent.tool_use, agent.tool_result and agent.status appear on the live stream only, not in history. Oldest-first with an opaque numeric cursor. Reconnect = open the stream, list events, dedupe by event id. types[] filters (e.g. types[]=user.message&types[]=agent.message is the transcript view).

Path parameters

idstringrequired

The session id

Query parameters

cursorstring
limitinteger
types[]array

Response · 200

eventsobject[]required

Oldest-first

▸ Show child attributes
idstringrequired

Stable event id — the dedupe key across stream ∪ events

typestringrequired

user.message · system.message (both history only — never on the live stream; they carry `content`) · agent.message · agent.reasoning · agent.tool_use · agent.tool_result · agent.status · user.interrupt · session.status_running · session.status_idle · session.error · session.status_terminated · session.deleted

sessionIdstringrequired
agentIdstring | null

The agent id (agent_…)

atstring

ISO 8601

messageIdstring

agent.message

partsobject[]

agent.message

▸ Show child attributes
type: "text"object
▸ Show child attributes
indexintegerrequired
type"text"required
textstring

default: ""

stream_idstring | null
stream_indexinteger | null
type: "reasoning"object
▸ Show child attributes
indexintegerrequired
type"reasoning"required
textstring

default: ""

redactedboolean

default: false

stream_idstring | null
stream_indexinteger | null
type: "tool_call"object
▸ Show child attributes
indexintegerrequired
type"tool_call"required
call_idstringrequired
tool_namestringrequired
argsmap<string, any>

default: {}

args_partialstring | null
type: "tool_result"object
▸ Show child attributes
indexintegerrequired
type"tool_result"required
call_idstringrequired
tool_namestringrequired
statusenum<string>

"ok" · "error" — default: "ok"

resultmap<string, any>

default: {}

type: "file"object
▸ Show child attributes
indexintegerrequired
type"file"required
namestringrequired
media_typestringrequired
uristring | null
datastring | null
size_bytesinteger | null
type: "image"object
▸ Show child attributes
indexintegerrequired
type"image"required
media_typestringrequired
uristring | null
datastring | null
altstring | null
widthinteger | null
heightinteger | null
type: "video"object
▸ Show child attributes
indexintegerrequired
type"video"required
media_typestringrequired
uristring | null
datastring | null
altstring | null
widthinteger | null
heightinteger | null
duration_msinteger | null
size_bytesinteger | null
thumbnail_uristring | null
type: "status"object
▸ Show child attributes
indexintegerrequired
type"status"required
levelenum<string>required

"thinking" · "working" · "waiting" · "idle" · "done"

textstring | null
type: "error"object
▸ Show child attributes
indexintegerrequired
type"error"required
codestringrequired
messagestringrequired
retryableboolean

default: false

textstring

agent.message — parts flattened to plain text

contentobject[]

user.message / system.message — the CMA content blocks as sent (text · image · document); every image/document source is a `file` source naming a per-session copy readable through GET /files/{file_id}/content

partobject

reasoning / tool_use / tool_result / status events

▸ Show child attributes
type: "text"object
▸ Show child attributes
indexintegerrequired
type"text"required
textstring

default: ""

stream_idstring | null
stream_indexinteger | null
type: "reasoning"object
▸ Show child attributes
indexintegerrequired
type"reasoning"required
textstring

default: ""

redactedboolean

default: false

stream_idstring | null
stream_indexinteger | null
type: "tool_call"object
▸ Show child attributes
indexintegerrequired
type"tool_call"required
call_idstringrequired
tool_namestringrequired
argsmap<string, any>

default: {}

args_partialstring | null
type: "tool_result"object
▸ Show child attributes
indexintegerrequired
type"tool_result"required
call_idstringrequired
tool_namestringrequired
statusenum<string>

"ok" · "error" — default: "ok"

resultmap<string, any>

default: {}

type: "file"object
▸ Show child attributes
indexintegerrequired
type"file"required
namestringrequired
media_typestringrequired
uristring | null
datastring | null
size_bytesinteger | null
type: "image"object
▸ Show child attributes
indexintegerrequired
type"image"required
media_typestringrequired
uristring | null
datastring | null
altstring | null
widthinteger | null
heightinteger | null
type: "video"object
▸ Show child attributes
indexintegerrequired
type"video"required
media_typestringrequired
uristring | null
datastring | null
altstring | null
widthinteger | null
heightinteger | null
duration_msinteger | null
size_bytesinteger | null
thumbnail_uristring | null
type: "status"object
▸ Show child attributes
indexintegerrequired
type"status"required
levelenum<string>required

"thinking" · "working" · "waiting" · "idle" · "done"

textstring | null
type: "error"object
▸ Show child attributes
indexintegerrequired
type"error"required
codestringrequired
messagestringrequired
retryableboolean

default: false

stop_reasonobject

session.status_idle — discriminate on type; never break on bare idle

▸ Show child attributes
typestring

"end_turn" (also after an interrupt) | "retries_exhausted" (preceded by an exhausted engine error) | "provider_lost" (confirmed runtime Pod loss, preceded by an exhausted session.error) | "budget_reached"; more reserved

errorobject

session.error — the stream stays open; a session.status_idle follows once the turn is over

▸ Show child attributes
typestring

e.g. "pod_unavailable"

messagestring
retry_statusstring

"retrying" (the turn continues) | "exhausted" (the turn is over)

bystring

user.interrupt — who requested the interrupt

modeenum<string>

user.interrupt — present on a save interrupt: the run was asked to save its work and end itself — "save"

deadline_atstring

user.interrupt with mode save — when the run is stopped if it has not ended by then

causeenum<string>

user.interrupt — present when the platform stopped a run whose save grace window ran out — "save_timeout"

actorobject

user.message only, in history and in the send echo: who sent it, present only when that was not the session's owner

▸ Show child attributes
idstring
namestring | null
cursorstring | nullrequired

Pass back as ?cursor= for the next page; null when the session has no events

hasMorebooleanrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/events' \
  -H "Authorization: Bearer ast_..."
Response · 200 OK
{
  "events": [
    {
      "id": "api-user-8c41f0…#idle",
      "type": "session.status_idle",
      "sessionId": "sess-8c41f0…",
      "agent": "agent_cmtb2f0a8m9k7x51q4ez6r0d",
      "stop_reason": {
        "type": "end_turn"
      }
    }
  ],
  "cursor": "42",
  "hasMore": false
}

The standing event stream (SSE)

text/event-stream, stays open across turns. If a run is in flight when the stream opens, its status marks so far (session.status_running, session.error, user.interrupt) are replayed from history under their own ids and timestamps, so a stream opened mid-run still sees the boundary its duration is measured from; a run that has already ended is not replayed — read it from the event history. Everything else is live. Dedupe by event id. Events: agent.message, agent.reasoning, agent.tool_use, agent.tool_result, agent.status, session.status_running, session.status_idle (carries stop_reason — never break on bare idle), session.error (the stream stays open; an idle follows), user.interrupt, session.status_terminated (terminal), session.deleted (terminal). User messages are not sent on the live stream — they appear in the event history only. Reconnect = reopen + list events + dedupe by event id.

Path parameters

idstringrequired

The session id

Response · 200

SSE stream

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -N 'https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/stream' \
  -H "Authorization: Bearer ast_..."

Abort the in-flight turn

Path parameters

idstringrequired

The session id

Response · 200

statusenum<string>required

no_turn = nothing in flight; otherwise user.interrupt echoes on the stream and the pod's session.status_idle follows — "interrupting" · "no_turn"

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/interrupt \
  -H "Authorization: Bearer ast_..."
Response · 200 OK
{
  "status": "interrupting"
}

Goals

The session's standing goal, or null

A goal is an objective the session works toward on its own: after each turn settles, the platform grades the work against the goal's criteria and either takes another turn or stops. At most one goal per session.

Path parameters

idstringrequired

The session id

Response · 200

goalobject | nullrequired
▸ Show child attributes
idstringrequired

goal_…

sessionstringrequired

sess_…

objectivestringrequired
criteriaobject[]required
▸ Show child attributes
idstringrequired

Stable within the goal, e.g. c1

textstringrequired
commandstring

Present when a shell command decides this criterion: it runs in the session's workspace after each iteration, and exit 0 means met. The grader cannot overturn it.

criteria_sourceenum<string>required

Whether the caller supplied the criteria or the platform derived them from the objective — "user" · "derived"

statusenum<string>required

"active" · "paused" · "completed" · "stopped"

stop_reasonstring | nullrequired

Why a stopped goal stopped; null in every other status — "failed" · "max_iterations" · "spend_budget" · "token_budget" · "time_budget" · "no_progress" · "cleared" · "session_ended" · null

iterationintegerrequired

Self-started turns taken so far

max_iterationsintegerrequired
max_spendobject | nullrequired
▸ Show child attributes
amountstring
currencyenum<string>

"USD"

consumed_spendobjectrequired

What this session has spent since the goal started

▸ Show child attributes
amountstring
currencyenum<string>

"USD"

max_tokensinteger | nullrequired

Token ceiling for this goal; null = none

consumed_tokensintegerrequired

Uncached input plus output tokens over the session's metered model calls since the goal started, grading included. Calls on the session's own model subscription are not metered and not counted.

deadline_atstring | nullrequired
last_evaluationany | nullrequired
created_atstringrequired
updated_atstringrequired
completed_atstring | nullrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/goal' \
  -H "Authorization: Bearer ast_..."

Set the session's goal, replacing any existing one

Work starts immediately — no separate message is needed, and sending one is not how a goal begins. Criteria are optional: omitted, they are derived from the objective so completion is always judged against an explicit list, which the response returns and PATCH can correct. A criterion given as { text, command } is decided by running the command in the session's workspace (exit 0 = met) instead of by the grader. A person's message always outranks the loop: while a turn is running the goal waits, and takes the turn after it. Grading is a model call billed to the session; with an empty wallet deriving criteria is refused with 402 insufficient_credits. Setting a goal stops the run the goal it replaces had started.

Path parameters

idstringrequired

The session id

Body · application/json

objectivestringrequired

What the agent should work toward, in the user's words — max length 4000

criteria(string | object)[]

Independently checkable requirements; omitted = derived from the objective

▸ Show child attributes
option 1string

max length 500

option 2object
▸ Show child attributes
textstringrequired

What the criterion requires, in words — max length 500

commandstring

Shell command run in the session's workspace; exit 0 means the criterion is met — max length 1000

max_iterationsinteger | null

Self-started turns this goal may take before it stops. Omitted = 20; null = no iteration ceiling

max_no_progressinteger | null

Consecutive turns without a tool call before stopping. Omitted = 3; null = no no-progress ceiling

max_spendobject | null

Spend ceiling for this goal; null = none

▸ Show child attributes
amountstringrequired

Whole US cents as an integer decimal string, e.g. "500" for $5.00 — max length 15

currency"USD"required
max_tokensinteger | null
max_duration_minutesinteger | null

Wall-clock ceiling from the goal's start, extended by any time it spends paused

Response · 201

goalobjectrequired
▸ Show child attributes
idstringrequired

goal_…

sessionstringrequired

sess_…

objectivestringrequired
criteriaobject[]required
▸ Show child attributes
idstringrequired

Stable within the goal, e.g. c1

textstringrequired
commandstring

Present when a shell command decides this criterion: it runs in the session's workspace after each iteration, and exit 0 means met. The grader cannot overturn it.

criteria_sourceenum<string>required

Whether the caller supplied the criteria or the platform derived them from the objective — "user" · "derived"

statusenum<string>required

"active" · "paused" · "completed" · "stopped"

stop_reasonstring | nullrequired

Why a stopped goal stopped; null in every other status — "failed" · "max_iterations" · "spend_budget" · "token_budget" · "time_budget" · "no_progress" · "cleared" · "session_ended" · null

iterationintegerrequired

Self-started turns taken so far

max_iterationsintegerrequired
max_spendobject | nullrequired
▸ Show child attributes
amountstring
currencyenum<string>

"USD"

consumed_spendobjectrequired

What this session has spent since the goal started

▸ Show child attributes
amountstring
currencyenum<string>

"USD"

max_tokensinteger | nullrequired

Token ceiling for this goal; null = none

consumed_tokensintegerrequired

Uncached input plus output tokens over the session's metered model calls since the goal started, grading included. Calls on the session's own model subscription are not metered and not counted.

deadline_atstring | nullrequired
last_evaluationobject | nullrequired
▸ Show child attributes
resultenum<string>required

"satisfied" · "needs_revision" · "failed"

explanationstringrequired
criteriaobject[]required
▸ Show child attributes
idstringrequired
metbooleanrequired
reasonstringrequired
judged_byenum<string>

What decided this criterion on this iteration — "grader" · "command"

iterationintegerrequired
atstringrequired
created_atstringrequired
updated_atstringrequired
completed_atstring | nullrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/goal \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"objective":"Get the failing integration tests in packages/api passing without weakening them.","criteria":[{"text":"The integration tests pass","command":"cd packages/api && npm test"},"No test assertion was deleted, skipped, or loosened","The fix is in source, not in the tests"],"max_iterations":15,"max_spend":{"amount":"500","currency":"USD"},"max_tokens":2000000}'

Edit the goal in place

A course correction for an active or paused goal, not a restart: the iteration count and spend already consumed carry over. Editing criteria marks them as the caller's. A completed or stopped goal returns 409; POST a new goal to start another outcome.

Path parameters

idstringrequired

The session id

Body · application/json

objectivestring

max length 4000

criteria(string | object)[]
▸ Show child attributes
option 1string

max length 500

option 2object
▸ Show child attributes
textstringrequired

What the criterion requires, in words — max length 500

commandstring

Shell command run in the session's workspace; exit 0 means the criterion is met — max length 1000

max_iterationsinteger | null
max_no_progressinteger | null
max_spendobject | null
▸ Show child attributes
amountstringrequired

Whole US cents as an integer decimal string, e.g. "500" for $5.00 — max length 15

currency"USD"required
max_tokensinteger | null
max_duration_minutesinteger | null

Response · 200

goalobjectrequired
▸ Show child attributes
idstringrequired

goal_…

sessionstringrequired

sess_…

objectivestringrequired
criteriaobject[]required
▸ Show child attributes
idstringrequired

Stable within the goal, e.g. c1

textstringrequired
commandstring

Present when a shell command decides this criterion: it runs in the session's workspace after each iteration, and exit 0 means met. The grader cannot overturn it.

criteria_sourceenum<string>required

Whether the caller supplied the criteria or the platform derived them from the objective — "user" · "derived"

statusenum<string>required

"active" · "paused" · "completed" · "stopped"

stop_reasonstring | nullrequired

Why a stopped goal stopped; null in every other status — "failed" · "max_iterations" · "spend_budget" · "token_budget" · "time_budget" · "no_progress" · "cleared" · "session_ended" · null

iterationintegerrequired

Self-started turns taken so far

max_iterationsintegerrequired
max_spendobject | nullrequired
▸ Show child attributes
amountstring
currencyenum<string>

"USD"

consumed_spendobjectrequired

What this session has spent since the goal started

▸ Show child attributes
amountstring
currencyenum<string>

"USD"

max_tokensinteger | nullrequired

Token ceiling for this goal; null = none

consumed_tokensintegerrequired

Uncached input plus output tokens over the session's metered model calls since the goal started, grading included. Calls on the session's own model subscription are not metered and not counted.

deadline_atstring | nullrequired
last_evaluationobject | nullrequired
▸ Show child attributes
resultenum<string>required

"satisfied" · "needs_revision" · "failed"

explanationstringrequired
criteriaobject[]required
▸ Show child attributes
idstringrequired
metbooleanrequired
reasonstringrequired
judged_byenum<string>

What decided this criterion on this iteration — "grader" · "command"

iterationintegerrequired
atstringrequired
created_atstringrequired
updated_atstringrequired
completed_atstring | nullrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PATCH https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/goal \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"criteria":[{"text":"The integration tests pass","command":"cd packages/api && npm test"},"No test assertion was deleted, skipped, or loosened"]}'

Clear the goal

Stops the loop for good with stop_reason "cleared", and interrupts the run the goal itself started if one is going. The record stays readable so the session can still report what it was working on; setting a new goal replaces it.

Path parameters

idstringrequired

The session id

Response · 200

goalobjectrequired
▸ Show child attributes
idstringrequired

goal_…

sessionstringrequired

sess_…

objectivestringrequired
criteriaobject[]required
▸ Show child attributes
idstringrequired

Stable within the goal, e.g. c1

textstringrequired
commandstring

Present when a shell command decides this criterion: it runs in the session's workspace after each iteration, and exit 0 means met. The grader cannot overturn it.

criteria_sourceenum<string>required

Whether the caller supplied the criteria or the platform derived them from the objective — "user" · "derived"

statusenum<string>required

"active" · "paused" · "completed" · "stopped"

stop_reasonstring | nullrequired

Why a stopped goal stopped; null in every other status — "failed" · "max_iterations" · "spend_budget" · "token_budget" · "time_budget" · "no_progress" · "cleared" · "session_ended" · null

iterationintegerrequired

Self-started turns taken so far

max_iterationsintegerrequired
max_spendobject | nullrequired
▸ Show child attributes
amountstring
currencyenum<string>

"USD"

consumed_spendobjectrequired

What this session has spent since the goal started

▸ Show child attributes
amountstring
currencyenum<string>

"USD"

max_tokensinteger | nullrequired

Token ceiling for this goal; null = none

consumed_tokensintegerrequired

Uncached input plus output tokens over the session's metered model calls since the goal started, grading included. Calls on the session's own model subscription are not metered and not counted.

deadline_atstring | nullrequired
last_evaluationobject | nullrequired
▸ Show child attributes
resultenum<string>required

"satisfied" · "needs_revision" · "failed"

explanationstringrequired
criteriaobject[]required
▸ Show child attributes
idstringrequired
metbooleanrequired
reasonstringrequired
judged_byenum<string>

What decided this criterion on this iteration — "grader" · "command"

iterationintegerrequired
atstringrequired
created_atstringrequired
updated_atstringrequired
completed_atstring | nullrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/goal \
  -H "Authorization: Bearer ast_..."

Stop driving the goal

Stops taking turns and interrupts the run the goal itself started, if one is going. A run a person started is left to finish; POST /sessions/{id}/interrupt stops that. Refused with 409 invalid_state unless the goal is active.

Path parameters

idstringrequired

The session id

Response · 200

goalobjectrequired
▸ Show child attributes
idstringrequired

goal_…

sessionstringrequired

sess_…

objectivestringrequired
criteriaobject[]required
▸ Show child attributes
idstringrequired

Stable within the goal, e.g. c1

textstringrequired
commandstring

Present when a shell command decides this criterion: it runs in the session's workspace after each iteration, and exit 0 means met. The grader cannot overturn it.

criteria_sourceenum<string>required

Whether the caller supplied the criteria or the platform derived them from the objective — "user" · "derived"

statusenum<string>required

"active" · "paused" · "completed" · "stopped"

stop_reasonstring | nullrequired

Why a stopped goal stopped; null in every other status — "failed" · "max_iterations" · "spend_budget" · "token_budget" · "time_budget" · "no_progress" · "cleared" · "session_ended" · null

iterationintegerrequired

Self-started turns taken so far

max_iterationsintegerrequired
max_spendobject | nullrequired
▸ Show child attributes
amountstring
currencyenum<string>

"USD"

consumed_spendobjectrequired

What this session has spent since the goal started

▸ Show child attributes
amountstring
currencyenum<string>

"USD"

max_tokensinteger | nullrequired

Token ceiling for this goal; null = none

consumed_tokensintegerrequired

Uncached input plus output tokens over the session's metered model calls since the goal started, grading included. Calls on the session's own model subscription are not metered and not counted.

deadline_atstring | nullrequired
last_evaluationobject | nullrequired
▸ Show child attributes
resultenum<string>required

"satisfied" · "needs_revision" · "failed"

explanationstringrequired
criteriaobject[]required
▸ Show child attributes
idstringrequired
metbooleanrequired
reasonstringrequired
judged_byenum<string>

What decided this criterion on this iteration — "grader" · "command"

iterationintegerrequired
atstringrequired
created_atstringrequired
updated_atstringrequired
completed_atstring | nullrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/goal/pause \
  -H "Authorization: Bearer ast_..."

Drive the goal again

Any wall-clock deadline moves out by the time the pause consumed. Refused with 409 invalid_state unless the goal is paused.

Path parameters

idstringrequired

The session id

Response · 200

goalobjectrequired
▸ Show child attributes
idstringrequired

goal_…

sessionstringrequired

sess_…

objectivestringrequired
criteriaobject[]required
▸ Show child attributes
idstringrequired

Stable within the goal, e.g. c1

textstringrequired
commandstring

Present when a shell command decides this criterion: it runs in the session's workspace after each iteration, and exit 0 means met. The grader cannot overturn it.

criteria_sourceenum<string>required

Whether the caller supplied the criteria or the platform derived them from the objective — "user" · "derived"

statusenum<string>required

"active" · "paused" · "completed" · "stopped"

stop_reasonstring | nullrequired

Why a stopped goal stopped; null in every other status — "failed" · "max_iterations" · "spend_budget" · "token_budget" · "time_budget" · "no_progress" · "cleared" · "session_ended" · null

iterationintegerrequired

Self-started turns taken so far

max_iterationsintegerrequired
max_spendobject | nullrequired
▸ Show child attributes
amountstring
currencyenum<string>

"USD"

consumed_spendobjectrequired

What this session has spent since the goal started

▸ Show child attributes
amountstring
currencyenum<string>

"USD"

max_tokensinteger | nullrequired

Token ceiling for this goal; null = none

consumed_tokensintegerrequired

Uncached input plus output tokens over the session's metered model calls since the goal started, grading included. Calls on the session's own model subscription are not metered and not counted.

deadline_atstring | nullrequired
last_evaluationobject | nullrequired
▸ Show child attributes
resultenum<string>required

"satisfied" · "needs_revision" · "failed"

explanationstringrequired
criteriaobject[]required
▸ Show child attributes
idstringrequired
metbooleanrequired
reasonstringrequired
judged_byenum<string>

What decided this criterion on this iteration — "grader" · "command"

iterationintegerrequired
atstringrequired
created_atstringrequired
updated_atstringrequired
completed_atstring | nullrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/goal/resume \
  -H "Authorization: Bearer ast_..."

Handoff

Hand this session's context to another agent

Accepted immediately; the move runs in the background. Poll the `status_url` in the response (also sent as the `Location` header) until `status` is terminal, then talk to `target_session`. `last_message_id` bounds how much history is carried; omitted = all of it. An `Idempotency-Key` header dedupes retries.

Path parameters

idstringrequired

The source session id (sess_…)

Body · application/json

target_agentstringrequired

max length 256

last_message_idstring

max length 256

Response · 202

Accepted — poll status_url

handoffobjectrequired

`resolved_mode` is how the move was actually made: `native_fork` when source and target share a harness and the pod's own state could be forked, else `summary` — a written handover the target reads as history, never as instructions. `target_session` is null until the move completes.

▸ Show child attributes
idstringrequired

handoff_…

source_sessionstring | null
target_sessionstring | null
last_message_idstring | null
target_agentstring | null
statusstringrequired

Lowercased HandoffStatus: pending · checkpointing · provisioning · restoring · completed · retry_wait · failed · cancelled. Terminal: completed, failed, cancelled.

resolved_modeenum<string>required

"native_fork" · "summary"

resolution_reasonstring | null
checkpointobject | null

What was carried across, without its content

summaryobject | null

What was carried across, without its content

errorobject | null
status_urlstringrequired

GET it to poll the move

created_atstringrequired
updated_atstringrequired
completed_atstring | null

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/handoff \
  -H "Authorization: Bearer ast_..."

The progress of one handoff

Path parameters

idstringrequired

The handoff id (handoff_…), as returned by POST /sessions/{id}/handoff

Response · 200

handoffobjectrequired

`resolved_mode` is how the move was actually made: `native_fork` when source and target share a harness and the pod's own state could be forked, else `summary` — a written handover the target reads as history, never as instructions. `target_session` is null until the move completes.

▸ Show child attributes
idstringrequired

handoff_…

source_sessionstring | null
target_sessionstring | null
last_message_idstring | null
target_agentstring | null
statusstringrequired

Lowercased HandoffStatus: pending · checkpointing · provisioning · restoring · completed · retry_wait · failed · cancelled. Terminal: completed, failed, cancelled.

resolved_modeenum<string>required

"native_fork" · "summary"

resolution_reasonstring | null
checkpointobject | null

What was carried across, without its content

summaryobject | null

What was carried across, without its content

errorobject | null
status_urlstringrequired

GET it to poll the move

created_atstringrequired
updated_atstringrequired
completed_atstring | null

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/session-handoffs/sess_cmtb7q2j' \
  -H "Authorization: Bearer ast_..."

Tasks

GET/tasksread

List the workspace's tasks

Most recent activity first. Helper and handoff sessions are counted inside their task and never listed on their own.

Query parameters

attentionstring

Return only tasks in this state

Response · 200

tasksobject[]required
▸ Show child attributes
idstringrequired

sess_… — the root session's id

titlestring | nullrequired
attentionenum<string>required

What the caller should do about the task. `needs_you`: a request addressed to the caller is open. `working`: a session in the task is running or starting, or the task is waiting on somebody else. `done`: a result arrived since the caller last marked the task seen. `idle`: nothing new. — "needs_you" · "working" · "done" · "idle"

status_linestring | nullrequired

One line, at most 140 characters, on where it stands: the oldest question waiting on the caller, else the start of the latest thing an agent said. Null when no agent has said anything.

open_request_countintegerrequired

Open requests addressed to the caller

session_countintegerrequired

The root session plus its helper and handoff sessions

sessionsobject[]required

Every session in the task, root first, each with its own share of the state: its own open requests, its own run and its own latest result, measured against the task's seen mark.

▸ Show child attributes
idstringrequired

sess_…

roleenum<string>required

"primary" · "helper" · "handoff"

attentionenum<string>required

What the caller should do about the task. `needs_you`: a request addressed to the caller is open. `working`: a session in the task is running or starting, or the task is waiting on somebody else. `done`: a result arrived since the caller last marked the task seen. `idle`: nothing new. — "needs_you" · "working" · "done" · "idle"

status_linestring | nullrequired

One line, at most 140 characters, on where it stands: the oldest question waiting on the caller, else the start of the latest thing an agent said. Null when no agent has said anything.

agent_idstring | nullrequired

The root session's agent (agent_…)

agent_typestringrequired
llmstringrequired
archivedbooleanrequired
last_activity_atstringrequired
created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/tasks' \
  -H "Authorization: Bearer ast_..."

One task with its sessions, open requests and cost

By default the id must name a task root. With by=session, resolves an accessible helper or handoff session to its containing task; both the member and root must be accessible.

Path parameters

idstringrequired

The task id: the id of its root session (sess_…)

Query parameters

bystring

Resolve this session to its existing task root.

Response · 200

taskobjectrequired
▸ Show child attributes
idstringrequired

sess_… — the root session's id

titlestring | nullrequired
attentionenum<string>required

What the caller should do about the task. `needs_you`: a request addressed to the caller is open. `working`: a session in the task is running or starting, or the task is waiting on somebody else. `done`: a result arrived since the caller last marked the task seen. `idle`: nothing new. — "needs_you" · "working" · "done" · "idle"

status_linestring | nullrequired

One line, at most 140 characters, on where it stands: the oldest question waiting on the caller, else the start of the latest thing an agent said. Null when no agent has said anything.

open_request_countintegerrequired

Open requests addressed to the caller

session_countintegerrequired

The root session plus its helper and handoff sessions

sessionsobject[]required

The root first, then the others in the order they joined

▸ Show child attributes
idstringrequired

sess_…

roleenum<string>required

"primary" · "helper" · "handoff"

attentionenum<string>required

What the caller should do about the task. `needs_you`: a request addressed to the caller is open. `working`: a session in the task is running or starting, or the task is waiting on somebody else. `done`: a result arrived since the caller last marked the task seen. `idle`: nothing new. — "needs_you" · "working" · "done" · "idle"

status_linestring | nullrequired

One line, at most 140 characters, on where it stands: the oldest question waiting on the caller, else the start of the latest thing an agent said. Null when no agent has said anything.

titlestring | nullrequired
statusenum<string>required

"provisioning" · "idle" · "running" · "terminated"

agent_idstring | nullrequired
agent_typestringrequired
llmstringrequired
consumed_costobjectrequired
▸ Show child attributes
amountstringrequired

Integer US cents, as a string

currencyenum<string>required

"USD"

model_paid_byobject

Who pays for the model in this session: the wallet, or the caller's own account at a vendor. Runtime is charged to the wallet either way. Present where external accounts are turned on.

▸ Show child attributes
sourceenum<string>required

"wallet" · "account"

vendorstring
namestring
created_atstringrequired
agent_idstring | nullrequired

The root session's agent (agent_…)

agent_typestringrequired
llmstringrequired
archivedbooleanrequired
last_activity_atstringrequired
created_atstringrequired
consumed_costobjectrequired

Billed cost summed over every session in the task, a paid agent's flat fee included

▸ Show child attributes
amountstringrequired

Integer US cents, as a string

currencyenum<string>required

"USD"

completion_answerobject | nullrequired

What the caller said about whether this task did the job; null until they answer. Other people's answers are not shown.

payerobject

Who pays for it, decided once when it was created and never changed. Present only when a payer was recorded, which happens in a team workspace where workspace wallets are on; absent means its owner's own balance pays.

▸ Show child attributes
typeenum<string>required

`workspace`: the team workspace's own wallet. `personal`: the balance of the person who started it. — "workspace" · "personal"

workspaceobject

The paying workspace; only with type workspace

▸ Show child attributes
slugstring
namestring
agent_feesobject[]

The flat fees of paid agents in this task. Present only when the task has one.

▸ Show child attributes
session_idstringrequired
handlestringrequired
feeobjectrequired
▸ Show child attributes
amountstringrequired

Whole US cents

currencyenum<string>required

"USD"

statusenum<string>required

`held`: set aside from the caller's credit when the task started. `captured`: taken, on the task's first result. `released`: given back because the task was archived or deleted without a result. `disputed`, `refunded`: see the dispute route. — "awaiting_confirmation" · "declined" · "held" · "captured" · "disputed" · "released" · "refunded"

dispute_untilstring | nullrequired

Until when the caller may say the task was not completed; null unless the fee is captured and undisputed

disputeobject | nullrequired

What the caller said and how it was ruled; null when the fee was never disputed.

requestsobject[]required

Open requests addressed to the caller, oldest first. Answer one by sending its reply to `session_id` as a message, exactly as a question is answered in that session.

▸ Show child attributes
idstringrequired

The request id the agent or the platform assigned

session_idstringrequired

The session that is waiting (sess_…)

message_idstringrequired
kindenum<string>required

`question`: an agent asked. `approval`: a tool needs the caller's go-ahead before it runs (options `allow`, `deny`), or a workspace rule asks for it before the task itself starts (options `confirm`, `decline`; nothing has run, and declining archives the task). `connect_app`: the agent needs an app that is not connected; it resolves by itself when the caller connects the app, or by answering `skip`. `connect_account`: the task cannot run without the caller's own account at a vendor, or that account has no usage left; what the caller sent is kept and nothing has run. It resolves by itself when the account is connected (`POST /external_accounts`), or by answering `use_wallet` (offered only when the account is exhausted or expired and the task can run on a platform model) or `wait`. `spend`: an agent whose maker asks a flat fee is about to be used for the first time at that price, either as this task's own agent (nothing has run, and nothing runs until it is answered) or as a helper an agent in the task wants to hire. Answer `confirm` or `decline`; a confirmation is remembered for that agent at that price. — "question" · "approval" · "connect_app" · "connect_account" · "spend"

subjectstring | nullrequired

For `connect_app`, the app's slug; for `connect_account`, the vendor; for `spend`, the agent's handle

questionstringrequired
optionsobject[]required
▸ Show child attributes
idstringrequired
labelstringrequired
descriptionstring
allow_free_textbooleanrequired
required_user_idstring | nullrequired

Set when only one person may answer

due_atstring | nullrequired
created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/tasks/sess_cmtb7q2j' \
  -H "Authorization: Bearer ast_..."

Mark the task seen by the caller

Records that the caller has looked at the task now, so a result that already arrived stops reading as `done` for them. Optional session_ids scopes the read to those task members; other members keep their unread results. Other people's view is unchanged. Answers 503 `not_available` until the platform's task tables are in place.

Path parameters

idstringrequired

The task id: the id of its root session (sess_…)

Body · application/json

session_idsstring[]

Only these task members are marked seen; omitted marks all current members. — max length 256

Response · 200

taskobjectrequired
▸ Show child attributes
idstringrequired

sess_… — the root session's id

titlestring | nullrequired
attentionenum<string>required

What the caller should do about the task. `needs_you`: a request addressed to the caller is open. `working`: a session in the task is running or starting, or the task is waiting on somebody else. `done`: a result arrived since the caller last marked the task seen. `idle`: nothing new. — "needs_you" · "working" · "done" · "idle"

status_linestring | nullrequired

One line, at most 140 characters, on where it stands: the oldest question waiting on the caller, else the start of the latest thing an agent said. Null when no agent has said anything.

open_request_countintegerrequired

Open requests addressed to the caller

session_countintegerrequired

The root session plus its helper and handoff sessions

sessionsobject[]required

The root first, then the others in the order they joined

▸ Show child attributes
idstringrequired

sess_…

roleenum<string>required

"primary" · "helper" · "handoff"

attentionenum<string>required

What the caller should do about the task. `needs_you`: a request addressed to the caller is open. `working`: a session in the task is running or starting, or the task is waiting on somebody else. `done`: a result arrived since the caller last marked the task seen. `idle`: nothing new. — "needs_you" · "working" · "done" · "idle"

status_linestring | nullrequired

One line, at most 140 characters, on where it stands: the oldest question waiting on the caller, else the start of the latest thing an agent said. Null when no agent has said anything.

titlestring | nullrequired
statusenum<string>required

"provisioning" · "idle" · "running" · "terminated"

agent_idstring | nullrequired
agent_typestringrequired
llmstringrequired
consumed_costobjectrequired
▸ Show child attributes
amountstringrequired

Integer US cents, as a string

currencyenum<string>required

"USD"

model_paid_byobject

Who pays for the model in this session: the wallet, or the caller's own account at a vendor. Runtime is charged to the wallet either way. Present where external accounts are turned on.

▸ Show child attributes
sourceenum<string>required

"wallet" · "account"

vendorstring
namestring
created_atstringrequired
agent_idstring | nullrequired

The root session's agent (agent_…)

agent_typestringrequired
llmstringrequired
archivedbooleanrequired
last_activity_atstringrequired
created_atstringrequired
consumed_costobjectrequired

Billed cost summed over every session in the task, a paid agent's flat fee included

▸ Show child attributes
amountstringrequired

Integer US cents, as a string

currencyenum<string>required

"USD"

completion_answerobject | nullrequired

What the caller said about whether this task did the job; null until they answer. Other people's answers are not shown.

payerobject

Who pays for it, decided once when it was created and never changed. Present only when a payer was recorded, which happens in a team workspace where workspace wallets are on; absent means its owner's own balance pays.

▸ Show child attributes
typeenum<string>required

`workspace`: the team workspace's own wallet. `personal`: the balance of the person who started it. — "workspace" · "personal"

workspaceobject

The paying workspace; only with type workspace

▸ Show child attributes
slugstring
namestring
agent_feesobject[]

The flat fees of paid agents in this task. Present only when the task has one.

▸ Show child attributes
session_idstringrequired
handlestringrequired
feeobjectrequired
▸ Show child attributes
amountstringrequired

Whole US cents

currencyenum<string>required

"USD"

statusenum<string>required

`held`: set aside from the caller's credit when the task started. `captured`: taken, on the task's first result. `released`: given back because the task was archived or deleted without a result. `disputed`, `refunded`: see the dispute route. — "awaiting_confirmation" · "declined" · "held" · "captured" · "disputed" · "released" · "refunded"

dispute_untilstring | nullrequired

Until when the caller may say the task was not completed; null unless the fee is captured and undisputed

disputeobject | nullrequired

What the caller said and how it was ruled; null when the fee was never disputed.

requestsobject[]required

Open requests addressed to the caller, oldest first. Answer one by sending its reply to `session_id` as a message, exactly as a question is answered in that session.

▸ Show child attributes
idstringrequired

The request id the agent or the platform assigned

session_idstringrequired

The session that is waiting (sess_…)

message_idstringrequired
kindenum<string>required

`question`: an agent asked. `approval`: a tool needs the caller's go-ahead before it runs (options `allow`, `deny`), or a workspace rule asks for it before the task itself starts (options `confirm`, `decline`; nothing has run, and declining archives the task). `connect_app`: the agent needs an app that is not connected; it resolves by itself when the caller connects the app, or by answering `skip`. `connect_account`: the task cannot run without the caller's own account at a vendor, or that account has no usage left; what the caller sent is kept and nothing has run. It resolves by itself when the account is connected (`POST /external_accounts`), or by answering `use_wallet` (offered only when the account is exhausted or expired and the task can run on a platform model) or `wait`. `spend`: an agent whose maker asks a flat fee is about to be used for the first time at that price, either as this task's own agent (nothing has run, and nothing runs until it is answered) or as a helper an agent in the task wants to hire. Answer `confirm` or `decline`; a confirmation is remembered for that agent at that price. — "question" · "approval" · "connect_app" · "connect_account" · "spend"

subjectstring | nullrequired

For `connect_app`, the app's slug; for `connect_account`, the vendor; for `spend`, the agent's handle

questionstringrequired
optionsobject[]required
▸ Show child attributes
idstringrequired
labelstringrequired
descriptionstring
allow_free_textbooleanrequired
required_user_idstring | nullrequired

Set when only one person may answer

due_atstring | nullrequired
created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/tasks/sess_cmtb7q2j/seen \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"session_ids":["sess_cmtb7q2j"]}'

Say whether the task did the job

The caller's own answer for a task that has a result. Each person has one answer per task; sending it again replaces the earlier one. It counts toward `stats.completed_yes` or `stats.completed_no` of the catalog listing the task's agent stands for. 409 `no_result` while no session of the task has replied. 404 for a task the caller cannot see. Answers 503 `not_migrated` until the platform's answer table is in place.

Path parameters

idstringrequired

The task id: the id of its root session (sess_…)

Body · application/json

did_the_jobbooleanrequired

Response · 200

taskobjectrequired
▸ Show child attributes
idstringrequired

sess_… — the root session's id

titlestring | nullrequired
attentionenum<string>required

What the caller should do about the task. `needs_you`: a request addressed to the caller is open. `working`: a session in the task is running or starting, or the task is waiting on somebody else. `done`: a result arrived since the caller last marked the task seen. `idle`: nothing new. — "needs_you" · "working" · "done" · "idle"

status_linestring | nullrequired

One line, at most 140 characters, on where it stands: the oldest question waiting on the caller, else the start of the latest thing an agent said. Null when no agent has said anything.

open_request_countintegerrequired

Open requests addressed to the caller

session_countintegerrequired

The root session plus its helper and handoff sessions

sessionsobject[]required

The root first, then the others in the order they joined

▸ Show child attributes
idstringrequired

sess_…

roleenum<string>required

"primary" · "helper" · "handoff"

attentionenum<string>required

What the caller should do about the task. `needs_you`: a request addressed to the caller is open. `working`: a session in the task is running or starting, or the task is waiting on somebody else. `done`: a result arrived since the caller last marked the task seen. `idle`: nothing new. — "needs_you" · "working" · "done" · "idle"

status_linestring | nullrequired

One line, at most 140 characters, on where it stands: the oldest question waiting on the caller, else the start of the latest thing an agent said. Null when no agent has said anything.

titlestring | nullrequired
statusenum<string>required

"provisioning" · "idle" · "running" · "terminated"

agent_idstring | nullrequired
agent_typestringrequired
llmstringrequired
consumed_costobjectrequired
▸ Show child attributes
amountstringrequired

Integer US cents, as a string

currencyenum<string>required

"USD"

model_paid_byobject

Who pays for the model in this session: the wallet, or the caller's own account at a vendor. Runtime is charged to the wallet either way. Present where external accounts are turned on.

▸ Show child attributes
sourceenum<string>required

"wallet" · "account"

vendorstring
namestring
created_atstringrequired
agent_idstring | nullrequired

The root session's agent (agent_…)

agent_typestringrequired
llmstringrequired
archivedbooleanrequired
last_activity_atstringrequired
created_atstringrequired
consumed_costobjectrequired

Billed cost summed over every session in the task, a paid agent's flat fee included

▸ Show child attributes
amountstringrequired

Integer US cents, as a string

currencyenum<string>required

"USD"

completion_answerobject | nullrequired

What the caller said about whether this task did the job; null until they answer. Other people's answers are not shown.

payerobject

Who pays for it, decided once when it was created and never changed. Present only when a payer was recorded, which happens in a team workspace where workspace wallets are on; absent means its owner's own balance pays.

▸ Show child attributes
typeenum<string>required

`workspace`: the team workspace's own wallet. `personal`: the balance of the person who started it. — "workspace" · "personal"

workspaceobject

The paying workspace; only with type workspace

▸ Show child attributes
slugstring
namestring
agent_feesobject[]

The flat fees of paid agents in this task. Present only when the task has one.

▸ Show child attributes
session_idstringrequired
handlestringrequired
feeobjectrequired
▸ Show child attributes
amountstringrequired

Whole US cents

currencyenum<string>required

"USD"

statusenum<string>required

`held`: set aside from the caller's credit when the task started. `captured`: taken, on the task's first result. `released`: given back because the task was archived or deleted without a result. `disputed`, `refunded`: see the dispute route. — "awaiting_confirmation" · "declined" · "held" · "captured" · "disputed" · "released" · "refunded"

dispute_untilstring | nullrequired

Until when the caller may say the task was not completed; null unless the fee is captured and undisputed

disputeobject | nullrequired

What the caller said and how it was ruled; null when the fee was never disputed.

requestsobject[]required

Open requests addressed to the caller, oldest first. Answer one by sending its reply to `session_id` as a message, exactly as a question is answered in that session.

▸ Show child attributes
idstringrequired

The request id the agent or the platform assigned

session_idstringrequired

The session that is waiting (sess_…)

message_idstringrequired
kindenum<string>required

`question`: an agent asked. `approval`: a tool needs the caller's go-ahead before it runs (options `allow`, `deny`), or a workspace rule asks for it before the task itself starts (options `confirm`, `decline`; nothing has run, and declining archives the task). `connect_app`: the agent needs an app that is not connected; it resolves by itself when the caller connects the app, or by answering `skip`. `connect_account`: the task cannot run without the caller's own account at a vendor, or that account has no usage left; what the caller sent is kept and nothing has run. It resolves by itself when the account is connected (`POST /external_accounts`), or by answering `use_wallet` (offered only when the account is exhausted or expired and the task can run on a platform model) or `wait`. `spend`: an agent whose maker asks a flat fee is about to be used for the first time at that price, either as this task's own agent (nothing has run, and nothing runs until it is answered) or as a helper an agent in the task wants to hire. Answer `confirm` or `decline`; a confirmation is remembered for that agent at that price. — "question" · "approval" · "connect_app" · "connect_account" · "spend"

subjectstring | nullrequired

For `connect_app`, the app's slug; for `connect_account`, the vendor; for `spend`, the agent's handle

questionstringrequired
optionsobject[]required
▸ Show child attributes
idstringrequired
labelstringrequired
descriptionstring
allow_free_textbooleanrequired
required_user_idstring | nullrequired

Set when only one person may answer

due_atstring | nullrequired
created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PUT https://api.agentsky.dev/v1/tasks/sess_cmtb7q2j/completion_answer \
  -H "Authorization: Bearer ast_..."

Answer a request the task is waiting on

Sends the caller's answer to the session that asked, as its next turn, in the same form a click in the app produces. Pass `option_id` for one of the request's options, or `text` where the request accepts free text. A `spend` request is applied before anything is sent: confirming remembers the price and, when the task itself was waiting to start, holds the fee and starts it with what it was given (402 `insufficient_credits` when the caller's credit does not cover the fee; the request stays open). Declining such a start closes the request and the task never runs. A `spend` request that asks to raise a member's monthly limit in a workspace is answered by an owner or admin of that workspace with `option_id` `raise` or `decline` (403 `request_not_yours` for anyone else, the member included): raising sets the limit the request offered and sends on what the member's waiting tasks were given. An optional `note` is sent to the agent after the answer, in the same turn, and is not part of the answer: a surface other than the app uses it to say where the answer came from and how to reply there. 404 when the task has no open request with that id, 403 `request_not_yours` when it is addressed to someone else, 400 when the answer is not one the request accepts, 409 `session_busy` while the turn that asked is still running (retry once the session is idle).

Path parameters

idstringrequired

The task id: the id of its root session (sess_…)

request_idstringrequired

The request's `id` from the task's `requests`

Body · application/json

option 1object
▸ Show child attributes
option_idstringrequired
notestring

max length 4000

option 2object
▸ Show child attributes
textstringrequired

max length 20000

notestring

max length 4000

Response · 200

session_idstringrequired

The session that asked

message_idstring | nullrequired

The answer's message; read the session's events from it to follow the turn. Null when a `spend` request was declined, or confirmed for a task that was given nothing to start with.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/tasks/sess_cmtb7q2j/requests/ask-7f3c2a/answer \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"option_id":"approve"}'

Say a paid agent did not complete the task

For the person who hired, within 72 hours of the task's first result. The fee and the seller's earning then wait for a reviewer, who either refunds the fee to the caller's credit or lets the charge stand. Usage is not refunded. 404 when the task has no agent fee of the caller's, 409 `not_disputable` outside the 72 hours or once it has been disputed, 400 when the task holds more than one fee and `session_id` does not name one.

Path parameters

idstringrequired

The task id: the id of its root session (sess_…)

Body · application/json

reasonstringrequired

max length 1000

session_idstring

Response · 200

taskobjectrequired
▸ Show child attributes
idstringrequired

sess_… — the root session's id

titlestring | nullrequired
attentionenum<string>required

What the caller should do about the task. `needs_you`: a request addressed to the caller is open. `working`: a session in the task is running or starting, or the task is waiting on somebody else. `done`: a result arrived since the caller last marked the task seen. `idle`: nothing new. — "needs_you" · "working" · "done" · "idle"

status_linestring | nullrequired

One line, at most 140 characters, on where it stands: the oldest question waiting on the caller, else the start of the latest thing an agent said. Null when no agent has said anything.

open_request_countintegerrequired

Open requests addressed to the caller

session_countintegerrequired

The root session plus its helper and handoff sessions

sessionsobject[]required

The root first, then the others in the order they joined

▸ Show child attributes
idstringrequired

sess_…

roleenum<string>required

"primary" · "helper" · "handoff"

attentionenum<string>required

What the caller should do about the task. `needs_you`: a request addressed to the caller is open. `working`: a session in the task is running or starting, or the task is waiting on somebody else. `done`: a result arrived since the caller last marked the task seen. `idle`: nothing new. — "needs_you" · "working" · "done" · "idle"

status_linestring | nullrequired

One line, at most 140 characters, on where it stands: the oldest question waiting on the caller, else the start of the latest thing an agent said. Null when no agent has said anything.

titlestring | nullrequired
statusenum<string>required

"provisioning" · "idle" · "running" · "terminated"

agent_idstring | nullrequired
agent_typestringrequired
llmstringrequired
consumed_costobjectrequired
▸ Show child attributes
amountstringrequired

Integer US cents, as a string

currencyenum<string>required

"USD"

model_paid_byobject

Who pays for the model in this session: the wallet, or the caller's own account at a vendor. Runtime is charged to the wallet either way. Present where external accounts are turned on.

▸ Show child attributes
sourceenum<string>required

"wallet" · "account"

vendorstring
namestring
created_atstringrequired
agent_idstring | nullrequired

The root session's agent (agent_…)

agent_typestringrequired
llmstringrequired
archivedbooleanrequired
last_activity_atstringrequired
created_atstringrequired
consumed_costobjectrequired

Billed cost summed over every session in the task, a paid agent's flat fee included

▸ Show child attributes
amountstringrequired

Integer US cents, as a string

currencyenum<string>required

"USD"

completion_answerobject | nullrequired

What the caller said about whether this task did the job; null until they answer. Other people's answers are not shown.

payerobject

Who pays for it, decided once when it was created and never changed. Present only when a payer was recorded, which happens in a team workspace where workspace wallets are on; absent means its owner's own balance pays.

▸ Show child attributes
typeenum<string>required

`workspace`: the team workspace's own wallet. `personal`: the balance of the person who started it. — "workspace" · "personal"

workspaceobject

The paying workspace; only with type workspace

▸ Show child attributes
slugstring
namestring
agent_feesobject[]

The flat fees of paid agents in this task. Present only when the task has one.

▸ Show child attributes
session_idstringrequired
handlestringrequired
feeobjectrequired
▸ Show child attributes
amountstringrequired

Whole US cents

currencyenum<string>required

"USD"

statusenum<string>required

`held`: set aside from the caller's credit when the task started. `captured`: taken, on the task's first result. `released`: given back because the task was archived or deleted without a result. `disputed`, `refunded`: see the dispute route. — "awaiting_confirmation" · "declined" · "held" · "captured" · "disputed" · "released" · "refunded"

dispute_untilstring | nullrequired

Until when the caller may say the task was not completed; null unless the fee is captured and undisputed

disputeobject | nullrequired

What the caller said and how it was ruled; null when the fee was never disputed.

requestsobject[]required

Open requests addressed to the caller, oldest first. Answer one by sending its reply to `session_id` as a message, exactly as a question is answered in that session.

▸ Show child attributes
idstringrequired

The request id the agent or the platform assigned

session_idstringrequired

The session that is waiting (sess_…)

message_idstringrequired
kindenum<string>required

`question`: an agent asked. `approval`: a tool needs the caller's go-ahead before it runs (options `allow`, `deny`), or a workspace rule asks for it before the task itself starts (options `confirm`, `decline`; nothing has run, and declining archives the task). `connect_app`: the agent needs an app that is not connected; it resolves by itself when the caller connects the app, or by answering `skip`. `connect_account`: the task cannot run without the caller's own account at a vendor, or that account has no usage left; what the caller sent is kept and nothing has run. It resolves by itself when the account is connected (`POST /external_accounts`), or by answering `use_wallet` (offered only when the account is exhausted or expired and the task can run on a platform model) or `wait`. `spend`: an agent whose maker asks a flat fee is about to be used for the first time at that price, either as this task's own agent (nothing has run, and nothing runs until it is answered) or as a helper an agent in the task wants to hire. Answer `confirm` or `decline`; a confirmation is remembered for that agent at that price. — "question" · "approval" · "connect_app" · "connect_account" · "spend"

subjectstring | nullrequired

For `connect_app`, the app's slug; for `connect_account`, the vendor; for `spend`, the agent's handle

questionstringrequired
optionsobject[]required
▸ Show child attributes
idstringrequired
labelstringrequired
descriptionstring
allow_free_textbooleanrequired
required_user_idstring | nullrequired

Set when only one person may answer

due_atstring | nullrequired
created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/tasks/sess_cmtb7q2j/agent-fee/dispute \
  -H "Authorization: Bearer ast_..."

List the files in the task's file space

The folder every session of the task has at `/workspace/task/`: a handoff session and a helper see the same files as the session that wrote them. Current files only, by path. Answers 503 `not_migrated` until the platform's task file tables are in place.

Path parameters

idstringrequired

The task id: the id of its root session (sess_…)

Response · 200

filesobject[]required
▸ Show child attributes
pathstringrequired
size_bytesintegerrequired
sha256stringrequired
updated_atstringrequired
updated_by_sessionstring | nullrequired

The session that last wrote it; null when a person or developer did

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/tasks/sess_cmtb7q2j/files' \
  -H "Authorization: Bearer ast_..."

Download the task's files as one archive

A zip archive of the current files in the task's file space, each at its own path. 413 `export_too_large` when they are more than 64 MiB together; download them one at a time then.

Path parameters

idstringrequired

The task id: the id of its root session (sess_…)

Response · 200

The archive

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/tasks/sess_cmtb7q2j/export' \
  -H "Authorization: Bearer ast_..."

Read one task file, or its history

Returns the file's bytes. With `versions=true` returns instead every recorded write of that path, newest first, including writes to a path that has since been deleted.

Path parameters

idstringrequired

The task id: the id of its root session (sess_…)

pathstringrequired

The file's path inside the task's file space, such as report.md or data/rows.csv

Query parameters

versionsstring

Response · 200

The bytes, or the version list

versionsobject[]required
▸ Show child attributes
idstringrequired
sha256stringrequired
size_bytesintegerrequired
sessionstring | nullrequired
conflictbooleanrequired

The writer had not seen what was current when it wrote

created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/tasks/sess_cmtb7q2j/files/report.md' \
  -H "Authorization: Bearer ast_..."

Write one task file

The body is the file's bytes (16 MiB at most; 413 `file_too_large`). The write becomes the current file. `base_sha256` names what the caller last saw at the path (empty for nothing); when something else is current the write is still made, both versions are kept, and the response says `conflict: true`. A task holds at most 2000 files and 256 MiB (413 `task_files_full`). Sessions of the task pick the file up at the start of their next turn.

Path parameters

idstringrequired

The task id: the id of its root session (sess_…)

pathstringrequired

The file's path inside the task's file space, such as report.md or data/rows.csv

Query parameters

base_sha256string

Response · 200

fileobjectrequired
▸ Show child attributes
pathstringrequired
size_bytesintegerrequired
sha256stringrequired
updated_atstringrequired
updated_by_sessionstring | nullrequired

The session that last wrote it; null when a person or developer did

conflictbooleanrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PUT https://api.agentsky.dev/v1/tasks/sess_cmtb7q2j/files/report.md \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: text/markdown" \
  --data-binary @report.md

Remove one task file

Removes the path from the current files. Its history stays readable with `versions=true`.

Path parameters

idstringrequired

The task id: the id of its root session (sess_…)

pathstringrequired

The file's path inside the task's file space, such as report.md or data/rows.csv

Response · 200

okbooleanrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/tasks/sess_cmtb7q2j/files/report.md \
  -H "Authorization: Bearer ast_..."

Report on a task from the server its agent runs on

Authorized by the pass handed to that server with the turn, sent as `Authorization: Bearer`, and by nothing else: any other credential is refused with 403. `message` shows progress and keeps the turn open. `result` is the answer; `request` asks the person a question, which they answer like any other request on the task; `error` says the work could not be done. Those three end the turn and the pass, so write the task's files first. 409 `turn_ended` once the turn is over; 401 for a pass that has ended.

Path parameters

idstringrequired

The task's id.

Body · application/json

type: "message"object

Something to show while the work goes on. The turn stays open.

▸ Show child attributes
type"message"required
textstringrequired

max length 200000

type: "result"object

The answer. Ends the turn and the pass.

▸ Show child attributes
type"result"required
textstringrequired

max length 200000

type: "request"object

A question for the person. Ends the turn and the pass; the answer arrives as the task's next turn, with a new pass.

▸ Show child attributes
type"request"required
questionstringrequired

max length 2000

optionsobject[]
▸ Show child attributes
idstringrequired

max length 200

labelstringrequired

max length 200

descriptionstring

max length 500

allow_free_textboolean

Whether the person may type an answer. Defaults to true; must be true when there are no options.

type: "error"object

The work could not be done. Ends the turn and the pass; the person reads the message.

▸ Show child attributes
type"error"required
messagestringrequired

max length 500

Response · 200

Recorded

okbooleanrequired
request_idstring

The id of the request that was raised, for `request`.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/tasks/sess_cmtb7q2j/callback \
  -H "Authorization: Bearer ast_..."

Notifications

Which task events the caller is emailed and pushed about

A person who has never chosen gets the defaults: for email `needs_you` on and `done` off, for push both on. Every task email also carries a link that turns its kind off without signing in.

Response · 200

notification_preferencesobjectrequired

The caller's own choices. They follow the person across workspaces.

▸ Show child attributes
pushobjectrequired

Which kinds reach the browsers the caller subscribed (`/push-subscriptions`). Both on unless turned off; without a subscribed browser nothing is pushed.

▸ Show child attributes
needs_youbooleanrequired

Notify my browsers when one of my tasks starts waiting on me.

donebooleanrequired

Notify my browsers when one of my tasks produces a result while I am away.

emailobjectrequired
▸ Show child attributes
needs_youbooleanrequired

Email me when one of my tasks starts waiting on me and I have not looked at it. On unless turned off.

donebooleanrequired

Email me when one of my tasks produces a result while I am away. Off unless turned on.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/notification-preferences' \
  -H "Authorization: Bearer ast_..."

Change which task events the caller is emailed and pushed about

Send `email`, `push` or both, each with only the kinds to change; the response holds all of them. Answers 503 `not_available` until the platform's notification tables are in place.

Body · application/json

emailobject
▸ Show child attributes
needs_youboolean
doneboolean
pushobject
▸ Show child attributes
needs_youboolean
doneboolean

Response · 200

notification_preferencesobjectrequired

The caller's own choices. They follow the person across workspaces.

▸ Show child attributes
pushobjectrequired

Which kinds reach the browsers the caller subscribed (`/push-subscriptions`). Both on unless turned off; without a subscribed browser nothing is pushed.

▸ Show child attributes
needs_youbooleanrequired

Notify my browsers when one of my tasks starts waiting on me.

donebooleanrequired

Notify my browsers when one of my tasks produces a result while I am away.

emailobjectrequired
▸ Show child attributes
needs_youbooleanrequired

Email me when one of my tasks starts waiting on me and I have not looked at it. On unless turned off.

donebooleanrequired

Email me when one of my tasks produces a result while I am away. Off unless turned on.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PATCH https://api.agentsky.dev/v1/notification-preferences \
  -H "Authorization: Bearer ast_..."

The browsers the caller is notified in

A subscribed browser gets a push notification when one of the caller's tasks starts waiting on them or has a result, under the same rules as task emails, for the kinds left on under `push` in `/notification-preferences`. `application_server_key` is the key a browser subscribes with; it is null, and the list empty, where push is not turned on.

Response · 200

application_server_keystringrequired
dataobject[]required
▸ Show child attributes
idstringrequired
kindenum<string>required

"web"

endpointstringrequired

The push service's address for that browser.

created_atstringrequired
last_seen_atstringrequired

When that browser last subscribed.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/push-subscriptions' \
  -H "Authorization: Bearer ast_..."

Subscribe a browser to push notifications

Send what the browser's `pushManager.subscribe()` returned. Subscribing the same browser again keeps one subscription. Answers 403 `not_enabled` where push is not turned on, 400 for an endpoint that is not a browser push service's, and 503 `not_migrated` until the platform's push tables are in place.

Body · application/json

endpointstringrequired
keysobjectrequired
▸ Show child attributes
p256dhstringrequired
authstringrequired

Response · 201

subscriptionobjectrequired

One browser the caller asked to be notified in. Its keys are never returned.

▸ Show child attributes
idstringrequired
kindenum<string>required

"web"

endpointstringrequired

The push service's address for that browser.

created_atstringrequired
last_seen_atstringrequired

When that browser last subscribed.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/push-subscriptions \
  -H "Authorization: Bearer ast_..."

Stop notifying one of the caller's browsers

Path parameters

idstringrequired

Response · 204

Removed

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/push-subscriptions/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."

Agent catalog

Read operational harness availability

The delisted engine identities, read without an HTTP cache. New acquisition rejects them; existing sessions are retained.

Response · 200

Current delisting state

delistedstring[]required

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/catalog/engines' \
  -H "Authorization: Bearer ast_..."

List hireable agents

Every listed agent: platform engines, and other people's agents that were reviewed and approved, each served as it was approved and carrying `seller`. Needs no credentials; a caller that sends them also gets its own workspace's listings. Answers 503 `not_migrated` until the platform's catalog tables are in place.

Query parameters

categorystring
qstring

Matches handle, name, tagline and description

sortstring
requiresstring

Keep the agents whose stated requirements match: `account` needs the caller's own account at a vendor, `no_account` needs none, `mcp_servers` can use MCP servers. An account requirement is stated only where external accounts are turned on.

Response · 200

agentsobject[]required
▸ Show child attributes
handlestringrequired

Globally unique and stable: lower-case letters, digits and underscores. What a person types after "/".

kindenum<string>required

A platform engine, or an agent a person listed — "engine" · "agent"

engine_typestring | nullrequired

The agent type to create an agent with, for an engine listing

agent_idstring | nullrequired

The agent one of the caller's own workspace listings stands for; null for an engine and for another person's agent

visibilityenum<string>required

public for everyone: an engine, or another person's agent that was reviewed and approved. workspace for the caller's own listing, whether or not it is also public. — "public" · "workspace"

sellerobject | nullrequired

Who made a public agent that is not a platform engine, by the name they chose. Null for an engine and for the caller's own listing.

namestringrequired
taglinestringrequired

One line, at most 140 characters

descriptionstringrequired
doesstring[]required

What it does. Empty when not yet written; never guessed.

does_notstring[]required

What it does not do. Empty when not yet written.

categoriesenum<string>[]required

"websites" · "content" · "video" · "code" · "research" · "general"

examplesstring[]required

Example tasks

requirementsobjectrequired

What the agent needs, stated rather than hidden. `mcp_servers` says whether it can use MCP servers; `website` is the engine's own site. `hosted_by_seller: { host }` is present when the agent runs on its maker's own server instead of a sandbox: what a person sends it, and the files of the task, go to that host, and a person's first task with it waits for them to agree (a task request).

pricingobjectrequired

`{ mode: "usage" }`: the model and tool usage the task incurs, with no agent fee. `{ mode: "per_task", fee: { amount, currency } }`: usage, plus a flat fee the agent's maker asks for each task; `amount` is whole US cents as a string. Starting such an agent asks the person to confirm the price the first time (a task request of kind `spend`), holds the fee on their credit when the task starts and takes it when the task gives its first result.

statsobjectrequired

Counts from real use, recounted hourly; never estimated. `uses`: sessions started on the agent. `comparisons` and `wins`: decided side-by-side comparisons the agent took part in, and the ones a person picked it in. `completed_yes` and `completed_no`: people who said a task on this agent did the job, and people who said it did not (`PUT /tasks/{id}/completion_answer`).

▸ Show child attributes
usesintegerrequired
comparisonsintegerrequired
winsintegerrequired
completed_yesintegerrequired
completed_nointegerrequired
usageobject | null

What one task typically consumes: medians over the agent's sessions of the last 30 days that metered model usage. Null until at least 10 such sessions exist.

conformanceobject | nullrequired

The verdicts of the listing's latest finished conformance run; for another person's agent, of the run it was submitted with. Null when it has never finished one.

created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/catalog/agents' \
  -H "Authorization: Bearer ast_..."

One agent by handle

Path parameters

handlestringrequired

The agent's handle; a leading @ is accepted

Response · 200

agentobjectrequired
▸ Show child attributes
handlestringrequired

Globally unique and stable: lower-case letters, digits and underscores. What a person types after "/".

kindenum<string>required

A platform engine, or an agent a person listed — "engine" · "agent"

engine_typestring | nullrequired

The agent type to create an agent with, for an engine listing

agent_idstring | nullrequired

The agent one of the caller's own workspace listings stands for; null for an engine and for another person's agent

visibilityenum<string>required

public for everyone: an engine, or another person's agent that was reviewed and approved. workspace for the caller's own listing, whether or not it is also public. — "public" · "workspace"

sellerobject | nullrequired

Who made a public agent that is not a platform engine, by the name they chose. Null for an engine and for the caller's own listing.

namestringrequired
taglinestringrequired

One line, at most 140 characters

descriptionstringrequired
doesstring[]required

What it does. Empty when not yet written; never guessed.

does_notstring[]required

What it does not do. Empty when not yet written.

categoriesenum<string>[]required

"websites" · "content" · "video" · "code" · "research" · "general"

examplesstring[]required

Example tasks

requirementsobjectrequired

What the agent needs, stated rather than hidden. `mcp_servers` says whether it can use MCP servers; `website` is the engine's own site. `hosted_by_seller: { host }` is present when the agent runs on its maker's own server instead of a sandbox: what a person sends it, and the files of the task, go to that host, and a person's first task with it waits for them to agree (a task request).

pricingobjectrequired

`{ mode: "usage" }`: the model and tool usage the task incurs, with no agent fee. `{ mode: "per_task", fee: { amount, currency } }`: usage, plus a flat fee the agent's maker asks for each task; `amount` is whole US cents as a string. Starting such an agent asks the person to confirm the price the first time (a task request of kind `spend`), holds the fee on their credit when the task starts and takes it when the task gives its first result.

statsobjectrequired

Counts from real use, recounted hourly; never estimated. `uses`: sessions started on the agent. `comparisons` and `wins`: decided side-by-side comparisons the agent took part in, and the ones a person picked it in. `completed_yes` and `completed_no`: people who said a task on this agent did the job, and people who said it did not (`PUT /tasks/{id}/completion_answer`).

▸ Show child attributes
usesintegerrequired
comparisonsintegerrequired
winsintegerrequired
completed_yesintegerrequired
completed_nointegerrequired
usageobject | null

What one task typically consumes: medians over the agent's sessions of the last 30 days that metered model usage. Null until at least 10 such sessions exist.

conformanceobject | nullrequired

The verdicts of the listing's latest finished conformance run; for another person's agent, of the run it was submitted with. Null when it has never finished one.

created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/catalog/agents/handle' \
  -H "Authorization: Bearer ast_..."

List one of your own agents under a handle

The listing is visible to your workspace only, and `agent: "@handle"` then starts a session with that agent. A handle is unique across the platform, engines included; a taken one is 409 `handle_taken`. Listing the same agent again replaces its listing and frees the old handle. A listing whose agent is archived or deleted stops being offered.

Body · application/json

agent_idstringrequired
handlestringrequired

2 to 40 lower-case letters, digits or underscores; a leading @ is accepted

taglinestringrequired

max length 140

descriptionstring

max length 4000

categoriesenum<string>[]

Defaults to general — "websites" · "content" · "video" · "code" · "research" · "general"

doesstring[]

max length 300

does_notstring[]

max length 300

examplesstring[]

max length 300

Response · 201

agentobjectrequired
▸ Show child attributes
handlestringrequired

Globally unique and stable: lower-case letters, digits and underscores. What a person types after "/".

kindenum<string>required

A platform engine, or an agent a person listed — "engine" · "agent"

engine_typestring | nullrequired

The agent type to create an agent with, for an engine listing

agent_idstring | nullrequired

The agent one of the caller's own workspace listings stands for; null for an engine and for another person's agent

visibilityenum<string>required

public for everyone: an engine, or another person's agent that was reviewed and approved. workspace for the caller's own listing, whether or not it is also public. — "public" · "workspace"

sellerobject | nullrequired

Who made a public agent that is not a platform engine, by the name they chose. Null for an engine and for the caller's own listing.

namestringrequired
taglinestringrequired

One line, at most 140 characters

descriptionstringrequired
doesstring[]required

What it does. Empty when not yet written; never guessed.

does_notstring[]required

What it does not do. Empty when not yet written.

categoriesenum<string>[]required

"websites" · "content" · "video" · "code" · "research" · "general"

examplesstring[]required

Example tasks

requirementsobjectrequired

What the agent needs, stated rather than hidden. `mcp_servers` says whether it can use MCP servers; `website` is the engine's own site. `hosted_by_seller: { host }` is present when the agent runs on its maker's own server instead of a sandbox: what a person sends it, and the files of the task, go to that host, and a person's first task with it waits for them to agree (a task request).

pricingobjectrequired

`{ mode: "usage" }`: the model and tool usage the task incurs, with no agent fee. `{ mode: "per_task", fee: { amount, currency } }`: usage, plus a flat fee the agent's maker asks for each task; `amount` is whole US cents as a string. Starting such an agent asks the person to confirm the price the first time (a task request of kind `spend`), holds the fee on their credit when the task starts and takes it when the task gives its first result.

statsobjectrequired

Counts from real use, recounted hourly; never estimated. `uses`: sessions started on the agent. `comparisons` and `wins`: decided side-by-side comparisons the agent took part in, and the ones a person picked it in. `completed_yes` and `completed_no`: people who said a task on this agent did the job, and people who said it did not (`PUT /tasks/{id}/completion_answer`).

▸ Show child attributes
usesintegerrequired
comparisonsintegerrequired
winsintegerrequired
completed_yesintegerrequired
completed_nointegerrequired
usageobject | null

What one task typically consumes: medians over the agent's sessions of the last 30 days that metered model usage. Null until at least 10 such sessions exist.

conformanceobject | nullrequired

The verdicts of the listing's latest finished conformance run; for another person's agent, of the run it was submitted with. Null when it has never finished one.

created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/catalog/listings \
  -H "Authorization: Bearer ast_..."

Take one of your own listings down

The agent itself is untouched. 404 for a handle that is not one of this workspace's listings.

Path parameters

handlestringrequired

The agent's handle; a leading @ is accepted

Response · 200

okbooleanrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/catalog/listings/handle \
  -H "Authorization: Bearer ast_..."

Start a conformance run of one of your own listings

Answers at once with the run as `running`; read it back with GET. The suite uses the listing the way a customer would, through this API and as you: it starts sessions in your workspace, which you pay for, and deletes them when it is done. 404 for a handle that is not one of this workspace's listings, an engine included. 409 `conformance_running` while a run of that listing is still going.

Path parameters

handlestringrequired

The agent's handle; a leading @ is accepted

Response · 202

runobjectrequired
▸ Show child attributes
idstringrequired
handlestringrequired
statusenum<string>required

A run still going after 30 minutes is reported as failed. — "running" · "finished" · "failed"

started_atstringrequired
finished_atstring | nullrequired
reasonstring | nullrequired

Why the run could not finish; null unless it failed

required_passedbooleanrequired

No required check failed and at least one ran. False until the run finished.

all_passedbooleanrequired

Every check ran and passed. False until the run finished.

reportobject | nullrequired

Every check with its outcome; null until the run finished.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/catalog/listings/handle/conformance \
  -H "Authorization: Bearer ast_..."

The latest conformance run of one of your own listings

`run` is null when the listing has never been run. 404 for a handle that is not one of this workspace's listings.

Path parameters

handlestringrequired

The agent's handle; a leading @ is accepted

Response · 200

runobject | nullrequired
▸ Show child attributes
idstringrequired
handlestringrequired
statusenum<string>required

A run still going after 30 minutes is reported as failed. — "running" · "finished" · "failed"

started_atstringrequired
finished_atstring | nullrequired
reasonstring | nullrequired

Why the run could not finish; null unless it failed

required_passedbooleanrequired

No required check failed and at least one ran. False until the run finished.

all_passedbooleanrequired

Every check ran and passed. False until the run finished.

reportobject | nullrequired

Every check with its outcome; null until the run finished.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/catalog/listings/handle/conformance' \
  -H "Authorization: Bearer ast_..."

Where one of your own listings stands with the public Market

Whether it can be submitted and what is missing, its latest submission, and the approved version being served. 404 for a handle that is not one of this workspace's listings.

Path parameters

handlestringrequired

The agent's handle; a leading @ is accepted

Response · 200

openbooleanrequired

Whether this workspace may submit listings to the public Market

missingstring[]required

What still has to be true before the listing can be submitted, in words. Empty when it can be.

pricingobject

Present only where this workspace may set a flat fee on its public listings.

▸ Show child attributes
seller_share_percentnumberrequired

The part of each fee the seller keeps

fee_cents_minintegerrequired
fee_cents_maxintegerrequired
submissionobject | nullrequired

The latest submission; null when the listing has never been submitted.

publishedobject | nullrequired

The approved version being served to everyone; null when the listing is not public.

taken_downobject | nullrequired

Set when a reviewer took the public listing down and it has not been submitted again.

scheduled_checkobject

What the scheduled checks of the approved version found. A public listing's approved version is checked when it is approved and then by the weekly conformance sweep, as its seller and on the seller's credit for usage, under a spend cap. Absent when the listing is not public.

▸ Show child attributes
passingboolean | nullrequired

Whether the required checks passed at the last scheduled run that finished; null before the first. False takes the listing's `conformance.required_passed` away for everyone; the listing stays public.

reasonstring | nullrequired

The required checks that failed, or why the latest run was skipped or could not finish

checked_atstring | nullrequired
runningbooleanrequired

Whether a scheduled run of this version is going now

next_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/catalog/listings/handle/submission' \
  -H "Authorization: Bearer ast_..."

Submit one of your own listings for the public Market

Stores the listing and its agent as they are now and puts them in front of a reviewer. Once approved, everyone sees the listing and can start it with `agent: "@handle"`; their session runs a hidden copy of the approved agent in their own workspace, on their own wallet. Later edits are not served until a new submission is approved. `fee` asks a flat fee for each task on top of usage; like everything else it takes effect, and changes, only when a submission carrying it is approved, and a submission without it makes the listing usage-only again. 403 `submissions_closed` when this workspace may not submit. 403 `pricing_closed` when `fee` is sent and this workspace may not set a price. 422 `not_submittable` when something is missing: the message names every item. 409 `already_in_review` while an earlier submission is waiting.

Path parameters

handlestringrequired

The agent's handle; a leading @ is accepted

Body · application/json

seller_namestringrequired

The name the Market shows as the maker. Not an email address. — max length 60

feeobject

The flat fee for each task, in whole US cents: 1 to 100000

▸ Show child attributes
amountstringrequired

Whole US cents — pattern ^[1-9][0-9]*$

currencyenum<string>required

"USD"

Response · 201

Submitted

openbooleanrequired

Whether this workspace may submit listings to the public Market

missingstring[]required

What still has to be true before the listing can be submitted, in words. Empty when it can be.

pricingobject

Present only where this workspace may set a flat fee on its public listings.

▸ Show child attributes
seller_share_percentnumberrequired

The part of each fee the seller keeps

fee_cents_minintegerrequired
fee_cents_maxintegerrequired
submissionobject | nullrequired

The latest submission; null when the listing has never been submitted.

publishedobject | nullrequired

The approved version being served to everyone; null when the listing is not public.

taken_downobject | nullrequired

Set when a reviewer took the public listing down and it has not been submitted again.

scheduled_checkobject

What the scheduled checks of the approved version found. A public listing's approved version is checked when it is approved and then by the weekly conformance sweep, as its seller and on the seller's credit for usage, under a spend cap. Absent when the listing is not public.

▸ Show child attributes
passingboolean | nullrequired

Whether the required checks passed at the last scheduled run that finished; null before the first. False takes the listing's `conformance.required_passed` away for everyone; the listing stays public.

reasonstring | nullrequired

The required checks that failed, or why the latest run was skipped or could not finish

checked_atstring | nullrequired
runningbooleanrequired

Whether a scheduled run of this version is going now

next_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/catalog/listings/handle/submission \
  -H "Authorization: Bearer ast_..."

Withdraw a submission that is waiting for review

404 when nothing of this listing is waiting.

Path parameters

handlestringrequired

The agent's handle; a leading @ is accepted

Response · 200

openbooleanrequired

Whether this workspace may submit listings to the public Market

missingstring[]required

What still has to be true before the listing can be submitted, in words. Empty when it can be.

pricingobject

Present only where this workspace may set a flat fee on its public listings.

▸ Show child attributes
seller_share_percentnumberrequired

The part of each fee the seller keeps

fee_cents_minintegerrequired
fee_cents_maxintegerrequired
submissionobject | nullrequired

The latest submission; null when the listing has never been submitted.

publishedobject | nullrequired

The approved version being served to everyone; null when the listing is not public.

taken_downobject | nullrequired

Set when a reviewer took the public listing down and it has not been submitted again.

scheduled_checkobject

What the scheduled checks of the approved version found. A public listing's approved version is checked when it is approved and then by the weekly conformance sweep, as its seller and on the seller's credit for usage, under a spend cap. Absent when the listing is not public.

▸ Show child attributes
passingboolean | nullrequired

Whether the required checks passed at the last scheduled run that finished; null before the first. False takes the listing's `conformance.required_passed` away for everyone; the listing stays public.

reasonstring | nullrequired

The required checks that failed, or why the latest run was skipped or could not finish

checked_atstring | nullrequired
runningbooleanrequired

Whether a scheduled run of this version is going now

next_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/catalog/listings/handle/submission \
  -H "Authorization: Bearer ast_..."

Stop serving one of your own listings to everyone else

The workspace listing and the agent stay. Sessions other people already started keep running. 404 when the listing is not public.

Path parameters

handlestringrequired

The agent's handle; a leading @ is accepted

Response · 200

openbooleanrequired

Whether this workspace may submit listings to the public Market

missingstring[]required

What still has to be true before the listing can be submitted, in words. Empty when it can be.

pricingobject

Present only where this workspace may set a flat fee on its public listings.

▸ Show child attributes
seller_share_percentnumberrequired

The part of each fee the seller keeps

fee_cents_minintegerrequired
fee_cents_maxintegerrequired
submissionobject | nullrequired

The latest submission; null when the listing has never been submitted.

publishedobject | nullrequired

The approved version being served to everyone; null when the listing is not public.

taken_downobject | nullrequired

Set when a reviewer took the public listing down and it has not been submitted again.

scheduled_checkobject

What the scheduled checks of the approved version found. A public listing's approved version is checked when it is approved and then by the weekly conformance sweep, as its seller and on the seller's credit for usage, under a spend cap. Absent when the listing is not public.

▸ Show child attributes
passingboolean | nullrequired

Whether the required checks passed at the last scheduled run that finished; null before the first. False takes the listing's `conformance.required_passed` away for everyone; the listing stays public.

reasonstring | nullrequired

The required checks that failed, or why the latest run was skipped or could not finish

checked_atstring | nullrequired
runningbooleanrequired

Whether a scheduled run of this version is going now

next_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/catalog/listings/handle/publication \
  -H "Authorization: Bearer ast_..."

What you have earned from the fees on your public listings

Totals, a line per listing, a line per captured fee (newest first) and the payouts they went into. The seller keeps the share shown on each line; the rest is the platform's. A `referral` line is the caller's share of a fee another seller's agent was paid by a person the caller brought; it counts in `earned`, `paid` and `unpaid`, not in `gross` or `listings`. A fee is payable once the 72 hours its buyer has to dispute it have passed, and payouts are made once a month. Nothing here identifies a buyer. 404 where flat fees are not offered.

Response · 200

totalsobjectrequired
▸ Show child attributes
grossobjectrequired
▸ Show child attributes
amountstringrequired

Whole US cents; negative on a reversal

currencyenum<string>required

"USD"

earnedobjectrequired
▸ Show child attributes
amountstringrequired

Whole US cents; negative on a reversal

currencyenum<string>required

"USD"

paidobjectrequired
▸ Show child attributes
amountstringrequired

Whole US cents; negative on a reversal

currencyenum<string>required

"USD"

unpaidobjectrequired
▸ Show child attributes
amountstringrequired

Whole US cents; negative on a reversal

currencyenum<string>required

"USD"

listingsobject[]required
▸ Show child attributes
handlestringrequired
tasksintegerrequired
grossobjectrequired
▸ Show child attributes
amountstringrequired

Whole US cents; negative on a reversal

currencyenum<string>required

"USD"

earnedobjectrequired
▸ Show child attributes
amountstringrequired

Whole US cents; negative on a reversal

currencyenum<string>required

"USD"

linesobject[]required
▸ Show child attributes
idstringrequired
handlestringrequired
kindenum<string>required

`reversal`: a fee refunded after it had been paid out, taken off the next payout. `referral`: the caller's share of a fee another seller's agent was paid by a person the caller referred (`POST /seller/referrals`); its `fee` is that fee — "earning" · "reversal" · "referral"

sourceenum<string>required

Who brought the buyer; `referral` on a referral line — "shelf" · "seller_referred" · "helper" · "referral"

feeobjectrequired
▸ Show child attributes
amountstringrequired

Whole US cents; negative on a reversal

currencyenum<string>required

"USD"

share_percentnumberrequired
earnedobjectrequired
▸ Show child attributes
amountstringrequired

Whole US cents; negative on a reversal

currencyenum<string>required

"USD"

statusenum<string>required

"waiting" · "disputed" · "refunded" · "payable" · "in_payout" · "paid"

payable_atstringrequired
created_atstringrequired
payoutsobject[]required
▸ Show child attributes
idstringrequired
period_startstringrequired
period_endstringrequired
amountobjectrequired
▸ Show child attributes
amountstringrequired

Whole US cents; negative on a reversal

currencyenum<string>required

"USD"

statusenum<string>required

"owed" · "paid"

paid_atstring | nullrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/seller/earnings' \
  -H "Authorization: Bearer ast_..."

Your seller account status

Returns the Stripe Connect account status for the caller. 404 when the caller has no seller account record or the payout tables are not yet migrated.

Response · 200

account_statusenum<string>required

"pending" · "active" · "restricted"

payout_connectedbooleanrequired

True when the Stripe Connect account is active and transfers can be sent

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/seller/account' \
  -H "Authorization: Bearer ast_..."

Create your seller account record

Creates or upserts the caller's seller account record. Idempotent — calling it again when a record already exists is a no-op. 404 when the payout tables are not yet migrated.

Response · 201

oktruerequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/seller/account \
  -H "Authorization: Bearer ast_..."

Start or resume Stripe Connect onboarding

Returns a single-use Stripe account-link URL the seller opens to complete payout setup. 404 when the payout tables are not yet migrated. 503 when the payment processor is not configured.

Response · 200

urlstringrequired

Single-use Stripe account-link URL; expires quickly

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/seller/account/connect \
  -H "Authorization: Bearer ast_..."

Record that a user was referred by you

Records that the target user was brought to the platform by the caller. A user can have at most one referral source; a second call for the same target is a no-op (200, `recorded: false`). 404 when the payout tables are not yet migrated.

Body · application/json

referred_user_idstringrequired

The id of the user who was referred

Response · 200

recordedbooleanrequired

true when this call created the referral row; false when it already existed

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/seller/referrals \
  -H "Authorization: Bearer ast_..."

What you were told about the agents you sell

Newest first: a submission approved or sent back, a listing taken down, a lost `Checked` mark, a ruling on a disputed fee, a payout recorded. Each is also mailed once to the seller where task emails are on for the seller's workspace, unless the seller turned these emails off with the link in one of them. `handle` narrows the list to one listing plus the notices that are about none. 404 where neither public submissions nor flat fees are offered.

Query parameters

handlestring

Response · 200

dataobject[]required
▸ Show child attributes
idstringrequired
kindenum<string>required

"approved" · "sent_back" · "taken_down" · "checks_failed" · "dispute_refunded" · "dispute_upheld" · "payout_paid"

handlestring | nullrequired
titlestringrequired
textstringrequired

The notice in words, with the reviewer's reason or the amount

created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/seller/notices' \
  -H "Authorization: Bearer ast_..."

Report comparison counts per handle

For the first-party client that records side-by-side comparison verdicts; any other token is refused with 403. The body is a full snapshot taken at `reported_at`: each handle is set to its totals and a handle left out is removed, so sending the same snapshot again changes nothing and an older one never overwrites a newer one. The totals reach `stats.comparisons` and `stats.wins` on the next hourly recount. Answers 503 `not_migrated` until the platform's table is in place.

Body · application/json

reported_atstringrequired
countsobject[]required
▸ Show child attributes
handlestringrequired
comparisonsintegerrequired
winsintegerrequired

Response · 200

handlesintegerrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PUT https://api.agentsky.dev/v1/catalog/comparison_counts \
  -H "Authorization: Bearer ast_..."

The category vocabulary

Response · 200

categoriesobject[]required
▸ Show child attributes
idenum<string>required

"websites" · "content" · "video" · "code" · "research" · "general"

labelstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/catalog/categories' \
  -H "Authorization: Bearer ast_..."

List environment listings on the shelf

All workspace-visible environment listings. Needs no credentials; a caller that sends them may also see their own workspace's unpublished listings. Answers 404 when the shelf is not enabled. Answers 503 `not_migrated` until the shelf migration is applied.

Query parameters

qstring

Matches handle, name, tagline and description

categorystring
sortstring

Response · 200

environmentsobject[]required
▸ Show child attributes
idstringrequired

The listing id (lst_…)

handlestringrequired

Globally unique within environment listings; lower-case letters, digits and underscores

namestringrequired
taglinestringrequired

One line, at most 140 characters

descriptionstringrequired
categoriesenum<string>[]required

"development" · "data" · "ml" · "security" · "web" · "general"

packagesobject | nullrequired

The listed environment's package configuration, or null when it has none

toolsobject | nullrequired

The listed environment's tool policy, or null when it has none

networkingobject | nullrequired

The listed environment's networking configuration, or null when it has none

installsintegerrequired

How many workspaces have installed this listing

sellerobjectrequired

The workspace that published the listing

▸ Show child attributes
namestringrequired
visibilityenum<string>required

workspace = visible only to the owning workspace; public = visible to all — "workspace" · "public"

conformancenullrequired

Reserved; always null in this release

created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/catalog/environments' \
  -H "Authorization: Bearer ast_..."

One environment listing by handle

Answers 404 when the shelf is not enabled, the handle is not found, or the listing belongs to a different workspace and the shelf is restricted to this workspace only.

Path parameters

handlestringrequired

The listing handle

Response · 200

environmentobjectrequired
▸ Show child attributes
idstringrequired

The listing id (lst_…)

handlestringrequired

Globally unique within environment listings; lower-case letters, digits and underscores

namestringrequired
taglinestringrequired

One line, at most 140 characters

descriptionstringrequired
categoriesenum<string>[]required

"development" · "data" · "ml" · "security" · "web" · "general"

packagesobject | nullrequired

The listed environment's package configuration, or null when it has none

toolsobject | nullrequired

The listed environment's tool policy, or null when it has none

networkingobject | nullrequired

The listed environment's networking configuration, or null when it has none

installsintegerrequired

How many workspaces have installed this listing

sellerobjectrequired

The workspace that published the listing

▸ Show child attributes
namestringrequired
visibilityenum<string>required

workspace = visible only to the owning workspace; public = visible to all — "workspace" · "public"

conformancenullrequired

Reserved; always null in this release

created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/catalog/environments/handle' \
  -H "Authorization: Bearer ast_..."

Install an environment listing into your workspace

Creates a copy of the listed environment in the caller's workspace that `extends` the original, so composition (packages, tool policy, networking) is applied at write time. A second install of the same listing by the same workspace is idempotent and returns the existing copy. Answers 404 when the shelf is not enabled or the listing is not found. Answers 503 `not_migrated` until the shelf migration is applied.

Path parameters

handlestringrequired

The listing handle

Response · 201

environmentobjectrequired
▸ Show child attributes
idstringrequired

env_…

namestringrequired
configobjectrequired

`packages` are installed into the image at build time — an environment is built when it is created and rebuilt when its config changes, so a session starting from it pays no install cost. `networking` is the egress policy its sessions run under; `limited` needs `allow_package_managers` when packages are declared, or the install could never succeed.

▸ Show child attributes
type"cloud"

default: "cloud"

packagesobject
▸ Show child attributes
aptstring[]

default: [] — max length 512

pipstring[]

default: [] — max length 512

npmstring[]

default: [] — max length 512

networkingobject
▸ Show child attributes
type: "unrestricted"object
▸ Show child attributes
type"unrestricted"required
type: "limited"object
▸ Show child attributes
type"limited"required
allowed_hostsstring[]

default: [] — max length 253 — pattern ^(\*\.)?([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?$

allow_mcp_serversboolean

default: false

allow_package_managersboolean

default: false

is_defaultbooleanrequired

Whether a new session that names no environment uses this one. At most one per workspace; setting it on one clears it on the others.

extendsstring | nullrequired

The env_… id of the parent environment this one extends, or null. Immutable after create. Child packages, tools.disabled and networking compose on the parent's at write time.

created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/catalog/environments/handle/install \
  -H "Authorization: Bearer ast_..."

Where one of the workspace's listings runs

The secret is never returned here. Answers 404 until running an agent on your own server is open for the workspace.

Path parameters

handlestringrequired

The handle of one of the workspace's own listings.

Response · 200

hostingenum<string>required

`platform`: in a sandbox. `seller`: on the maker's own server. — "platform" · "seller"

endpoint_urlstring

The address tasks are sent to. Present when `hosting` is `seller`.

secretstring

The secret requests are signed with. Present only in the response that made or replaced it.

created_atstring
updated_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/catalog/listings/handle/hosting' \
  -H "Authorization: Bearer ast_..."

Run a listing on your own server

Each task given to the listing is then sent to this address instead of a sandbox, as one POST per turn: `{id, type: "task.turn", created_at, task: {id, session_id, agent}, message: {id, text}, pass: {token, expires_at}, api_base, callback_url}`. The request is signed like a webhook: `x-asteroids-timestamp`, and `x-asteroids-signature` = `v1=` + HMAC-SHA256 of `<timestamp>.<body>` with the listing's secret; check it before trusting the body. Answer 2xx within 10 seconds, then do the work and report to `callback_url`. The request is made once and is not retried; an address that does not answer 2xx in time ends the turn with an error the person reads. `pass.token` is a Bearer credential for that one turn of that one task. It reads the task (`GET /tasks/{id}`), reports to it (`POST /tasks/{id}/callback`), and reads and writes its files (`/tasks/{id}/files`); every other route refuses it with 403. It stops working when the turn ends, when the person stops the turn or archives the task, or after 15 minutes, whichever is first; a turn still open then is ended with an error. A later message from the person, or their answer to a question, is a new turn with a new pass. The address must be https on the public internet. The first call answers 201 with the signing secret, shown once; a later call changes the address and keeps the secret. A listing that is already public keeps running where its approved version said until a new submission is approved. Answers 404 until running an agent on your own server is open for the workspace. 503 `not_migrated` until its tables are in place.

Path parameters

handlestringrequired

The handle of one of the workspace's own listings.

Body · application/json

endpoint_urlstringrequired

The https address tasks are sent to.

Response · 200

Address changed

hostingenum<string>required

`platform`: in a sandbox. `seller`: on the maker's own server. — "platform" · "seller"

endpoint_urlstring

The address tasks are sent to. Present when `hosting` is `seller`.

secretstring

The secret requests are signed with. Present only in the response that made or replaced it.

created_atstring
updated_atstring

Response · 201

Now runs on your server; carries the secret

hostingenum<string>required

`platform`: in a sandbox. `seller`: on the maker's own server. — "platform" · "seller"

endpoint_urlstring

The address tasks are sent to. Present when `hosting` is `seller`.

secretstring

The secret requests are signed with. Present only in the response that made or replaced it.

created_atstring
updated_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PUT https://api.agentsky.dev/v1/catalog/listings/handle/hosting \
  -H "Authorization: Bearer ast_..."

Run a listing in a sandbox again

Tasks already started on your server can no longer be sent to it: their next turn ends with an error. Answers 404 until running an agent on your own server is open for the workspace.

Path parameters

handlestringrequired

The handle of one of the workspace's own listings.

Response · 200

hostingenum<string>required

`platform`: in a sandbox. `seller`: on the maker's own server. — "platform" · "seller"

endpoint_urlstring

The address tasks are sent to. Present when `hosting` is `seller`.

secretstring

The secret requests are signed with. Present only in the response that made or replaced it.

created_atstring
updated_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/catalog/listings/handle/hosting \
  -H "Authorization: Bearer ast_..."

Replace the secret a listing's requests are signed with

Answers the new secret, shown once. The next request is signed with it; the old one is no longer used. Answers 404 until running an agent on your own server is open for the workspace.

Path parameters

handlestringrequired

The handle of one of the workspace's own listings.

Response · 201

Replaced; carries the new secret

hostingenum<string>required

`platform`: in a sandbox. `seller`: on the maker's own server. — "platform" · "seller"

endpoint_urlstring

The address tasks are sent to. Present when `hosting` is `seller`.

secretstring

The secret requests are signed with. Present only in the response that made or replaced it.

created_atstring
updated_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/catalog/listings/handle/hosting/secret \
  -H "Authorization: Bearer ast_..."

Artifacts

GET/artifactsread

List the workspace's artifacts

Newest first. With `task_id`, that task's only. Answers 503 `not_migrated` until the platform's artifact tables are in place.

Query parameters

task_idstring

Response · 200

artifactsobject[]required
▸ Show child attributes
idstringrequired
task_idstringrequired

The task it belongs to (sess_…)

namestringrequired

Unique within the task; publishing under the same name adds a version

versionintegerrequired

The current revision

entrystringrequired

The file opened first

filesobject[]required
▸ Show child attributes
pathstringrequired
sha256stringrequired
size_bytesintegerrequired
share_urlstring | nullrequired

The public link, or null while not shared

created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/artifacts' \
  -H "Authorization: Bearer ast_..."
POST/artifactswrite

Publish task files as an artifact revision

Publishes paths from the task's file space (`/tasks/{id}/files`) as a new revision of the artifact with that name in the task, creating the artifact on first use. A path that names a folder publishes everything under it. The revision records each file's content at this moment; later edits to the task's files do not change it. `entry` defaults to the only file, or to an `index.html`. 400 when a path names nothing; at most 500 files.

Body · application/json

task_idstringrequired
namestringrequired

max length 120

pathsstring[]required
entrystring

Response · 201

artifactobjectrequired
▸ Show child attributes
idstringrequired
task_idstringrequired

The task it belongs to (sess_…)

namestringrequired

Unique within the task; publishing under the same name adds a version

versionintegerrequired

The current revision

entrystringrequired

The file opened first

filesobject[]required
▸ Show child attributes
pathstringrequired
sha256stringrequired
size_bytesintegerrequired
share_urlstring | nullrequired

The public link, or null while not shared

created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/artifacts \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"task_id":"sess_cmtb7q2j","name":"Launch page","paths":["site/index.html","site/style.css"],"entry":"site/index.html"}'

One artifact with every revision

Path parameters

idstringrequired

The artifact id

Response · 200

artifactanyrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/artifacts/cmtb6a1r9t4f2c01s6x8y3z5' \
  -H "Authorization: Bearer ast_..."
DELETE/artifacts/{id}write

Remove an artifact

It stops being listed and its public link stops working. Publishing under the same name in the task afterwards brings it back with the next version number.

Path parameters

idstringrequired

The artifact id

Response · 200

okbooleanrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/artifacts/cmtb6a1r9t4f2c01s6x8y3z5 \
  -H "Authorization: Bearer ast_..."

Turn the artifact's public link on or off

The link needs no credentials and always serves the current revision. Published pages are served sandboxed: their scripts cannot read the platform's cookies or call its API as the visitor. Turning sharing off makes the link stop working; turning it on again gives a new link.

Path parameters

idstringrequired

The artifact id

Body · application/json

enabledbooleanrequired

Response · 200

share_urlstring | nullrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/artifacts/cmtb6a1r9t4f2c01s6x8y3z5/share \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"enabled":true}'

Download an artifact as one archive

A zip archive of every file of the current revision, or of `version=N`, each at its published path. 413 `export_too_large` when the files are more than 64 MiB together.

Path parameters

idstringrequired

The artifact id

Query parameters

versioninteger

Response · 200

The archive

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/artifacts/cmtb6a1r9t4f2c01s6x8y3z5/export' \
  -H "Authorization: Bearer ast_..."

Download one file of an artifact

The current revision's file, or `version=N`. Always sent as a download.

Path parameters

idstringrequired

The artifact id

pathstringrequired

Query parameters

versioninteger

Response · 200

The bytes

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/artifacts/cmtb6a1r9t4f2c01s6x8y3z5/files/report.md' \
  -H "Authorization: Bearer ast_..."

Browser

Read the session browser and live snapshots

Uses the session's existing universe and token restrictions. Viewing reconnects without restarting execution. Expired browsers are finalized; final screenshots and action history remain readable.

Path parameters

idstringrequired

The session id

Response · 200

Authorized browser state, or null when the session has no browser. Provider credentials, interactive viewer links and browser connection URLs are never returned.

browserobject | nullrequired
▸ Show child attributes
idstringrequired
statusenum<string>required

"preparing" · "running" · "completed" · "blocked" · "failed" · "stopped"

viewerUrlnullrequired

Always null. Observation uses screenshots; interactive provider viewer links are never exposed.

urlstringrequired
startedAtstringrequired
expiresAtstringrequired
endedAtstring | nullrequired
elapsedMsnumberrequired
actionCountintegerrequired
progressstring
claimstring

The agent's completion claim, separate from task verification.

resolvedModelstring

Resolved Jev model reported by OpenRouter.

errorstring
actionsobject[]required
▸ Show child attributes
idstringrequired
verbstringrequired
detailstringrequired
timestampstringrequired
statusstringrequired
verificationobjectrequired
▸ Show child attributes
statusenum<string>required

"passed" · "failed" · "unverified"

checksobject[]required
▸ Show child attributes
labelstringrequired
statusenum<string>required

"passed" · "failed" · "unverified"

detailstringrequired
lastScreenshotstring | nullrequired

Latest observed or final JPEG as a data URL when capture succeeded.

lastScreenshotAtstring | null

Time the latest screenshot was captured successfully.

cleanupPendingbooleanrequired

A terminal browser may still be releasing provider resources; cleanup is retried durably.

costsobjectrequired

Recorded billed USD, including the fixed Mercury text-entry helper. Receipts can arrive after completion.

▸ Show child attributes
decisionUsdnumberrequired
helperUsdnumberrequired
browserUsdnumberrequired
runtimeUsdnumberrequired
totalUsdnumberrequired

Metered cost including waived usage.

chargedUsdnumberrequired

Actual amount charged after billing waivers.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/browser' \
  -H "Authorization: Bearer ast_..."

Prepare an isolated browser for a session

Prepare before sending the task's first turn. Requires an active session, positive credit balance and remaining session budget. An identical repeated request reuses the browser; a different configuration or an ended browser returns 409. The browser has a 15-minute lifetime, fixed viewport and bounded actions. Structured Google Flights verification checks visible route, dates, passengers, cabin and results; tasks without verification remain unverified. Browser usage is billed separately from model and runtime usage.

Path parameters

idstringrequired

The session id

Body · application/json

taskstringrequired

max length 16000

startUrlstringrequired
viewportobjectrequired
▸ Show child attributes
widthintegerrequired
heightintegerrequired
verificationobject
▸ Show child attributes
kind"google-flights"required
originstringrequired

max length 120

destinationstringrequired

max length 120

departureDatestringrequired

pattern ^\d{4}-\d{2}-\d{2}$

returnDatestring

pattern ^\d{4}-\d{2}-\d{2}$

passengersintegerrequired
cabinenum<string>required

"economy" · "premium-economy" · "business" · "first"

Response · 201

Authorized browser state, or null when the session has no browser. Provider credentials, interactive viewer links and browser connection URLs are never returned.

browserobject | nullrequired
▸ Show child attributes
idstringrequired
statusenum<string>required

"preparing" · "running" · "completed" · "blocked" · "failed" · "stopped"

viewerUrlnullrequired

Always null. Observation uses screenshots; interactive provider viewer links are never exposed.

urlstringrequired
startedAtstringrequired
expiresAtstringrequired
endedAtstring | nullrequired
elapsedMsnumberrequired
actionCountintegerrequired
progressstring
claimstring

The agent's completion claim, separate from task verification.

resolvedModelstring

Resolved Jev model reported by OpenRouter.

errorstring
actionsobject[]required
▸ Show child attributes
idstringrequired
verbstringrequired
detailstringrequired
timestampstringrequired
statusstringrequired
verificationobjectrequired
▸ Show child attributes
statusenum<string>required

"passed" · "failed" · "unverified"

checksobject[]required
▸ Show child attributes
labelstringrequired
statusenum<string>required

"passed" · "failed" · "unverified"

detailstringrequired
lastScreenshotstring | nullrequired

Latest observed or final JPEG as a data URL when capture succeeded.

lastScreenshotAtstring | null

Time the latest screenshot was captured successfully.

cleanupPendingbooleanrequired

A terminal browser may still be releasing provider resources; cleanup is retried durably.

costsobjectrequired

Recorded billed USD, including the fixed Mercury text-entry helper. Receipts can arrive after completion.

▸ Show child attributes
decisionUsdnumberrequired
helperUsdnumberrequired
browserUsdnumberrequired
runtimeUsdnumberrequired
totalUsdnumberrequired

Metered cost including waived usage.

chargedUsdnumberrequired

Actual amount charged after billing waivers.

Response · 400

Error — { error: { code, message } }

Response · 402

Error — { error: { code, message } }

Response · 409

Error — { error: { code, message } }

Response · 502

Error — { error: { code, message } }

Response · 503

Error — { error: { code, message } }

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/browser \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"task":"Find the Example Domain heading and stop when it is visible.","startUrl":"https://example.com","viewport":{"width":1120,"height":780}}'

Stop the session browser and release its resources

Fences new browser actions before capturing the final page and releasing the browser. Repeated requests retry unfinished cleanup; a session without a browser returns null. This operation stops browser access; use POST /sessions/{id}/interrupt to also interrupt the agent's turn.

Path parameters

idstringrequired

The session id

Response · 200

Authorized browser state, or null when the session has no browser. Provider credentials, interactive viewer links and browser connection URLs are never returned.

browserobject | nullrequired
▸ Show child attributes
idstringrequired
statusenum<string>required

"preparing" · "running" · "completed" · "blocked" · "failed" · "stopped"

viewerUrlnullrequired

Always null. Observation uses screenshots; interactive provider viewer links are never exposed.

urlstringrequired
startedAtstringrequired
expiresAtstringrequired
endedAtstring | nullrequired
elapsedMsnumberrequired
actionCountintegerrequired
progressstring
claimstring

The agent's completion claim, separate from task verification.

resolvedModelstring

Resolved Jev model reported by OpenRouter.

errorstring
actionsobject[]required
▸ Show child attributes
idstringrequired
verbstringrequired
detailstringrequired
timestampstringrequired
statusstringrequired
verificationobjectrequired
▸ Show child attributes
statusenum<string>required

"passed" · "failed" · "unverified"

checksobject[]required
▸ Show child attributes
labelstringrequired
statusenum<string>required

"passed" · "failed" · "unverified"

detailstringrequired
lastScreenshotstring | nullrequired

Latest observed or final JPEG as a data URL when capture succeeded.

lastScreenshotAtstring | null

Time the latest screenshot was captured successfully.

cleanupPendingbooleanrequired

A terminal browser may still be releasing provider resources; cleanup is retried durably.

costsobjectrequired

Recorded billed USD, including the fixed Mercury text-entry helper. Receipts can arrive after completion.

▸ Show child attributes
decisionUsdnumberrequired
helperUsdnumberrequired
browserUsdnumberrequired
runtimeUsdnumberrequired
totalUsdnumberrequired

Metered cost including waived usage.

chargedUsdnumberrequired

Actual amount charged after billing waivers.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/browser \
  -H "Authorization: Bearer ast_..."

Workspace

List a directory in the session's workspace

Returns up to 200 entries (name, type, size, mtime) for a directory under /data/workspace. Dotfiles are excluded by default; pass ?hidden=true to include them. Only regular files and directories are listed: symlinks, FIFOs, sockets and devices never are. Paths are confined to the workspace root; '..' and absolute paths outside the root return 400 invalid_path. A parked or suspended pod returns 409 session_parked — send a message to wake it.

Path parameters

idstringrequired

The session id

Query parameters

pathstring

Relative or absolute path under workspace root; defaults to root

hiddenboolean

Include dotfiles (default false)

Response · 200

pathstring
entriesobject[]
▸ Show child attributes
namestring
typeenum<string>

"file" · "directory"

sizeinteger
mtimestring
truncatedboolean
limitinteger

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/workspace/files' \
  -H "Authorization: Bearer ast_..."

Download a file from the session's workspace

Returns the raw file bytes as an attachment. Limited to 1 MB. Binary files are supported. Content-Type is inferred from the file extension. Returns 400 not_a_file for directories, 413 file_too_large when over the cap, 403 path_escape for symlink escapes, 409 session_parked when the pod is not running.

Path parameters

idstringrequired

The session id

Query parameters

pathstringrequired

Relative or absolute path to the file under workspace root

Response · 200

File contents

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/workspace/files/content?path=report.md' \
  -H "Authorization: Bearer ast_..."

Git status and diff summary for each repo in the session's workspace

Finds up to 10 git repositories within three levels of the workspace root and, for each, runs `git status --porcelain=v1` and `git diff --stat HEAD` inside the pod as the workspace owner, with fsmonitor, hooks, external diff drivers and textconv disabled. Each output is bounded to 200 lines. `repos` is empty when the workspace has no repository. Never wakes the pod: 409 session_parked when it is not running, 409 workspace_unsupported when its runtime has no exec or resumes a parked sandbox on contact (E2B), 503 workspace_unavailable when the read cannot run as the workspace owner.

Path parameters

idstringrequired

The session id

Response · 200

rootstring
reposobject[]
▸ Show child attributes
pathstring

repo directory relative to root; "." for the root itself

statusstring | null

git status --porcelain=v1 output; null when clean

statstring | null

git diff --stat HEAD output; null when no diff or no commit yet

limitinteger

most repos reported

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/workspace/changes' \
  -H "Authorization: Bearer ast_..."

Copy a folder from the caller's machine into the workspace

The body is the folder as a gzipped tar (up to 25 MB). It is unpacked at <workspace root>/<name> as the workspace owner and made a git repository whose first commit is that copy, so /workspace/patch later answers the work done on it. Wakes a parked pod. 400 invalid_name, 409 already_exists, 413 archive_too_large, 422 invalid_archive.

Path parameters

idstringrequired

The session id

Query parameters

namestringrequired

the folder's name in the workspace: 1–80 letters, digits, spaces, dots, dashes or underscores

Response · 200

pathstring
filesinteger

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/workspace/import \
  -H "Authorization: Bearer ast_..."

The work in one workspace repo since its base branch, as a git patch

Runs inside the pod as the workspace owner and returns one binary-safe `git diff --binary` from the merge base of HEAD with the branch's upstream (or the remote's default branch, or else the base an imported folder recorded, with base_branch "") to the working tree: commits, uncommitted edits and new files that are not ignored. The repository's own index is left as it was. Wakes a parked pod. 400 not_a_repository, 409 no_base when there is no remote branch to compare against, 413 patch_too_large over 5 MB.

Path parameters

idstringrequired

The session id

Body · application/json

repostringrequired

repo directory relative to the workspace root, as /workspace/changes lists it; "." for the root

Response · 200

repostring
base_branchstring

the branch the work started from, as the remote names it

base_commitstring

the commit the patch applies to

commitsstring[]

subjects of the commits since the base, oldest first

patchstring

base64 of the patch; empty when nothing changed

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/sessions/sess_cmtb7q2j/workspace/patch \
  -H "Authorization: Bearer ast_..."

This Mac

The person's Macs connected through the Mac app

Response · 200

machinesobject[]required
▸ Show child attributes
idstringrequired

mac_…

namestringrequired
onlinebooleanrequired

The Mac app polled within the last minute

last_seen_atstringrequired
created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/desktop/machines' \
  -H "Authorization: Bearer ast_..."

Register this Mac

The Mac app registers the Mac it runs on and is handed its connect token once. The token is what the app polls the relay with; the person's own token never reaches the app. Edge-routed to the chat-proxy like the ports routes.

Body · application/json

namestringrequired

What the person calls this Mac

Response · 201

Registered

machineobjectrequired
▸ Show child attributes
idstringrequired

mac_…

namestringrequired
onlinebooleanrequired

The Mac app polled within the last minute

last_seen_atstringrequired
created_atstringrequired
connect_tokenstringrequired

dmc_… — shown once; the Mac app's only credential, stored hashed

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/desktop/machines \
  -H "Authorization: Bearer ast_..."

Revoke a Mac

The app's connect token stops working and every folder it handed over answers 404 from then on.

Path parameters

idstringrequired

Response · 204

Revoked

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/desktop/machines/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."
POST/desktop/machines/{id}/mountsmachine connect token

Hand a locally selected folder on that Mac to agents

Answers the address a spec's `mcp_servers` entry carries (`{type: "url", name: "this-mac", url: mcp_url}`): a pod's MCP calls on it are relayed to the Mac app, which answers them with file tools rooted at the folder and holds every change for the person's confirmation. This route accepts only that Mac's connect token after its native picker returns a normalized absolute path; an account token cannot create a mount. A Mac that is not polling answers 503 machine_offline to the pod.

Path parameters

idstringrequired

Body · application/json

rootstringrequired

The folder's absolute path on that Mac

labelstringrequired

What the thread shows for it

Response · 201

Mounted

idstringrequired

dmt_…

machine_idstringrequired
rootstringrequired
labelstringrequired
mcp_urlstringrequired

https://mac-<token>.agentsky.dev/mcp — put it in a spec's mcp_servers as a url server; the token is the credential

created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/desktop/machines/sess_cmtb7q2j/mounts \
  -H "Authorization: Bearer ast_..."

Take a folder back

Its address answers 404 from then on; a running session keeps its spec entry but every call to it fails.

Path parameters

idstringrequired

Response · 204

Revoked

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/desktop/mounts/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."

Verify a live folder mount before starting agents

Confirms that the mount id and capability URL still name the same live folder owned by this account in the token's universe, or the account's personal universe when the token is unscoped. A stale, revoked, foreign-universe or mismatched mount answers 404.

Path parameters

idstringrequired

Body · application/json

mcp_urlstringrequired

The mount capability URL returned when the folder was selected

Response · 204

The mount is live and owned by this account

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/desktop/mounts/sess_cmtb7q2j/verify \
  -H "Authorization: Bearer ast_..."

Routines

GET/routinesread

List routines

Query parameters

cursorstring
limitinteger

1–500, default 50

Response · 200

itemsobject[]required
▸ Show child attributes
idstring

rtn_… identifier

namestring
descriptionstring | null
metadataobject
targetobject

{type:"new_session", agent, environment_id?, vault_ids?} — a fresh session per fire (CMA parity) · {type:"session", session_id} — a turn into the existing session every fire (busy target skips with session_busy_error)

initial_eventsobject[]
scheduleobject | null

5-field POSIX cron + IANA timezone, wall-clock matching, minute granularity; null = manual-run only

budgetobject | null

Per-run cap (RFC-0080 shape): copied onto each new session (mode new_session) or granted as a per-fire delta allowance consumed+budget (mode session). Clearable.

statusenum<string>

"active" · "paused"

paused_reasonobject | null

{type:"manual"} | {type:"error", error:{type}} — non-null exactly when paused

archived_atstring | null
created_atstring
updated_atstring
cursorstring | null
hasMoreboolean

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/routines' \
  -H "Authorization: Bearer ast_..."
POST/routineswrite

Create a routine — scheduled agent execution

initial_events (1–50 user.message events) are delivered on every fire. target picks the mode: new_session creates a fresh session per run; session sends the turn into an existing session (busy target → failed run session_busy_error). schedule is a 5-field POSIX cron with an IANA timezone; omit it for a manual-run-only routine. budget bounds each run separately.

Body · application/json

namestringrequired

max length 256

descriptionstring

max length 2048

metadatamap<string, string>

max length 512

targetobjectrequired
▸ Show child attributes
type: "new_session"object
▸ Show child attributes
type"new_session"required
agentstringrequired
environment_idstring
vault_idsstring[]
type: "session"object
▸ Show child attributes
type"session"required
session_idstringrequired
initial_eventsobject[]required
▸ Show child attributes
type"user.message"required
contentobject[]required
▸ Show child attributes
type: "text"object
▸ Show child attributes
type"text"required
textstringrequired
type: "image"object
▸ Show child attributes
type"image"required
sourceobjectrequired
▸ Show child attributes
type: "base64"object
▸ Show child attributes
type"base64"required
media_typestringrequired
datastringrequired
type: "url"object
▸ Show child attributes
type"url"required
urlstringrequired
type: "file"object
▸ Show child attributes
type"file"required
file_idstringrequired
type: "document"object
▸ Show child attributes
type"document"required
sourceobjectrequired
▸ Show child attributes
type: "base64"object
▸ Show child attributes
type"base64"required
media_typestringrequired
datastringrequired
type: "text"object
▸ Show child attributes
type"text"required
media_type"text/plain"

default: "text/plain"

datastringrequired
type: "url"object
▸ Show child attributes
type"url"required
urlstringrequired
type: "file"object
▸ Show child attributes
type"file"required
file_idstringrequired
titlestring | null
contextstring | null
interaction_modeenum<string> | null

"plan" · "build"

scheduleobject | null
▸ Show child attributes
type"cron"required
expressionstringrequired

max length 256

timezonestringrequired
budgetobject | null
▸ Show child attributes
type"limit"required
max_list_costobjectrequired
▸ Show child attributes
amountstringrequired

Whole US cents as an integer decimal string, e.g. "125" for $1.25 — max length 15

currency"USD"required

Response · 201

routineobjectrequired

Scheduled agent execution: initial_events + a target (new_session per fire, or an existing session) bound to a cron schedule. Fires record routine runs.

▸ Show child attributes
idstring

rtn_… identifier

namestring
descriptionstring | null
metadataobject
targetobject

{type:"new_session", agent, environment_id?, vault_ids?} — a fresh session per fire (CMA parity) · {type:"session", session_id} — a turn into the existing session every fire (busy target skips with session_busy_error)

initial_eventsobject[]
scheduleobject | null

5-field POSIX cron + IANA timezone, wall-clock matching, minute granularity; null = manual-run only

budgetobject | null

Per-run cap (RFC-0080 shape): copied onto each new session (mode new_session) or granted as a per-fire delta allowance consumed+budget (mode session). Clearable.

statusenum<string>

"active" · "paused"

paused_reasonobject | null

{type:"manual"} | {type:"error", error:{type}} — non-null exactly when paused

archived_atstring | null
created_atstring
updated_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/routines \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"name":"Weekly compliance scan","target":{"type":"new_session","agent":"agent_cmtb2f0a8m9k7x51q4ez6r0d"},"initial_events":[{"type":"user.message","content":[{"type":"text","text":"Run the weekly compliance scan."}]}],"schedule":{"type":"cron","expression":"0 20 * * 5","timezone":"America/New_York"}}'

Routine detail

Path parameters

idstringrequired

The routine id (rtn_…)

Response · 200

routineobjectrequired

Scheduled agent execution: initial_events + a target (new_session per fire, or an existing session) bound to a cron schedule. Fires record routine runs.

▸ Show child attributes
idstring

rtn_… identifier

namestring
descriptionstring | null
metadataobject
targetobject

{type:"new_session", agent, environment_id?, vault_ids?} — a fresh session per fire (CMA parity) · {type:"session", session_id} — a turn into the existing session every fire (busy target skips with session_busy_error)

initial_eventsobject[]
scheduleobject | null

5-field POSIX cron + IANA timezone, wall-clock matching, minute granularity; null = manual-run only

budgetobject | null

Per-run cap (RFC-0080 shape): copied onto each new session (mode new_session) or granted as a per-fire delta allowance consumed+budget (mode session). Clearable.

statusenum<string>

"active" · "paused"

paused_reasonobject | null

{type:"manual"} | {type:"error", error:{type}} — non-null exactly when paused

archived_atstring | null
created_atstring
updated_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/routines/sess_cmtb7q2j' \
  -H "Authorization: Bearer ast_..."
PATCH/routines/{id}write

Update a routine — omit preserves; null clears schedule/budget

initial_events is a full replacement; metadata is key-patched (null deletes a key); name and target cannot be cleared. Archived routines are immutable (409).

Path parameters

idstringrequired

The routine id (rtn_…)

Body · application/json

namestring

max length 256

descriptionstring | null

max length 2048

metadatamap<string, string | null>
targetobject
▸ Show child attributes
type: "new_session"object
▸ Show child attributes
type"new_session"required
agentstringrequired
environment_idstring
vault_idsstring[]
type: "session"object
▸ Show child attributes
type"session"required
session_idstringrequired
initial_eventsobject[]
▸ Show child attributes
type"user.message"required
contentobject[]required
▸ Show child attributes
type: "text"object
▸ Show child attributes
type"text"required
textstringrequired
type: "image"object
▸ Show child attributes
type"image"required
sourceobjectrequired
▸ Show child attributes
type: "base64"object
▸ Show child attributes
type"base64"required
media_typestringrequired
datastringrequired
type: "url"object
▸ Show child attributes
type"url"required
urlstringrequired
type: "file"object
▸ Show child attributes
type"file"required
file_idstringrequired
type: "document"object
▸ Show child attributes
type"document"required
sourceobjectrequired
▸ Show child attributes
type: "base64"object
▸ Show child attributes
type"base64"required
media_typestringrequired
datastringrequired
type: "text"object
▸ Show child attributes
type"text"required
media_type"text/plain"

default: "text/plain"

datastringrequired
type: "url"object
▸ Show child attributes
type"url"required
urlstringrequired
type: "file"object
▸ Show child attributes
type"file"required
file_idstringrequired
titlestring | null
contextstring | null
interaction_modeenum<string> | null

"plan" · "build"

scheduleobject | null
▸ Show child attributes
type"cron"required
expressionstringrequired

max length 256

timezonestringrequired
budgetobject | null
▸ Show child attributes
type"limit"required
max_list_costobjectrequired
▸ Show child attributes
amountstringrequired

Whole US cents as an integer decimal string, e.g. "125" for $1.25 — max length 15

currency"USD"required

Response · 200

routineobjectrequired

Scheduled agent execution: initial_events + a target (new_session per fire, or an existing session) bound to a cron schedule. Fires record routine runs.

▸ Show child attributes
idstring

rtn_… identifier

namestring
descriptionstring | null
metadataobject
targetobject

{type:"new_session", agent, environment_id?, vault_ids?} — a fresh session per fire (CMA parity) · {type:"session", session_id} — a turn into the existing session every fire (busy target skips with session_busy_error)

initial_eventsobject[]
scheduleobject | null

5-field POSIX cron + IANA timezone, wall-clock matching, minute granularity; null = manual-run only

budgetobject | null

Per-run cap (RFC-0080 shape): copied onto each new session (mode new_session) or granted as a per-fire delta allowance consumed+budget (mode session). Clearable.

statusenum<string>

"active" · "paused"

paused_reasonobject | null

{type:"manual"} | {type:"error", error:{type}} — non-null exactly when paused

archived_atstring | null
created_atstring
updated_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PATCH https://api.agentsky.dev/v1/routines/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"schedule":{"type":"cron","expression":"0 9 * * 1-5","timezone":"UTC"}}'

Pause — suppress scheduled fires; manual runs still work

Path parameters

idstringrequired

The routine id (rtn_…)

Response · 200

routineobjectrequired

Scheduled agent execution: initial_events + a target (new_session per fire, or an existing session) bound to a cron schedule. Fires record routine runs.

▸ Show child attributes
idstring

rtn_… identifier

namestring
descriptionstring | null
metadataobject
targetobject

{type:"new_session", agent, environment_id?, vault_ids?} — a fresh session per fire (CMA parity) · {type:"session", session_id} — a turn into the existing session every fire (busy target skips with session_busy_error)

initial_eventsobject[]
scheduleobject | null

5-field POSIX cron + IANA timezone, wall-clock matching, minute granularity; null = manual-run only

budgetobject | null

Per-run cap (RFC-0080 shape): copied onto each new session (mode new_session) or granted as a per-fire delta allowance consumed+budget (mode session). Clearable.

statusenum<string>

"active" · "paused"

paused_reasonobject | null

{type:"manual"} | {type:"error", error:{type}} — non-null exactly when paused

archived_atstring | null
created_atstring
updated_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/routines/sess_cmtb7q2j/pause \
  -H "Authorization: Bearer ast_..."

Unpause — resumes from the NEXT occurrence; missed fires are never backfilled

Path parameters

idstringrequired

The routine id (rtn_…)

Response · 200

routineobjectrequired

Scheduled agent execution: initial_events + a target (new_session per fire, or an existing session) bound to a cron schedule. Fires record routine runs.

▸ Show child attributes
idstring

rtn_… identifier

namestring
descriptionstring | null
metadataobject
targetobject

{type:"new_session", agent, environment_id?, vault_ids?} — a fresh session per fire (CMA parity) · {type:"session", session_id} — a turn into the existing session every fire (busy target skips with session_busy_error)

initial_eventsobject[]
scheduleobject | null

5-field POSIX cron + IANA timezone, wall-clock matching, minute granularity; null = manual-run only

budgetobject | null

Per-run cap (RFC-0080 shape): copied onto each new session (mode new_session) or granted as a per-fire delta allowance consumed+budget (mode session). Clearable.

statusenum<string>

"active" · "paused"

paused_reasonobject | null

{type:"manual"} | {type:"error", error:{type}} — non-null exactly when paused

archived_atstring | null
created_atstring
updated_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/routines/sess_cmtb7q2j/unpause \
  -H "Authorization: Bearer ast_..."

Archive — terminal; the schedule stops and the routine becomes immutable

Path parameters

idstringrequired

The routine id (rtn_…)

Response · 200

routineobjectrequired

Scheduled agent execution: initial_events + a target (new_session per fire, or an existing session) bound to a cron schedule. Fires record routine runs.

▸ Show child attributes
idstring

rtn_… identifier

namestring
descriptionstring | null
metadataobject
targetobject

{type:"new_session", agent, environment_id?, vault_ids?} — a fresh session per fire (CMA parity) · {type:"session", session_id} — a turn into the existing session every fire (busy target skips with session_busy_error)

initial_eventsobject[]
scheduleobject | null

5-field POSIX cron + IANA timezone, wall-clock matching, minute granularity; null = manual-run only

budgetobject | null

Per-run cap (RFC-0080 shape): copied onto each new session (mode new_session) or granted as a per-fire delta allowance consumed+budget (mode session). Clearable.

statusenum<string>

"active" · "paused"

paused_reasonobject | null

{type:"manual"} | {type:"error", error:{type}} — non-null exactly when paused

archived_atstring | null
created_atstring
updated_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/routines/sess_cmtb7q2j/archive \
  -H "Authorization: Bearer ast_..."

Run now, outside the schedule; works while paused

With no body it is a manual run: trigger_context {type:"manual"}. With `input` or `idempotency_key` it is an API-triggered run: trigger_context {type:"api"}; the input is added to the run's first message under the label "Input for this run:", and a repeated idempotency_key on the same routine returns the first run instead of starting another. Neither emits routine_run webhooks.

Path parameters

idstringrequired

The routine id (rtn_…)

Body · application/json

inputstring

What this run should work on, such as an event's payload — max length 50000

idempotency_keystring

The caller's id for the event; a repeat returns the first run — max length 200

Response · 201

runobjectrequired

One fire attempt. Exactly one of session_id / error is non-null.

▸ Show child attributes
idstring

rrun_… identifier

routine_idstring
trigger_contextobject

{type:"schedule", scheduled_at} | {type:"manual"}

session_idstring | null
errorobject | null

{type, message}. Types: agent_archived_error · agent_not_found_error · session_archived_error · session_not_found_error · session_busy_error · environment_archived_error · environment_not_found_error · vault_not_found_error · insufficient_credits_error · rate_limited_error · run_rejected_error · unknown_error. Unrecoverable types auto-pause the routine; transient ones (credits, rate limit, busy) leave it active for the next occurrence. precheck_unchanged is not a failure: the scheduled fire was skipped because the routine's precheck URL returned the same content as at the last run; no session started, the routine stays active and no routine_run webhook is sent.

agentobject

Resolved agent reference at fire time

created_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/routines/sess_cmtb7q2j/run \
  -H "Authorization: Bearer ast_..."

Whether the routine has an inbound URL

`inbound_url` is null when there is none. The URL itself is never returned here, only the start of its secret.

Path parameters

idstringrequired

The routine id (rtn_…)

Response · 200

inbound_urlobject | nullrequired
▸ Show child attributes
routine_idstringrequired
prefixstringrequired

The start of the secret in the URL

created_atstringrequired
last_used_atstring | nullrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/routines/sess_cmtb7q2j/inbound-url' \
  -H "Authorization: Bearer ast_..."

Make the routine's inbound URL

Returns a URL that starts a run of this routine when posted to, with no API token: for a service that can only call a URL. It replaces any earlier one, which stops working at once. The URL carries its own secret and is returned only in this response.

Path parameters

idstringrequired

The routine id (rtn_…)

Response · 201

inbound_urlobjectrequired
▸ Show child attributes
routine_idstringrequired
prefixstringrequired

The start of the secret in the URL

created_atstringrequired
last_used_atstring | nullrequired
urlstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/routines/sess_cmtb7q2j/inbound-url \
  -H "Authorization: Bearer ast_..."

Remove the routine's inbound URL

Path parameters

idstringrequired

The routine id (rtn_…)

Response · 200

removedbooleanrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/routines/sess_cmtb7q2j/inbound-url \
  -H "Authorization: Bearer ast_..."

Whether the routine emails its result

Path parameters

idstringrequired

The routine id (rtn_…)

Response · 200

result_emailobjectrequired
▸ Show child attributes
enabledbooleanrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/routines/sess_cmtb7q2j/result-email' \
  -H "Authorization: Bearer ast_..."

Email the routine's creator the result of each run

When a run finishes, its creator gets one email with the last thing the agent said and a link to the run. It is sent whatever the person chose for finished-task emails, and every email carries a link that turns this routine's emails off. Only a routine whose target is `new_session` can have it (400 otherwise); an archived routine answers 409.

Path parameters

idstringrequired

The routine id (rtn_…)

Response · 200

result_emailobjectrequired
▸ Show child attributes
enabledbooleanrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PUT https://api.agentsky.dev/v1/routines/sess_cmtb7q2j/result-email \
  -H "Authorization: Bearer ast_..."

Stop emailing the routine's result

Path parameters

idstringrequired

The routine id (rtn_…)

Response · 200

result_emailobjectrequired
▸ Show child attributes
enabledbooleanrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/routines/sess_cmtb7q2j/result-email \
  -H "Authorization: Bearer ast_..."

The routine's precheck

`precheck` is null when there is none. It carries what the last check before a scheduled fire found.

Path parameters

idstringrequired

The routine id (rtn_…)

Response · 200

precheckobject | nullrequired
▸ Show child attributes
routine_idstringrequired
urlstringrequired
created_atstringrequired
last_checked_atstring | nullrequired

When the URL was last checked before a scheduled fire

last_resultstring | nullrequired

changed: the fire ran. unchanged: the fire was skipped. failed: the check could not be completed and the fire ran anyway. — "changed" · "unchanged" · "failed" · null

last_errorobject | nullrequired

{type, message} when last_result is failed. Types: address_not_allowed · dns_failed · redirect · http_status · too_large · timeout · network.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/routines/sess_cmtb7q2j/precheck' \
  -H "Authorization: Bearer ast_..."

Run scheduled fires only when a URL's content changed

Before each scheduled fire the platform GETs `url` and compares its content with the content at the last scheduled fire that ran. The same content skips the fire: it is recorded as a run with error.type `precheck_unchanged` and no session, and nothing is charged. New content, and the first check, run the fire. A check that cannot be completed (a redirect, a status outside 2xx, more than 256 KiB, more than 5 seconds, a host that is not on the public internet) never skips: the fire runs and the reason is kept in `last_error`. Manual runs, API runs and inbound-URL runs never consult it. The URL must be https on the default port, with no user name or password, and must not point at a private, loopback or link-local address (400 otherwise); it is fetched with no credentials. Setting a URL forgets what the earlier check remembered. An archived routine answers 409.

Path parameters

idstringrequired

The routine id (rtn_…)

Body · application/json

urlstringrequired

Response · 200

precheckobjectrequired
▸ Show child attributes
routine_idstringrequired
urlstringrequired
created_atstringrequired
last_checked_atstring | nullrequired

When the URL was last checked before a scheduled fire

last_resultstring | nullrequired

changed: the fire ran. unchanged: the fire was skipped. failed: the check could not be completed and the fire ran anyway. — "changed" · "unchanged" · "failed" · null

last_errorobject | nullrequired

{type, message} when last_result is failed. Types: address_not_allowed · dns_failed · redirect · http_status · too_large · timeout · network.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PUT https://api.agentsky.dev/v1/routines/sess_cmtb7q2j/precheck \
  -H "Authorization: Bearer ast_..."

Remove the routine's precheck

Path parameters

idstringrequired

The routine id (rtn_…)

Response · 200

removedbooleanrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/routines/sess_cmtb7q2j/precheck \
  -H "Authorization: Bearer ast_..."

The routine's chat trigger

`channel_trigger` is null when there is none. `available` says whether messages of this workspace's connected chats are offered to routines in this deployment; where it is false a trigger can be stored and will never match.

Path parameters

idstringrequired

The routine id (rtn_…)

Response · 200

channel_triggerobject | nullrequired
▸ Show child attributes
routine_idstringrequired
connection_idstringrequired
thread_idstring | nullrequired

The one conversation whose messages start a run; null for every conversation on the connection

text_prefixstring | nullrequired

What a message has to start with to start a run; null for every message

created_atstringrequired
last_matched_atstring | nullrequired
availablebooleanrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/routines/sess_cmtb7q2j/channel-trigger' \
  -H "Authorization: Bearer ast_..."

Start the routine from a message in a connected chat

A message starts a run when it is on the connection, in `thread_id` when one is given, and starts with `text_prefix` when one is given (leading mentions of the bot and letter case are ignored). Only messages from the person the routine belongs to start a run: the person who connected the chat, or a chat identity they linked to the same account. Anyone else's message is routed as if there were no trigger. The text after the prefix is added to the run's first message under the label "Input for this run:". The run is a task of the routine's creator (trigger_context {type:"channel", connection_id, thread_id}), and when its turn ends its last message is posted, once, in the conversation the message came from, with a link to the run. A message that started a run is sent nowhere else. One message starts at most one run; when several routines match, the one naming a thread and then the longest prefix wins. A paused or archived routine starts nothing, and more than 30 runs of one routine in a minute are dropped. Only the routine's creator can set the trigger (403 otherwise), on a connected chat of their own in this workspace (404 otherwise). `thread_id` must be a conversation on that connection and `text_prefix` 1 to 200 characters (400 otherwise). Setting a trigger replaces the earlier one. An archived routine answers 409.

Path parameters

idstringrequired

The routine id (rtn_…)

Body · application/json

connection_idstringrequired
thread_idstring
text_prefixstring

Response · 200

channel_triggerobjectrequired
▸ Show child attributes
routine_idstringrequired
connection_idstringrequired
thread_idstring | nullrequired

The one conversation whose messages start a run; null for every conversation on the connection

text_prefixstring | nullrequired

What a message has to start with to start a run; null for every message

created_atstringrequired
last_matched_atstring | nullrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PUT https://api.agentsky.dev/v1/routines/sess_cmtb7q2j/channel-trigger \
  -H "Authorization: Bearer ast_..."

Remove the routine's chat trigger

Path parameters

idstringrequired

The routine id (rtn_…)

Response · 200

removedbooleanrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/routines/sess_cmtb7q2j/channel-trigger \
  -H "Authorization: Bearer ast_..."

Where the routine's runs post their answer

`deliver_to` is null when the answers are posted nowhere.

Path parameters

idstringrequired

The routine id (rtn_…)

Response · 200

deliver_toobject | nullrequired
▸ Show child attributes
routine_idstringrequired
typeenum<string>required

"channel_thread"

connection_idstringrequired
thread_idstringrequired
created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/routines/sess_cmtb7q2j/deliver-to' \
  -H "Authorization: Bearer ast_..."

Post each run's answer to a conversation in a connected chat

When a turn of a run's session ends and the run is not waiting on its owner, the last thing the agent said (at most 3,000 characters) is posted in the conversation with a link to the run, once per run. `thread_id` defaults to the chat itself. A run a chat message started answers where that message was instead. Only the routine's creator can set this (403 otherwise), on a connected chat of their own in this workspace (404 otherwise). An archived routine answers 409.

Path parameters

idstringrequired

The routine id (rtn_…)

Body · application/json

typeenum<string>required

"channel_thread"

connection_idstringrequired
thread_idstring

Response · 200

deliver_toobjectrequired
▸ Show child attributes
routine_idstringrequired
typeenum<string>required

"channel_thread"

connection_idstringrequired
thread_idstringrequired
created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PUT https://api.agentsky.dev/v1/routines/sess_cmtb7q2j/deliver-to \
  -H "Authorization: Bearer ast_..."

Stop posting the routine's answers to a conversation

Path parameters

idstringrequired

The routine id (rtn_…)

Response · 200

removedbooleanrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/routines/sess_cmtb7q2j/deliver-to \
  -H "Authorization: Bearer ast_..."

Start a run through the routine's inbound URL

No Authorization header: the secret in the path is the credential. The request body, in any format and up to 50,000 characters, is added to the run's first message under the label "Input for this run:"; an empty body starts a run with no input. An `Idempotency-Key` header makes a repeated delivery return the first run. A paused routine answers 409 and starts nothing, an unknown URL or an archived routine answers 404, and more than 30 runs of one routine in a minute answers 429. The run is a task of the routine's owner (trigger_context {type:"api"}).

Path parameters

tokenstringrequired

The secret part of the inbound URL (rin_…)

Response · 202

runobjectrequired
▸ Show child attributes
idstringrequired
created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/routines/inbound/Yy5oaLAHSF5t96EAi9FiEk7uTjLMxNWDVHK8UPr1zK0 \
  -H "Authorization: Bearer ast_..."

List routine runs — every fire attempt

Query parameters

routinestring

Filter to one routine (rtn_…)

has_errorboolean

true = failed runs, false = runs with a session

trigger_typestring
created_at[gte]string

Also gt / lt / lte

cursorstring
limitinteger

Response · 200

itemsobject[]required
▸ Show child attributes
idstring

rrun_… identifier

routine_idstring
trigger_contextobject

{type:"schedule", scheduled_at} | {type:"manual"}

session_idstring | null
errorobject | null

{type, message}. Types: agent_archived_error · agent_not_found_error · session_archived_error · session_not_found_error · session_busy_error · environment_archived_error · environment_not_found_error · vault_not_found_error · insufficient_credits_error · rate_limited_error · run_rejected_error · unknown_error. Unrecoverable types auto-pause the routine; transient ones (credits, rate limit, busy) leave it active for the next occurrence. precheck_unchanged is not a failure: the scheduled fire was skipped because the routine's precheck URL returned the same content as at the last run; no session started, the routine stays active and no routine_run webhook is sent.

agentobject

Resolved agent reference at fire time

created_atstring
cursorstring | null
hasMoreboolean

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/routine-runs' \
  -H "Authorization: Bearer ast_..."

Routine run detail

Path parameters

idstringrequired

The run id (rrun_…)

Response · 200

runobjectrequired

One fire attempt. Exactly one of session_id / error is non-null.

▸ Show child attributes
idstring

rrun_… identifier

routine_idstring
trigger_contextobject

{type:"schedule", scheduled_at} | {type:"manual"}

session_idstring | null
errorobject | null

{type, message}. Types: agent_archived_error · agent_not_found_error · session_archived_error · session_not_found_error · session_busy_error · environment_archived_error · environment_not_found_error · vault_not_found_error · insufficient_credits_error · rate_limited_error · run_rejected_error · unknown_error. Unrecoverable types auto-pause the routine; transient ones (credits, rate limit, busy) leave it active for the next occurrence. precheck_unchanged is not a failure: the scheduled fire was skipped because the routine's precheck URL returned the same content as at the last run; no session started, the routine stays active and no routine_run webhook is sent.

agentobject

Resolved agent reference at fire time

created_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/routine-runs/sess_cmtb7q2j' \
  -H "Authorization: Bearer ast_..."

Model subscriptions

List connected model subscriptions — metadata only, never credentials

Query parameters

accountsstring

Include additional accounts; omitted preserves the legacy provider-only list

Response · 200

modelSubscriptionsobject[]required
▸ Show child attributes
providerenum<string>

"anthropic" · "openai" · "cursor" · "xai" · "meta"

accountIdstring

Additional account identifier; omitted for the legacy provider account

labelstring
statusenum<string>

"connected" · "needs_reconnect"

expiresAtstring | null
lastUsedAtstring | null
useForNewAgentsboolean
createdAtstring
agentsobject[]

Agents in this universe running on the subscription

▸ Show child attributes
idstring
agentIdstring | null
namestring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/model-subscriptions' \
  -H "Authorization: Bearer ast_..."

Add a separate subscription account

Body · application/json

credentialstringrequired

max length 100000

labelstring

max length 60

providerenum<string>required

"anthropic" · "openai" · "cursor" · "xai" · "meta"

Response · 201

modelSubscriptionobjectrequired

A connected consumer AI subscription (Claude Pro/Max, ChatGPT, Cursor, Grok or Muse plan) powering eligible agents at $0 model usage. The credential itself is write-only.

▸ Show child attributes
providerenum<string>

"anthropic" · "openai" · "cursor" · "xai" · "meta"

accountIdstring

Additional account identifier; omitted for the legacy provider account

labelstring
statusenum<string>

"connected" · "needs_reconnect"

expiresAtstring | null
lastUsedAtstring | null
useForNewAgentsboolean
createdAtstring
agentsobject[]

Agents in this universe running on the subscription

▸ Show child attributes
idstring
agentIdstring | null
namestring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/model-subscriptions \
  -H "Authorization: Bearer ast_..."

Connect or replace a subscription credential (write-only)

anthropic: the sk-ant-oat… token from `claude setup-token`. openai: the contents of ~/.codex/auth.json from `codex login`. cursor: a Cursor API key, or the sign-in file ~/.config/cursor/auth.json from `cursor-agent login`. xai: the sign-in file ~/.grok/auth.json from `grok login`. meta: the sign-in file ~/.config/muse/auth.json from `muse login`. Eligible agents can then run at $0 model usage; with useForNewAgents (default on), new eligible Claude, ChatGPT, Grok and Muse agents use it automatically. Cursor agents use it only when created or switched with modelBilling `account`.

Path parameters

providerstringrequired

anthropic = Claude subscription · openai = ChatGPT plan · cursor = Cursor plan · xai = Grok subscription · meta = Muse subscription

Query parameters

accountIdstring

Target an additional account; omitted targets the legacy provider account

Body · application/json

credentialstringrequired

max length 100000

labelstring

max length 60

Response · 200

modelSubscriptionobjectrequired

A connected consumer AI subscription (Claude Pro/Max, ChatGPT, Cursor, Grok or Muse plan) powering eligible agents at $0 model usage. The credential itself is write-only.

▸ Show child attributes
providerenum<string>

"anthropic" · "openai" · "cursor" · "xai" · "meta"

accountIdstring

Additional account identifier; omitted for the legacy provider account

labelstring
statusenum<string>

"connected" · "needs_reconnect"

expiresAtstring | null
lastUsedAtstring | null
useForNewAgentsboolean
createdAtstring
agentsobject[]

Agents in this universe running on the subscription

▸ Show child attributes
idstring
agentIdstring | null
namestring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PUT https://api.agentsky.dev/v1/model-subscriptions/provider \
  -H "Authorization: Bearer ast_..."

Update useForNewAgents / label

Path parameters

providerstringrequired

anthropic = Claude subscription · openai = ChatGPT plan · cursor = Cursor plan · xai = Grok subscription · meta = Muse subscription

Query parameters

accountIdstring

Target an additional account; omitted targets the legacy provider account

Body · application/json

useForNewAgentsboolean
labelstring

max length 60

Response · 200

modelSubscriptionobjectrequired

A connected consumer AI subscription (Claude Pro/Max, ChatGPT, Cursor, Grok or Muse plan) powering eligible agents at $0 model usage. The credential itself is write-only.

▸ Show child attributes
providerenum<string>

"anthropic" · "openai" · "cursor" · "xai" · "meta"

accountIdstring

Additional account identifier; omitted for the legacy provider account

labelstring
statusenum<string>

"connected" · "needs_reconnect"

expiresAtstring | null
lastUsedAtstring | null
useForNewAgentsboolean
createdAtstring
agentsobject[]

Agents in this universe running on the subscription

▸ Show child attributes
idstring
agentIdstring | null
namestring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PATCH https://api.agentsky.dev/v1/model-subscriptions/provider \
  -H "Authorization: Bearer ast_..."

Disconnect — affected agents keep their pointer and fail until reconnected or switched

Path parameters

providerstringrequired

anthropic = Claude subscription · openai = ChatGPT plan · cursor = Cursor plan · xai = Grok subscription · meta = Muse subscription

Query parameters

accountIdstring

Target an additional account; omitted targets the legacy provider account

Response · 200

affectedAgentsobject[]
▸ Show child attributes
idstring
agentIdstring | null
namestring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/model-subscriptions/provider \
  -H "Authorization: Bearer ast_..."

External accounts

List the workspace's accounts at outside vendors — never credentials

Vendor accounts connected here, and the workspace's model plans (managed under /model-subscriptions; their ids start with `plan:`). `vendors` lists the vendors an account can be connected for and whether connecting takes one `key` or the vendor's full `settings`. 404 where external accounts are not turned on for the workspace.

Response · 200

external_accountsobject[]required
▸ Show child attributes
idstringrequired
kindenum<string>required

"model_subscription" · "vendor_account"

vendorstringrequired
vendor_namestringrequired
labelstringrequired
statusenum<string>required

"active" · "needs_reconnect" · "exhausted"

planstring | nullrequired

The plan the vendor reported, when it reports one

agentsobject[]required

The agents that have run on it

▸ Show child attributes
idstringrequired
namestringrequired
last_used_atstring | nullrequired
created_atstringrequired
vendorsobject[]required
▸ Show child attributes
idstringrequired
namestringrequired
credentialenum<string>required

"key" · "settings"

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/external_accounts' \
  -H "Authorization: Bearer ast_..."

Connect a vendor account, or replace the credential of the one with the same vendor and label

The credential is write-only. Every task of the workspace waiting on this vendor's account (an open `connect_account` request) then continues. 422 `invalid_credential` when the vendor does not accept it; 503 `not_migrated` before the store exists. A vendor's own browser sign-in is not offered here.

Body · application/json

vendorstringrequired

A vendor id from `vendors`

labelstring

Defaults to the vendor's name

credentialstring | map<string, string>required

One key, or the vendor's account settings as upper-case names with text values

▸ Show child attributes
option 1string
option 2map<string, string>

Response · 201

external_accountobjectrequired
▸ Show child attributes
idstringrequired
kindenum<string>required

"model_subscription" · "vendor_account"

vendorstringrequired
vendor_namestringrequired
labelstringrequired
statusenum<string>required

"active" · "needs_reconnect" · "exhausted"

planstring | nullrequired

The plan the vendor reported, when it reports one

agentsobject[]required

The agents that have run on it

▸ Show child attributes
idstringrequired
namestringrequired
last_used_atstring | nullrequired
created_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/external_accounts \
  -H "Authorization: Bearer ast_..."

Disconnect an account; a later task that needs it asks for it again

Path parameters

idstringrequired

The account's id from the list

Response · 204

Disconnected

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/external_accounts/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."

Which agents and tasks ran on a vendor account

Path parameters

idstringrequired

The account's id from the list

Response · 200

usageobjectrequired
▸ Show child attributes
agentsobject[]required
▸ Show child attributes
idstringrequired
namestringrequired
tasksobject[]required
▸ Show child attributes
session_idstringrequired
agent_idstring | nullrequired
titlestring | nullrequired
first_used_atstringrequired
last_used_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/external_accounts/sess_cmtb7q2j/usage' \
  -H "Authorization: Bearer ast_..."

Connectors

Everything you share with a workspace, and the calls made through each

Response · 200

sharedobject[]required
▸ Show child attributes
connection_idstring
appstring
app_namestring
labelstring
workspaceobject
▸ Show child attributes
slugstring
namestring
shared_atstring
use_countinteger
usesobject[]
▸ Show child attributes
session_idstring
started_byobject
▸ Show child attributes
user_idstring
namestring
keyobject

The workspace key that started the session, when one did.

▸ Show child attributes
idstring
namestring
methodstring
hoststring
statusinteger
atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/shared-connections' \
  -H "Authorization: Bearer ast_..."

List the apps a person can connect

One page of the catalog. With neither `q` nor `cursor` the page leads with the widely used apps. Pages vary in size: continue with `next_cursor` until it is null. Answers 502 `catalog_error` when the catalog cannot be read.

Query parameters

qstring

Search by name

cursorstring

A page's `next_cursor`

Response · 200

appsobject[]required
▸ Show child attributes
slugstringrequired

The app's id, used wherever an app is named.

namestringrequired
descriptionstringrequired
next_cursorstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/connectors/apps' \
  -H "Authorization: Bearer ast_..."

List the caller's connections

The accounts the caller connected, by app and then oldest first. Connections belong to the person, not to a workspace. `credit` is what the caller has earned by connecting apps and the most they can earn that way.

Response · 200

connectionsobject[]required
▸ Show child attributes
idstringrequired
appstringrequired

The app's slug.

app_namestringrequired
labelstringrequired

The account's name at the app, usually an email address.

created_atstringrequired
creditobjectrequired
▸ Show child attributes
earned_usdnumberrequired
cap_usdnumberrequired
granted_appsstring[]required

Slugs of the apps that earned credit.

eligible_appsstring[]required

Slugs of the apps whose connection can earn credit.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/connectors/connections' \
  -H "Authorization: Bearer ast_..."

Start connecting an app

Answers the address the person's browser opens to sign in to the app and allow access. Afterwards the browser is sent to `success_url`, with `account_id` added to its query, or to `error_url`; the caller then records the result with `POST /connectors/connections/complete`. Both addresses must be https (http is accepted for localhost) and on one origin. Answers 400 `unknown_app` for an app that cannot be connected and 502 `connect_error` when the authorization cannot be started.

Body · application/json

appstringrequired

The app's slug.

success_urlstringrequired
error_urlstringrequired

Response · 200

urlstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/connectors/connections \
  -H "Authorization: Bearer ast_..."

Record a finished authorization

Call this when the browser arrives at `success_url`. The account is checked against the caller's own accounts at the app's provider, so an account somebody else authorized is refused; without `account_id` the caller's newest account for the app is used. Every task of the caller that was waiting on the app continues. Answers 404 when the caller has no such account and 502 `connect_error` when the provider cannot be read.

Body · application/json

appstringrequired
account_idstring

Response · 200

connectionobjectrequired
▸ Show child attributes
appstringrequired
app_namestringrequired
labelstringrequired
credit_grantobjectrequired

Credit given for this connection, when connecting apps earns credit. `status` is granted, already_granted, cap_reached or ineligible.

▸ Show child attributes
statusstringrequired
amount_usdnumber
earned_usdnumber
cap_usdnumber

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/connectors/connections/complete \
  -H "Authorization: Bearer ast_..."

Disconnect one of the caller's connections

Agents stop being able to use the account at once. Answers 404 for a connection that is not the caller's.

Path parameters

idstringrequired

Response · 204

Disconnected

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/connectors/connections/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."

List the repositories the caller's GitHub connection can reach

Most recently pushed first, at most 100. Answers 404 `github_not_connected` when the caller has no GitHub connection and 409 `github_reconnect_required` when none of their connections can be used.

Response · 200

reposobject[]required
▸ Show child attributes
full_namestringrequired
default_branchstringrequired
privatebooleanrequired
pushed_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/connectors/github/repos' \
  -H "Authorization: Bearer ast_..."

Make a link to connect the app a task is waiting on

For a task with an open `connect_app` request (see `GET /tasks/{id}`): a link the person the request is addressed to can open in any browser, without being signed in, to connect the app. Only that person can make it. The link can be used once, within fifteen minutes, and this is the only response that carries it; making another replaces one that was not used. When the app is connected the task continues by itself. Answers 404 when the task has no such open request, 403 `request_not_yours` when it is addressed to somebody else, and 503 `not_migrated` until the platform's link table is in place.

Body · application/json

task_idstringrequired

The task (sess_…)

request_idstringrequired

Response · 201

linkobjectrequired
▸ Show child attributes
urlstringrequired
expires_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/connectors/links \
  -H "Authorization: Bearer ast_..."

Continue from a connect link to the app's authorization

What the page's button sends. Uses the link up and redirects the browser to the app's sign-in. Refused exactly as the page is.

Path parameters

tokenstringrequired

Response · 303

Redirect to the app's authorization

Response · 404

The link cannot be used

Response · 429

Too many requests for this link

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/connectors/links/Yy5oaLAHSF5t96EAi9FiEk7uTjLMxNWDVHK8UPr1zK0 \
  -H "Authorization: Bearer ast_..."

Webhooks

The workspace's hook rules, in evaluation order

`enabled` says whether hook rules are turned on for the workspace; where they are not the list is empty and nothing is evaluated.

Response · 200

enabledbooleanrequired

Whether hook rules are turned on for the workspace.

can_editbooleanrequired

Whether the caller may replace the rules: they are turned on and the caller owns the workspace.

hook_rulesobject[]required
▸ Show child attributes
idstringrequired

hkr_…

pointenum<string>required

"session.start" · "tool.call" · "spend" · "turn.end"

matchmap<string, string>required
actionenum<string>required

"notify" · "block" · "require_approval"

webhook_idstring | nullrequired
enabledbooleanrequired
created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/hook_rules' \
  -H "Authorization: Bearer ast_..."
PUT/hook_ruleswrite

Replace the workspace's hook rules (owner only)

The body is the whole ordered list (at most 20); the order is the order of evaluation. A rule sent with the `id` of an existing rule keeps it. Points: `session.start` (a session is about to be created), `tool.call` (a capability call, a call to a connected app, or a tool the gateway runs for a session reached the platform), `spend` (a session's consumed cost reached `match.amount`, whole US cents; read when a turn ends and at a capability call, once per session), `turn.end` (a turn ended). Actions: `notify` delivers a signed event (`hook.session_start`, `hook.tool_call`, `hook.spend`, `hook.turn_end`) to `webhook_id`, one of the workspace's webhook endpoints, whatever events that endpoint subscribed to; never a URL. `block` at `session.start` refuses the session with 403 `blocked_by_hook_rule`; at `tool.call` it refuses the call with `capability_denied` (`reason: hook_rule`). `require_approval` at `tool.call` asks the session's owner exactly as an `ask` capability policy does, and an answer covers one call. `require_approval` at `session.start` creates the session waiting: it has no sandbox and takes no turn (409 `start_not_approved`), and its task carries an `approval` request for the person who created it, answered `confirm` or `decline` through `POST /tasks/{id}/requests/{request_id}/answer`. Approved, it starts with what it was created with; declined, it is archived, never runs and is charged nothing. A session started in a way that cannot wait (a helper, a product run, a handoff) is refused with 403 `blocked_by_hook_rule`. The most restrictive of the matching rules and the capability policies wins. Refused with 400 and the reason: `block` and `require_approval` at `spend` and at `turn.end`. `match` narrows a rule: `{agent_id}` at `session.start` and `turn.end`, `{capability_id}` or `{connector_app}` (the slug of a connected app), not both, at `tool.call`; omitted, the rule applies to all. A notify rule that cannot be delivered never affects the session. 403 `not_enabled` where hook rules are not turned on; 503 `not_migrated` before the tables exist.

Body · application/json

rulesobject[]required
▸ Show child attributes
idstring

An existing rule's id, to keep it.

pointenum<string>required

"session.start" · "tool.call" · "spend" · "turn.end"

actionenum<string>required

"notify" · "block" · "require_approval"

matchobject
▸ Show child attributes
agent_idstring
capability_idstring
connector_appstring

The slug of a connected app, e.g. "slack".

amountstring

Whole US cents, e.g. "125" for $1.25. Required at spend.

webhook_idstring

Required for notify (whep_…); not allowed otherwise.

enabledboolean

Default true.

Response · 200

enabledbooleanrequired

Whether hook rules are turned on for the workspace.

can_editbooleanrequired

Whether the caller may replace the rules: they are turned on and the caller owns the workspace.

hook_rulesobject[]required
▸ Show child attributes
idstringrequired

hkr_…

pointenum<string>required

"session.start" · "tool.call" · "spend" · "turn.end"

matchmap<string, string>required
actionenum<string>required

"notify" · "block" · "require_approval"

webhook_idstring | nullrequired
enabledbooleanrequired
created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PUT https://api.agentsky.dev/v1/hook_rules \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"rules":[{"point":"turn.end","action":"notify","webhook_id":"whep_cmtb2f0a8m9k7x51q4ez6r0d"},{"point":"tool.call","action":"require_approval","match":{"capability_id":"exa.search"}}]}'
GET/webhooksread

List webhook endpoints

Response · 200

webhooksobject[]required
▸ Show child attributes
idstring

whep_… identifier

urlstring
eventsstring[]
statusenum<string>

"active" · "disabled"

failure_countinteger
created_atstring
secretstring

whsec_… — present ONLY in the create response

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/webhooks' \
  -H "Authorization: Bearer ast_..."
POST/webhookswrite

Register a webhook endpoint — the whsec_ secret appears only in this response

The URL must be https, with no user name or password, and must not point at a private, loopback or link-local address (400 otherwise). At delivery the host is resolved again: a host that resolves to such an address, and a redirect, are failed attempts.

Body · application/json

urlstringrequired

max length 2048

eventsstring[]required

Response · 201

webhookobjectrequired

Outbound webhook endpoint. Deliveries carry x-asteroids-event/-delivery/-timestamp/-signature (v1=hmac-sha256(secret, "<ts>.<body>")), retry 3× (0s/5s/30s), and sustained failure disables (PATCH status:active re-enables). Payloads are thin {id, type, created_at, data:{type, id}} — fetch the resource, dedupe on the event id.

▸ Show child attributes
idstring

whep_… identifier

urlstring
eventsstring[]
statusenum<string>

"active" · "disabled"

failure_countinteger
created_atstring
secretstring

whsec_… — present ONLY in the create response

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/webhooks \
  -H "Authorization: Bearer ast_..." \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/hooks/agentsky","events":["routine_run.failed","routine.paused"]}'

Webhook endpoint detail

Path parameters

idstringrequired

The webhook endpoint id (whep_…)

Response · 200

webhookobjectrequired

Outbound webhook endpoint. Deliveries carry x-asteroids-event/-delivery/-timestamp/-signature (v1=hmac-sha256(secret, "<ts>.<body>")), retry 3× (0s/5s/30s), and sustained failure disables (PATCH status:active re-enables). Payloads are thin {id, type, created_at, data:{type, id}} — fetch the resource, dedupe on the event id.

▸ Show child attributes
idstring

whep_… identifier

urlstring
eventsstring[]
statusenum<string>

"active" · "disabled"

failure_countinteger
created_atstring
secretstring

whsec_… — present ONLY in the create response

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/webhooks/sess_cmtb7q2j' \
  -H "Authorization: Bearer ast_..."
PATCH/webhooks/{id}write

Update url/events, or status:active to re-enable a disabled endpoint

Path parameters

idstringrequired

The webhook endpoint id (whep_…)

Body · application/json

urlstring

max length 2048

eventsstring[]
statusenum<string>

"active" · "disabled"

Response · 200

webhookobjectrequired

Outbound webhook endpoint. Deliveries carry x-asteroids-event/-delivery/-timestamp/-signature (v1=hmac-sha256(secret, "<ts>.<body>")), retry 3× (0s/5s/30s), and sustained failure disables (PATCH status:active re-enables). Payloads are thin {id, type, created_at, data:{type, id}} — fetch the resource, dedupe on the event id.

▸ Show child attributes
idstring

whep_… identifier

urlstring
eventsstring[]
statusenum<string>

"active" · "disabled"

failure_countinteger
created_atstring
secretstring

whsec_… — present ONLY in the create response

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PATCH https://api.agentsky.dev/v1/webhooks/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."
DELETE/webhooks/{id}write

Delete a webhook endpoint

Path parameters

idstringrequired

The webhook endpoint id (whep_…)

Response · 200

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/webhooks/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."

Apps with sign-in

The apps the caller registered

Answers 404 until apps with sign-in are open on the platform.

Response · 200

oauth_clientsobject[]required
▸ Show child attributes
idstringrequired

The client id the app presents when it sends a person to sign in.

namestringrequired

Shown to people when they are asked to allow the app. — max length 80

redirect_urisstring[]required

Where the app may send people back after they decide. Matched exactly: no wildcards, no fragments. Must be https; `http://localhost` and `http://127.0.0.1` are accepted while the app is not reviewed.

scopesenum<string>[]required

What the app may ask a person for. `read` sees their tasks, agents and sessions; `write` also starts and changes them. — "read" · "write"

test_usersstring[]required

People besides you who may use the app before it is reviewed, by the email address of their account.

review_statusenum<string>required

An unreviewed app works only for its owner and its test users, and people are told it has not been reviewed. — "unreviewed" · "approved"

created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/oauth_clients' \
  -H "Authorization: Bearer ast_..."

Register an app that signs people in

The app signs a person in with the authorization-code flow and PKCE (S256) at the sign-in service, asking for `openid` plus the scopes registered here and naming this API as the `resource`. The access token it receives is sent as `Authorization: Bearer` to this API. It acts as that person in one workspace: a person who belongs to several chooses it when they allow the app, and the app is refused everywhere else (`universe_mismatch` for another workspace named in `X-Universe`, `not_found` for a session outside it). It holds only the scopes they allowed and reaches tasks, sessions, agents, the catalog and whoami. On a session in that workspace it can also send messages and interrupts (`POST /sessions/{id}/events`, `POST /sessions/{id}/interrupt`, both `write`) and follow the live stream (`GET /sessions/{id}/stream`, `read`). It stops working as soon as the person removes the app from their account page: the next request is refused, and a stream that is open ends within a few seconds. To move the app to another workspace the person removes its access and allows it again. A new app is unreviewed. A caller may register up to 10 apps. Answers 404 until apps with sign-in are open on the platform, and 503 `not_migrated` until its tables are in place.

Body · application/json

namestringrequired

Shown to people when they are asked to allow the app. — max length 80

redirect_urisstring[]required

Where the app may send people back after they decide. Matched exactly: no wildcards, no fragments. Must be https; `http://localhost` and `http://127.0.0.1` are accepted while the app is not reviewed.

scopesenum<string>[]required

What the app may ask a person for. `read` sees their tasks, agents and sessions; `write` also starts and changes them. — "read" · "write"

test_usersstring[]

People besides you who may use the app before it is reviewed, by the email address of their account.

Response · 201

oauth_clientobjectrequired

An app registered to sign people in with their account.

▸ Show child attributes
idstringrequired

The client id the app presents when it sends a person to sign in.

namestringrequired

Shown to people when they are asked to allow the app. — max length 80

redirect_urisstring[]required

Where the app may send people back after they decide. Matched exactly: no wildcards, no fragments. Must be https; `http://localhost` and `http://127.0.0.1` are accepted while the app is not reviewed.

scopesenum<string>[]required

What the app may ask a person for. `read` sees their tasks, agents and sessions; `write` also starts and changes them. — "read" · "write"

test_usersstring[]required

People besides you who may use the app before it is reviewed, by the email address of their account.

review_statusenum<string>required

An unreviewed app works only for its owner and its test users, and people are told it has not been reviewed. — "unreviewed" · "approved"

created_atstringrequired
updated_atstringrequired
client_secretstringrequired

Shown in this response only. Keep it on your server.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/oauth_clients \
  -H "Authorization: Bearer ast_..."

One of the caller's apps

Path parameters

idstringrequired

The app's client id.

Response · 200

oauth_clientobjectrequired

An app registered to sign people in with their account.

▸ Show child attributes
idstringrequired

The client id the app presents when it sends a person to sign in.

namestringrequired

Shown to people when they are asked to allow the app. — max length 80

redirect_urisstring[]required

Where the app may send people back after they decide. Matched exactly: no wildcards, no fragments. Must be https; `http://localhost` and `http://127.0.0.1` are accepted while the app is not reviewed.

scopesenum<string>[]required

What the app may ask a person for. `read` sees their tasks, agents and sessions; `write` also starts and changes them. — "read" · "write"

test_usersstring[]required

People besides you who may use the app before it is reviewed, by the email address of their account.

review_statusenum<string>required

An unreviewed app works only for its owner and its test users, and people are told it has not been reviewed. — "unreviewed" · "approved"

created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/oauth_clients/sess_cmtb7q2j' \
  -H "Authorization: Bearer ast_..."

Change one of the caller's apps

Send only the fields to change. Changing the name, the redirect URLs or the scopes of an approved app returns it to unreviewed; changing its test users does not.

Path parameters

idstringrequired

The app's client id.

Body · application/json

namestring

Shown to people when they are asked to allow the app. — max length 80

redirect_urisstring[]

Where the app may send people back after they decide. Matched exactly: no wildcards, no fragments. Must be https; `http://localhost` and `http://127.0.0.1` are accepted while the app is not reviewed.

scopesenum<string>[]

What the app may ask a person for. `read` sees their tasks, agents and sessions; `write` also starts and changes them. — "read" · "write"

test_usersstring[]

People besides you who may use the app before it is reviewed, by the email address of their account.

Response · 200

oauth_clientobjectrequired

An app registered to sign people in with their account.

▸ Show child attributes
idstringrequired

The client id the app presents when it sends a person to sign in.

namestringrequired

Shown to people when they are asked to allow the app. — max length 80

redirect_urisstring[]required

Where the app may send people back after they decide. Matched exactly: no wildcards, no fragments. Must be https; `http://localhost` and `http://127.0.0.1` are accepted while the app is not reviewed.

scopesenum<string>[]required

What the app may ask a person for. `read` sees their tasks, agents and sessions; `write` also starts and changes them. — "read" · "write"

test_usersstring[]required

People besides you who may use the app before it is reviewed, by the email address of their account.

review_statusenum<string>required

An unreviewed app works only for its owner and its test users, and people are told it has not been reviewed. — "unreviewed" · "approved"

created_atstringrequired
updated_atstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PATCH https://api.agentsky.dev/v1/oauth_clients/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."

Delete one of the caller's apps

Everyone's access through the app ends with it.

Path parameters

idstringrequired

The app's client id.

Response · 200

Deleted

deletedboolean

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/oauth_clients/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."

Replace an app's client secret

The previous secret stops working at once. People who already allowed the app keep their access.

Path parameters

idstringrequired

The app's client id.

Response · 200

oauth_clientobjectrequired

An app registered to sign people in with their account.

▸ Show child attributes
idstringrequired

The client id the app presents when it sends a person to sign in.

namestringrequired

Shown to people when they are asked to allow the app. — max length 80

redirect_urisstring[]required

Where the app may send people back after they decide. Matched exactly: no wildcards, no fragments. Must be https; `http://localhost` and `http://127.0.0.1` are accepted while the app is not reviewed.

scopesenum<string>[]required

What the app may ask a person for. `read` sees their tasks, agents and sessions; `write` also starts and changes them. — "read" · "write"

test_usersstring[]required

People besides you who may use the app before it is reviewed, by the email address of their account.

review_statusenum<string>required

An unreviewed app works only for its owner and its test users, and people are told it has not been reviewed. — "unreviewed" · "approved"

created_atstringrequired
updated_atstringrequired
client_secretstringrequired

Shown in this response only. Keep it on your server.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/oauth_clients/sess_cmtb7q2j/rotate_secret \
  -H "Authorization: Bearer ast_..."

Channels

List BYO channel apps — credentials masked

Response · 200

appsobject[]required
▸ Show child attributes
verification_errorstring

Non-secret explanation when X verification remains pending

verification_retryableboolean

Present for pending X verification. False means the saved refresh attempt cannot be replayed; replace credentials with a fresh OAuth grant.

idstring
platformenum<string>

"telegram" · "slack" · "discord" · "whatsapp" · "imessage" · "email" · "teams" · "x" · "lark" · "buzz" · "gchat" · "line"

labelstring
statusstring
credential_keysstring[]

Key names only — values are write-only

created_atstring
setupmap<string, string>

Steps the platform cannot automate (per-app webhook_url / verify_token / events_url / invite_url)

registered_platformsstring[]required

Platforms with a registered-app writer enabled in this service deployment. Does not prove customer credentials or provider delivery.

shared_platformsstring[]required

Shared bot choices supported by app selection in this deployment; does not inventory the legacy shared channel flows.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/channels/apps' \
  -H "Authorization: Bearer ast_..."

Register your own bot/number as a channel app

Credentials are proven against the platform where an API exists, stored encrypted, and write-only from then on. The response's setup object carries the steps the platform cannot automate (webhook URLs to paste, invite links).

Body · application/json

platformenum<string>required

"telegram" · "slack" · "discord" · "whatsapp" · "imessage" · "email" · "teams" · "x" · "lark" · "buzz" · "gchat" · "line"

labelstringrequired

max length 120

credentialsmap<string, string>required

Write-only. Required keys per platform — telegram: bot_token · discord: bot_token · slack: bot_token, signing_secret · whatsapp: access_token, phone_number_id, app_secret · email (requires EMAIL_CHANNEL_ENABLED): region, access_key, secret_key, from_address, sns_topic_arn; optional from_name, inbound_address, allow_subaddressing, reply_to_sender_only (string true/false); optional s3_bucket, s3_prefix (nonempty, ends /), s3_bucket_owner (12 digits), all three together for S3 receiving with the same region/key pair · teams (when enabled; app creation and credential rotation return 501 coming_soon when disabled): app_id (Azure Application client ID), app_password (client secret); optional app_tenant_id (Directory ID for single-tenant bots, omit for multi-tenant). Credentials are validated against Azure AD on creation. The API returns a webhook_url to paste into Azure Bot Configuration → Messaging Endpoint. Connection returns PENDING and a LINK code to send to the bot. Each conversation can bind to its own session. · imessage (coming soon — answers 501 coming_soon today): api_key, phone_number, webhook_secret · x: consumer_secret + either user_access_token (Group A, OAuth 2.0 Bearer) or client_id + refresh_token (Group B, OAuth 2.0 managed refresh). Exactly one group must be supplied. · lark: app_id, app_secret, verification_token (optional encrypt_key, domain: lark|feishu, app_mode: self-built|store, app_ticket for migration) · buzz: private_key, auth_tag · gchat: service_account_json, project_number · line: channel_access_token, channel_secret (requires LINE_CHANNEL_ENABLED; setup returns manual webhook instructions)

Response · 201

verification_errorstring

Non-secret explanation when X verification remains pending

verification_retryableboolean

Present for pending X verification. False means the saved refresh attempt cannot be replayed; replace credentials with a fresh OAuth grant.

idstring
platformenum<string>

"telegram" · "slack" · "discord" · "whatsapp" · "imessage" · "email" · "teams" · "x" · "lark" · "buzz" · "gchat" · "line"

labelstring
statusstring
credential_keysstring[]

Key names only — values are write-only

created_atstring
setupmap<string, string>

Steps the platform cannot automate (per-app webhook_url / verify_token / events_url / invite_url)

Response · 202

Verification pending

verification_errorstring

Non-secret explanation when X verification remains pending

verification_retryableboolean

Present for pending X verification. False means the saved refresh attempt cannot be replayed; replace credentials with a fresh OAuth grant.

idstring
platformenum<string>

"telegram" · "slack" · "discord" · "whatsapp" · "imessage" · "email" · "teams" · "x" · "lark" · "buzz" · "gchat" · "line"

labelstring
statusstring
credential_keysstring[]

Key names only — values are write-only

created_atstring
setupmap<string, string>

Steps the platform cannot automate (per-app webhook_url / verify_token / events_url / invite_url)

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/channels/apps \
  -H "Authorization: Bearer ast_..."

Channel app detail — credentials masked

Path parameters

idstringrequired

The channel app id

Response · 200

verification_errorstring

Non-secret explanation when X verification remains pending

verification_retryableboolean

Present for pending X verification. False means the saved refresh attempt cannot be replayed; replace credentials with a fresh OAuth grant.

idstring
platformenum<string>

"telegram" · "slack" · "discord" · "whatsapp" · "imessage" · "email" · "teams" · "x" · "lark" · "buzz" · "gchat" · "line"

labelstring
statusstring
credential_keysstring[]

Key names only — values are write-only

created_atstring
setupmap<string, string>

Steps the platform cannot automate (per-app webhook_url / verify_token / events_url / invite_url)

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/channels/apps/sess_cmtb7q2j' \
  -H "Authorization: Bearer ast_..."

Rename or rotate credentials (rotation re-runs registration)

Path parameters

idstringrequired

The channel app id

Body · application/json

retry_registrationboolean

Retry saved X verification without resubmitting credentials; mutually exclusive with credentials

labelstring

max length 120

credentialsmap<string, string>

Full replacement bag; rotation re-runs the platform registration

Response · 200

verification_errorstring

Non-secret explanation when X verification remains pending

verification_retryableboolean

Present for pending X verification. False means the saved refresh attempt cannot be replayed; replace credentials with a fresh OAuth grant.

idstring
platformenum<string>

"telegram" · "slack" · "discord" · "whatsapp" · "imessage" · "email" · "teams" · "x" · "lark" · "buzz" · "gchat" · "line"

labelstring
statusstring
credential_keysstring[]

Key names only — values are write-only

created_atstring
setupmap<string, string>

Steps the platform cannot automate (per-app webhook_url / verify_token / events_url / invite_url)

Response · 202

Verification pending

verification_errorstring

Non-secret explanation when X verification remains pending

verification_retryableboolean

Present for pending X verification. False means the saved refresh attempt cannot be replayed; replace credentials with a fresh OAuth grant.

idstring
platformenum<string>

"telegram" · "slack" · "discord" · "whatsapp" · "imessage" · "email" · "teams" · "x" · "lark" · "buzz" · "gchat" · "line"

labelstring
statusstring
credential_keysstring[]

Key names only — values are write-only

created_atstring
setupmap<string, string>

Steps the platform cannot automate (per-app webhook_url / verify_token / events_url / invite_url)

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PATCH https://api.agentsky.dev/v1/channels/apps/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."

Delete the channel app

Path parameters

idstringrequired

The channel app id

Response · 204

Deleted

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/channels/apps/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."

List connections with their bound session

Response · 200

connectionsobject[]required
▸ Show child attributes
idstring
platformstring
channel_idstring
thread_idstring

Present after administrative adoption; the existing app-scoped reply address

labelstring
statusenum<string>

"PENDING" · "CONNECTED" · "DISCONNECTED"

bound_sessionobject
▸ Show child attributes
idstring
labelstring
created_atstring
connectobject

PENDING only: open url; X and webhook-based Slack/Discord use a hosted page, phone-based flows include phone + code, and Lark includes app_id and a code to send to the bot.

▸ Show child attributes
urlstring
phonestring
app_idstring

Lark app ID used to open the bot

codestring
expires_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/channels/connections' \
  -H "Authorization: Bearer ast_..."

Connect a surface — link-flow platforms return a pending connect ceremony

telegram/imessage/whatsapp/x/lark/gchat mint a connect ceremony (hosted page or deep link + code) the end user claims in-platform. Slack/Discord with destination.webhook return a LINK ceremony; other Slack/Discord flows create a channel synchronously. Pass app for BYO; callback_url (link flows) redirects the hosted connect page to you after the claim.

Body · application/json

platformenum<string>required

"telegram" · "slack" · "discord" · "whatsapp" · "imessage" · "email" · "teams" · "x" · "lark" · "buzz" · "gchat" · "line" · "loopback"

labelstring

max length 120

metadataobject

Echoed on channel.connected and the callback redirect

destinationobject

Pre-bind to exactly one owned session or webhook endpoint when the surface is claimed

▸ Show child attributes
sessionstring
webhookstring
appstring

BYO ChannelApp id — the connect ceremony runs on your bot/number

adoptobject

Admin-scope migration of the app owner's previously verified conversation. Requires an owned active app, an app-scoped thread ID and destination. The caller attests the existing sender binding and consent; no LINK ceremony or provider message is performed. Exact replay reuses the connection; changed sender, metadata, destination or a disconnected record returns 409. Cannot combine with callback_url or invite_user.

▸ Show child attributes
thread_idstringrequired

max length 8192

author_idstringrequired

max length 1024

tenant_keystring

Required only for Lark Store adoption; provider app and chat state must confirm this organization. — max length 256

invite_userstring

Slack only: user id to invite into the created channel

callback_urlstring

Link-flow platforms only: the hosted connect page redirects here after the claim with connection_id, status, and metadata query params

Response · 201

idstring
platformstring
channel_idstring
thread_idstring

Present after administrative adoption; the existing app-scoped reply address

labelstring
statusenum<string>

"PENDING" · "CONNECTED" · "DISCONNECTED"

bound_sessionobject
▸ Show child attributes
idstring
labelstring
created_atstring
connectobject

PENDING only: open url; X and webhook-based Slack/Discord use a hosted page, phone-based flows include phone + code, and Lark includes app_id and a code to send to the bot.

▸ Show child attributes
urlstring
phonestring
app_idstring

Lark app ID used to open the bot

codestring
expires_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/channels/connections \
  -H "Authorization: Bearer ast_..."

Read your connection claim's current status

Look up a link-flow ceremony by its 32-character token, scoped to the authenticated owner and universe. Reconnecting an existing conversation can replace the pending connection ID; this returns the effective ID. It does not confirm downstream webhook processing. Responses are not cached. Normal API rate limits apply; back off on 429.

Query parameters

tokenstringrequired

The token after LINK: or in the Telegram start parameter

Response · 200

statusenum<string>required

"pending" · "connected" · "expired" · "disconnected"

connection_idstringrequired
platformstringrequired
metadataobjectrequired

The caller's original connection metadata

expires_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/channels/connections/status?token=Yy5oaLAHSF5t96EAi9FiEk7uTjLMxNWDVHK8UPr1zK0' \
  -H "Authorization: Bearer ast_..."

Disconnect the surface

Path parameters

idstringrequired

The connection id

Response · 204

Disconnected

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/channels/connections/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."

Set where the surface routes — a session or your webhook endpoint (single active binding)

Path parameters

idstringrequired

The connection id

Body · application/json

destinationobjectrequired

Exactly one of webhook (endpoint id) or session (session id)

▸ Show child attributes
webhookstring
sessionstring

Response · 200

connection_idstring
binding_idstring
sessionstring
webhookstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PUT https://api.agentsky.dev/v1/channels/connections/sess_cmtb7q2j/binding \
  -H "Authorization: Bearer ast_..."

Declared platform capabilities — branch on these instead of guessing

Path parameters

idstringrequired

The connection id

Response · 200

connection_idstring
platformstring
capabilitiesmap<string, boolean>

threads · reactions · markers · proactive · markdown · modals · ephemeral · streaming · files

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/channels/connections/sess_cmtb7q2j/capabilities' \
  -H "Authorization: Bearer ast_..."

Inject a message into a loopback connection

Local development without a real platform: the message goes through the same webhook pipeline a Telegram or Slack event would. Only loopback connections accept it — anything else answers 400.

Path parameters

idstringrequired

The connection id

Body · application/json

textstringrequired
threadstring

Thread key within the connection; default "main"

idstring

Message id to attribute it to; default a generated one

authorobject
▸ Show child attributes
user_idstringrequired
user_namestring
mentionboolean

Whether it reads as a mention of the bot

Response · 202

thread_idstringrequired

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/channels/connections/sess_cmtb7q2j/dev/inbound \
  -H "Authorization: Bearer ast_..."

Everything the agent has sent on a loopback connection

The counterpart to dev/inbound: what a real platform would have received.

Path parameters

idstringrequired

The connection id

Response · 200

outboundobject[]required

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/channels/connections/sess_cmtb7q2j/dev/outbound' \
  -H "Authorization: Bearer ast_..."

List bindings, optionally by connection

Query parameters

connection_idstring

Response · 200

bindingsobject[]required
▸ Show child attributes
idstring
connection_idstring
thread_idstring
destinationobject

Exactly one of webhook (endpoint id) or session (session id)

▸ Show child attributes
webhookstring
sessionstring
is_defaultboolean
statusstring
route_keystring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/channels/bindings' \
  -H "Authorization: Bearer ast_..."

Route one thread of a connection to a session or your webhook

Body · application/json

connection_idstringrequired
thread_idstringrequired

The one thread this rule routes. Connection-level routing is a single slot — set it via PUT /connections/{id}/binding

destinationobjectrequired

Exactly one of webhook (endpoint id) or session (session id)

▸ Show child attributes
webhookstring
sessionstring
route_keystring

max length 60

Response · 201

idstring
connection_idstring
thread_idstring
destinationobject

Exactly one of webhook (endpoint id) or session (session id)

▸ Show child attributes
webhookstring
sessionstring
is_defaultboolean
statusstring
route_keystring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/channels/bindings \
  -H "Authorization: Bearer ast_..."

Delete the binding

Path parameters

idstringrequired

The binding id

Response · 204

Deleted

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/channels/bindings/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."

List the chat identities linked to your account

Response · 200

identitiesobject[]required
▸ Show child attributes
idstring
platformenum<string>

"telegram" · "slack" · "discord" · "whatsapp" · "imessage" · "email" · "teams" · "x" · "lark" · "buzz" · "gchat" · "line"

external_user_idstring

The person's id on that platform

display_namestring
linked_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/channels/identities' \
  -H "Authorization: Bearer ast_..."

Complete a link offered to a person in a connected chat, as the caller

From then on that person's messages in conversations on the same bot or workspace run as the caller's account. The token is the one posted in the chat; it works once and for 30 minutes. 404 when it was used or has expired, 503 `not_migrated` until the platform's tables are in place.

Body · application/json

tokenstringrequired

Response · 201

Linked

identityobjectrequired

A person in a connected chat, linked to the account their messages there run as.

▸ Show child attributes
idstring
platformenum<string>

"telegram" · "slack" · "discord" · "whatsapp" · "imessage" · "email" · "teams" · "x" · "lark" · "buzz" · "gchat" · "line"

external_user_idstring

The person's id on that platform

display_namestring
linked_atstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/channels/identities \
  -H "Authorization: Bearer ast_..."

Unlink a chat identity; that person's messages stop running as you

Path parameters

idstringrequired

The identity id

Response · 204

Unlinked

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/channels/identities/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."

List webhook endpoints

Response · 200

webhooksobject[]required
▸ Show child attributes
idstring
urlstring
eventsstring[]
statusstring
secretstring

whsec_ HMAC secret — returned on create only

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/channels/webhooks' \
  -H "Authorization: Bearer ast_..."

Create a webhook endpoint — HMAC-signed deliveries, 0/5/30s retries

Deliveries carry X-Asteroids-{Event,Delivery,Timestamp,Signature}; ~20 consecutive failures disable the endpoint. Consumers must be idempotent by delivery id. The message.received payload is described by ChannelMessageReceived, including its optional service-owned claim.

Body · application/json

urlstringrequired

https (http allowed for localhost only)

eventsstring[]

Default ["message.received"]

Response · 201

idstring
urlstring
eventsstring[]
statusstring
secretstring

whsec_ HMAC secret — returned on create only

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/channels/webhooks \
  -H "Authorization: Bearer ast_..."

Re-enable a disabled endpoint (resets failures, keeps the secret) and/or re-pick events

Path parameters

idstringrequired

The webhook endpoint id

Body · application/json

statusenum<string>

"ACTIVE"

eventsstring[]

Response · 200

idstring
urlstring
eventsstring[]
statusstring
secretstring

whsec_ HMAC secret — returned on create only

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PATCH https://api.agentsky.dev/v1/channels/webhooks/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."

Delete the webhook endpoint

Path parameters

idstringrequired

The webhook endpoint id

Response · 204

Deleted

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/channels/webhooks/sess_cmtb7q2j \
  -H "Authorization: Bearer ast_..."

Post into a thread — markdown renders natively per platform

File parts use owned Files API assets and require capabilities.files. Long replies are split into complete platform-sized messages. Supply idempotency_key to avoid duplicate sends on retry; an uncertain or partial send must be inspected before choosing a new key. done and failed are mutually exclusive.

Path parameters

idstringrequired

The thread id (from message.received or channel events)

Body · application/json

partsobject[]required
▸ Show child attributes
type: "file"object
▸ Show child attributes
type"file"required
file_idstringrequired

A visible, unexpired Files API upload or session output; requires capabilities.files. — pattern ^file_[A-Za-z0-9_-]{1,128}$

type: "text"object
▸ Show child attributes
type"text"required
textstringrequired
type: "markdown"object
▸ Show child attributes
type"markdown"required
textstringrequired
type: "raw"object
▸ Show child attributes
type"raw"required
platformstringrequired
payloadstringrequired

Platform-native payload, JSON-encoded

emailobject

SES-only headers. The authorized thread owns the recipient; this object cannot change To.

▸ Show child attributes
subjectstring

max length 200 — pattern ^[^\r\n]+$

reply_tostring
idempotency_keystring

Durable replay key scoped to the persisted owner, connection and thread, independent of bearer token scope. Same-content replays return the accepted receipt even after disconnect; changed content or an unconfirmed send returns 409 without resending. — max length 200

doneboolean

Resolves the working marker as successful; cannot be true with failed

failedboolean

Resolves the working marker as failed; cannot be true with done

Response · 201

message_idstring
thread_idstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/channels/threads/sess_cmtb7q2j/messages \
  -H "Authorization: Bearer ast_..."

Add a reaction (platform-neutral emoji names)

Path parameters

idstringrequired

The thread id

midstringrequired
emojistringrequired

Response · 204

Reacted

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PUT https://api.agentsky.dev/v1/channels/threads/sess_cmtb7q2j/messages/mid/reactions/emoji \
  -H "Authorization: Bearer ast_..."

Remove a reaction

Path parameters

idstringrequired

The thread id

midstringrequired
emojistringrequired

Response · 204

Removed

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X DELETE https://api.agentsky.dev/v1/channels/threads/sess_cmtb7q2j/messages/mid/reactions/emoji \
  -H "Authorization: Bearer ast_..."

Proactive fan-out: post to every thread bound to a destination

Body · application/json

destinationobjectrequired

Exactly one of webhook (endpoint id) or session (session id)

▸ Show child attributes
webhookstring
sessionstring
partsobject[]required
▸ Show child attributes
type: "file"object
▸ Show child attributes
type"file"required
file_idstringrequired

A visible, unexpired Files API upload or session output; requires capabilities.files. — pattern ^file_[A-Za-z0-9_-]{1,128}$

type: "text"object
▸ Show child attributes
type"text"required
textstringrequired
type: "markdown"object
▸ Show child attributes
type"markdown"required
textstringrequired
type: "raw"object
▸ Show child attributes
type"raw"required
platformstringrequired
payloadstringrequired

Platform-native payload, JSON-encoded

doneboolean

Resolves each working marker as successful; cannot be true with failed

failedboolean

Resolves each working marker as failed; cannot be true with done

Response · 200

OK — per-thread results

resultsobject[]
▸ Show child attributes
thread_idstring
statusstring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/channels/deliveries \
  -H "Authorization: Bearer ast_..."

SSE mirror of your webhook events — for local development

Response · 200

SSE stream

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -N 'https://api.agentsky.dev/v1/channels/events/stream' \
  -H "Authorization: Bearer ast_..."

White label

The onboarding instruction for this account

Markdown by default (the reader is a language model); `?format=json` returns the same state as fields. It describes the step this account is actually on, so an agent can fetch it, make the call it names, and fetch it again until it reports the account is live. This is the entry point for white-label onboarding — there is no form.

Query parameters

formatstring

Response · 200

The instruction

stateenum<string>

"unapplied" · "waiting" · "rejected" · "setting_up" · "live" · "suspended"

next_actionstring

The one call that advances onboarding; null when nothing does.

outstandingstring[]
partnerany

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/partner/onboarding' \
  -H "Authorization: Bearer ast_..."
GET/partnerread

Where this account stands

Response · 200

stateenum<string>

"unapplied" · "waiting" · "rejected" · "setting_up" · "live" · "suspended"

next_actionstring

The one call that advances onboarding; null when nothing does.

outstandingstring[]
partnerany

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/partner' \
  -H "Authorization: Bearer ast_..."

Ask to become a white-label partner

A request, not a switch: a person here reads it and decides, and no call advances it in the meantime. One open application per account.

Body · application/json

productNamestringrequired

What this partner's customers will call the product.

intendedHoststringrequired

Advisory at this stage; hostnames are claimed later.

notesstring

Response · 201

Accepted for a decision

application_idstring
statestring
next_actionstring
messagestring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/partner/application \
  -H "Authorization: Bearer ast_..."

Claim the prefix this partner's API keys carry

The visible half of every key their customers hold: `acme_…` rather than `ast_…`. Changeable only while no keys exist under it — after that, changing it would strand them.

Body · application/json

prefixstringrequired

2–8 lowercase letters or digits, starting with a letter.

Response · 200

Claimed

partnerobject
▸ Show child attributes
idstring
slugstring
namestring
statusenum<string>

"pending" · "active" · "suspended"

key_prefixstring

Null until claimed.

brandmap<string, string>
brand_missingstring[]

Brand fields still falling back to ours.

rate_limit_per_mininteger
hostname_quotainteger
hostnamesobject[]
▸ Show child attributes
hostnamestring
planeenum<string>

"API" · "GATEWAY" · "APP" · "ACCOUNTS" · "STUDIO_POOL" · "STUDIO_WILDCARD"

ssl_statusstring
servingboolean

Only a serving hostname counts toward going live.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/partner/key-prefix \
  -H "Authorization: Bearer ast_..."

Claim a hostname for one plane

The response leads with the CNAME a person must add at the partner's own registrar — the one step of onboarding nobody on our side can do. Adding the row is not ownership: nothing routes until domain-control validation issues a certificate.

Body · application/json

hostnamestringrequired
planeenum<string>required

"API" · "GATEWAY" · "APP" · "ACCOUNTS" · "STUDIO_POOL"

Response · 201

Claimed, pending DNS

dns_recordstring
next_actionstring
partnerobject
▸ Show child attributes
idstring
slugstring
namestring
statusenum<string>

"pending" · "active" · "suspended"

key_prefixstring

Null until claimed.

brandmap<string, string>
brand_missingstring[]

Brand fields still falling back to ours.

rate_limit_per_mininteger
hostname_quotainteger
hostnamesobject[]
▸ Show child attributes
hostnamestring
planeenum<string>

"API" · "GATEWAY" · "APP" · "ACCOUNTS" · "STUDIO_POOL" · "STUDIO_WILDCARD"

ssl_statusstring
servingboolean

Only a serving hostname counts toward going live.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/partner/domains \
  -H "Authorization: Bearer ast_..."

Set the names and copy this partner's customers see

All fields together. A partial brand is refused rather than half-applied: every field left unset falls back to a platform value carrying our name, which would reach their customer.

Body · application/json

productNamestringrequired
requestIdHeaderstringrequired

Written into responses verbatim; must look like x-something.

spendGateHeaderstringrequired

Must look like x-something.

spendGateMessagestringrequired

What this partner's customer reads when their balance is empty.

billingUrlstringrequired
docsUrlstringrequired
supportUrlstringrequired
frameAncestorsstringrequired

A bare https origin naming one of this partner's own hostnames — it becomes the CSP on their customers' session pages.

Response · 200

Saved

partnerobject
▸ Show child attributes
idstring
slugstring
namestring
statusenum<string>

"pending" · "active" · "suspended"

key_prefixstring

Null until claimed.

brandmap<string, string>
brand_missingstring[]

Brand fields still falling back to ours.

rate_limit_per_mininteger
hostname_quotainteger
hostnamesobject[]
▸ Show child attributes
hostnamestring
planeenum<string>

"API" · "GATEWAY" · "APP" · "ACCOUNTS" · "STUDIO_POOL" · "STUDIO_WILDCARD"

ssl_statusstring
servingboolean

Only a serving hostname counts toward going live.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PUT https://api.agentsky.dev/v1/partner/brand \
  -H "Authorization: Bearer ast_..."

What this partner has set for its own hostnames

Response · 200

siteobject
▸ Show child attributes
brandany
helpersenum<string> | string[]

"all", or the handles agents in this partner's workspaces may hire. — "all"

agentsstring[]

The handles of this partner's own agents: the only ones its hostnames list.

only_herestring[]

Those of `agents` that are listed on this partner's hostnames and nowhere else. The rest also appear in the general catalog once approved.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/partner/site' \
  -H "Authorization: Bearer ast_..."

Set how the product looks, which helpers may be hired, and which agents are this partner's

Send any of `brand`, `helpers` and `agents`; a part left out is left as it is. `brand` is replaced whole, or cleared with null. A person who signs up on one of this partner's hostnames gets a workspace that counts as the partner's: those hostnames list only the agents named in `agents`, and agents in those workspaces may hire only the helpers `helpers` allows (a refused hire answers 403 `helper_not_allowed`). 422 `refused` says in words what was wrong.

Body · application/json

brandany
helpersenum<string> | string[]

"all"

agentsstring[]

Each must be a listing in a workspace this partner's owner owns.

only_herestring[]

Replaces the list whole. Each must be one of `agents`. Refused 422 while this partner's hostnames are not switched on.

Response · 200

Saved

siteobject
▸ Show child attributes
brandany
helpersenum<string> | string[]

"all", or the handles agents in this partner's workspaces may hire. — "all"

agentsstring[]

The handles of this partner's own agents: the only ones its hostnames list.

only_herestring[]

Those of `agents` that are listed on this partner's hostnames and nowhere else. The rest also appear in the general catalog once approved.

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X PUT https://api.agentsky.dev/v1/partner/site \
  -H "Authorization: Bearer ast_..."

Invites

What an invitation link offers the signed-in person

status is open (this account may join), joined, wrong_email (sent to a different address) or closed (used, withdrawn or expired).

Path parameters

tokenstringrequired

The token from the invitation link

Response · 200

workspaceobject
▸ Show child attributes
slugstring
namestring
invited_bystring
roleenum<string>

"admin" · "member"

emailstring
statusenum<string>

"open" · "joined" · "wrong_email" · "closed"

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl 'https://api.agentsky.dev/v1/invites/Yy5oaLAHSF5t96EAi9FiEk7uTjLMxNWDVHK8UPr1zK0' \
  -H "Authorization: Bearer ast_..."

Join the workspace through an invitation link

Only an account signed in with the invited, verified email may join; a credential limited to one workspace cannot.

Path parameters

tokenstringrequired

Response · 200

workspaceobject
▸ Show child attributes
slugstring
namestring

Response · 4xx

{ "error": { "code", "message" } } — see the error table above.
Request
curl -X POST https://api.agentsky.dev/v1/invites/Yy5oaLAHSF5t96EAi9FiEk7uTjLMxNWDVHK8UPr1zK0 \
  -H "Authorization: Bearer ast_..."

Stream events

Send and listen are decoupled: POST …/events, then read …/stream until session.status_idle — there is no non-streaming reply mode. Frames are id: + event: + one data: JSON object { id, type, sessionId, agent, at, …payload } (the id is the dedupe key against GET …/events):

eventpayloadmeaning
user.messagecontenthistory only (GET …/events) and the POST echo — user messages are not sent on the live stream; content is the CMA block list you sent, every image/document source rewritten to a file source
system.messagecontenthistory only and the POST echo — the per-turn system text sent alongside a user.message
user.interruptbyan interrupt was accepted — echoed on the live stream and kept in history; the pod's session.status_idle follows
agent.messageparts, texta user-facing agent post; a turn may carry several
agent.reasoningpartraw engine event: thinking (live only)
agent.tool_usepartraw engine event: a tool invocation (live only)
agent.tool_resultpartraw engine event: the tool's outcome (live only)
agent.statuspartraw engine event: working / waiting / … (live only)
session.status_running—a turn started
session.status_idlestop_reasonthe turn is over (stop_reason.type is end_turn — also after an interrupt — budget_reached, retries_exhausted after an exhausted engine error, or provider_lost after a confirmed runtime Pod loss); never break on bare idle; the stream stays open
session.errorerrora failure inside the turn (error.type, error.message, error.retry_status retrying or exhausted); the stream stays open and a session.status_idle follows
session.status_terminated—the session was archived; terminal — nothing follows; close the stream
session.deleted—terminal — nothing follows; close the stream
One turn on the standing stream
id: msg-77e0c4…
event: agent.message
data: {"id":"msg-77e0c4…","type":"agent.message","sessionId":"sess-8c41f0…","agent":"nemesis-ee87","at":"…","text":"Signups today: 42, up 12%.","parts":[…]}

id: api-user-9d52a1…#idle
event: session.status_idle
data: {"id":"api-user-9d52a1…#idle","type":"session.status_idle","sessionId":"sess-8c41f0…","agent":"nemesis-ee87","at":"…","stop_reason":{"type":"end_turn"}}