On this page

App providers and which agents use them

GET/runtime/providers

Operation getRuntimeProvidersAuthBearer token

Responses

StatusDescriptionBody
200Providers (hasApiKey only)ProviderDiagnostics
providersrequiredarray<ProviderDiagnosticsEntry>
11 fields of providers
idrequiredstring
typerequiredstring
namerequiredstring
baseUrlrequiredstring
defaultModelstring
presetstring
credentialStoragerequiredstring

app or agent

apiKeyStoragestring
hasApiKeyrequiredboolean
requestDelayMsrequiredinteger
paramsrequiredarray<object>
2 fields of params
keyrequiredstring
hasValuerequiredboolean
agentUsagerequiredarray<object>
7 fields of agentUsage
agentIdrequiredstring
handlestring
namerequiredstring
providerIdrequiredstring
modelIdrequiredstring
sourcerequiredstring

One of agent, app, missing

credentialStoragerequiredstring | null
Errors 401 · 403
401Missing or wrong bearer token (unauthorized)
403The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin

Error bodies use the error format.

Example

Request
curl "http://127.0.0.1:7385/runtime/providers" \
  -H "Authorization: Bearer $ADF_DAEMON_TOKEN"

Add an API-key provider

POST/runtime/providers

Operation addRuntimeProviderAuthBearer token

For every agent on this daemon. The key goes to the daemon secret store (OS keychain, or the owner's passphrase file), never the settings file, and is never returned: the settings entry carries apiKeyStorage: "secret-store" and an empty apiKey, and the daemon fills the key in when it resolves the provider. openai-compatible needs baseUrl (apiKey optional, for local servers); subscriptions (ChatGPT, Grok) sign in instead (400 subscription_type). The name is made unique (OpenRouter 2); the first provider becomes the default.

Request bodyapplication/json · AddProviderBody · required

FieldTypeDescription
typerequiredstring

One of anthropic, openai, openrouter, openai-compatible

namestring
baseUrlstring

Required for openai-compatible

defaultModelstring
presetstring

Provider catalog key (e.g. groq)

apiKeystring

Required except for openai-compatible. Stored in the daemon secret store, never returned.

Responses

StatusDescriptionBody
201AddedAddProviderResponse
providerrequiredobject

An app-level provider as clients see it: never the key.

9 fields of provider · PublicProvider
idrequiredstring
typerequiredstring
namerequiredstring
baseUrlrequiredstring
defaultModelstring
presetstring
credentialStoragerequiredstring

app or agent

apiKeyStoragestring
hasApiKeyrequiredboolean
defaultProviderIdrequiredstring | null
Errors 400 · 401 · 403 · 405 · 409 · 500
400Invalid body (bad_type, subscription_type, api_key_required, base_url_required, bad_base_url)
401Missing or wrong bearer token (unauthorized)
403The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin
405Settings store is read-only (read_only)
409The secret store is locked or not set up (secret_store_locked): set up or unlock the owner identity first
500Saving failed (save_failed)

Error bodies use the error format.

Example

Request
curl -X POST "http://127.0.0.1:7385/runtime/providers" \
  -H "Authorization: Bearer $ADF_DAEMON_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"type":"anthropic","apiKey":"sk-ant-…"}'

Remove an app provider and its stored key

DELETE/runtime/providers/{id}

Operation removeRuntimeProviderAuthBearer token

The default moves to the next provider.

Path parameters

NameTypeDescription
idrequiredstring

App provider id (settings.providers[].id)

example: custom:ab12cd

Responses

StatusDescriptionBody
200RemovedRemoveProviderResponse
removedrequiredstring
providersrequiredarray<PublicProvider>
9 fields of providers
idrequiredstring
typerequiredstring
namerequiredstring
baseUrlrequiredstring
defaultModelstring
presetstring
credentialStoragerequiredstring

app or agent

apiKeyStoragestring
hasApiKeyrequiredboolean
Errors 401 · 403 · 404 · 405
401Missing or wrong bearer token (unauthorized)
403The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin
404Unknown provider (not_found)
405Settings store is read-only (read_only)

Error bodies use the error format.

Example

Request
curl -X DELETE "http://127.0.0.1:7385/runtime/providers/custom%3Aab12cd" \
  -H "Authorization: Bearer $ADF_DAEMON_TOKEN"

List a provider's models

GET/runtime/models

Operation listRuntimeProviderModelsAuthBearer token

App providers, or an agent's own provider (and its agent-scoped key) with agentId. Remote failures come back as 200 { models: [], error }.

Query parameters

NameTypeDescription
providerrequiredstring

Provider id

example: anthropic

agentIdstring

Resolve the provider in this agent's config

Responses

StatusDescriptionBody
200ModelsModelsResponse
providerrequiredstring
modelsrequiredarray<string>
errorstring

Listing failed (the call itself still answers 200)

Errors 400 · 401 · 403
400Invalid request: missing or malformed field, query parameter or body. A body Fastify cannot parse gets Fastify's own shape (statusCode, code, error, message).bad_requestFST_ERR_CTP_EMPTY_JSON_BODY
401Missing or wrong bearer token (unauthorized)
403The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin

Error bodies use the error format.

Example

Request
curl "http://127.0.0.1:7385/runtime/models?provider=anthropic" \
  -H "Authorization: Bearer $ADF_DAEMON_TOKEN"
Response 200
{
  "provider": "anthropic",
  "models": [
    "claude-sonnet-4-5",
    "claude-opus-4-1"
  ]
}

Sign-in and API-key status of every provider

GET/runtime/auth

Operation getRuntimeAuthAuthBearer token

Responses

StatusDescriptionBody
200Auth statusAuthDiagnostics
chatgptrequiredobject
5 fields of chatgpt · SubscriptionAuthStatus
authenticatedrequiredboolean
emailstring
expiresAtinteger

Epoch ms

flowPendingboolean
flowErrorstring
grokrequiredobject
5 fields of grok · SubscriptionAuthStatus
authenticatedrequiredboolean
emailstring
expiresAtinteger

Epoch ms

flowPendingboolean
flowErrorstring
providersrequiredarray<object>
5 fields of providers
idrequiredstring
typerequiredstring
namerequiredstring
credentialStoragerequiredstring
hasApiKeyrequiredboolean
Errors 401 · 403
401Missing or wrong bearer token (unauthorized)
403The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin

Error bodies use the error format.

Example

Request
curl "http://127.0.0.1:7385/runtime/auth" \
  -H "Authorization: Bearer $ADF_DAEMON_TOKEN"

ChatGPT subscription sign-in status

GET/auth/chatgpt/status

Operation getChatGptAuthStatusAuthBearer token

Responses

StatusDescriptionBody
200StatusSubscriptionAuthStatus
authenticatedrequiredboolean
emailstring
expiresAtinteger

Epoch ms

flowPendingboolean
flowErrorstring
Errors 401 · 403
401Missing or wrong bearer token (unauthorized)
403The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin

Error bodies use the error format.

Example

Request
curl "http://127.0.0.1:7385/auth/chatgpt/status" \
  -H "Authorization: Bearer $ADF_DAEMON_TOKEN"
Response 200
{
  "authenticated": true,
  "email": "me@example.com",
  "expiresAt": 1790003600000
}

Start a ChatGPT subscription sign-in

POST/auth/chatgpt/start

Operation startChatGptAuthAuthBearer token

The daemon keeps its own subscription session, separate from Studio's. ChatGPT uses a loopback OAuth redirect, so the callback server must run where the browser is. loopback (default) serves it in the daemon: open authUrl, then poll GET /auth/chatgpt/status. relay (for a remote daemon) keeps the PKCE verifier in the daemon while the caller serves the callback on its own loopback redirectUri (required, loopback only) and posts code + state to /auth/chatgpt/complete within 10 minutes.

Request bodyapplication/json · ChatGptAuthStartRequest · optional

FieldTypeDescription
modestring

Where the OAuth callback is served (default loopback)

One of loopback, relay

redirectUristring

Relay mode only, and required there: the caller's own loopback callback URL

Responses

StatusDescriptionBody
200Flow started; open authUrlChatGptAuthStartResponse
startedrequiredboolean

Value true

moderequiredstring

One of loopback, relay

authUrlrequiredstring
callbackPortinteger

Loopback mode: the port the daemon listens on

flowIdstring

Relay mode: pass to /auth/chatgpt/complete

statestring

Relay mode: echo back with the code

expiresAtinteger

Relay mode: epoch ms after which the flow is discarded

Errors 400 · 401 · 403
400Invalid request: missing or malformed field, query parameter or body. A body Fastify cannot parse gets Fastify's own shape (statusCode, code, error, message).bad_requestFST_ERR_CTP_EMPTY_JSON_BODY
401Missing or wrong bearer token (unauthorized)
403The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin

Error bodies use the error format.

Example

Request
curl -X POST "http://127.0.0.1:7385/auth/chatgpt/start" \
  -H "Authorization: Bearer $ADF_DAEMON_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "mode": "relay",
  "redirectUri": "http://127.0.0.1:1455/auth/callback"
}'

Complete a relayed ChatGPT sign-in

POST/auth/chatgpt/complete

Operation completeChatGptAuthAuthBearer token

Exchanges the code captured by the caller's callback server. Each flowId is single-use and expires 10 minutes after start; an unknown or expired flowId, a mismatched state or a failed token exchange answers 400. After any sign-in (loopback, relay or Grok) every loaded loop in error from an auth failure of that provider type returns to idle and emits agent.recovered; the failed turn is not re-run.

Request bodyapplication/json · ChatGptAuthCompleteRequest · required

FieldTypeDescription
flowIdrequiredstring
coderequiredstring

Authorization code from the caller's OAuth callback

staterequiredstring

Responses

StatusDescriptionBody
200Signed inChatGptAuthCompleteResponse
successrequiredboolean

Value true

statusrequiredobject
5 fields of status · SubscriptionAuthStatus
authenticatedrequiredboolean
emailstring
expiresAtinteger

Epoch ms

flowPendingboolean
flowErrorstring
recoveredrequiredarray<AuthRecovery>

Loops that left error after this sign-in

4 fields of recovered
agentIdrequiredstring
filePathrequiredstring | null
looprequiredstring
noticerequiredstring
Errors 400 · 401 · 403
400Invalid request: missing or malformed field, query parameter or body. A body Fastify cannot parse gets Fastify's own shape (statusCode, code, error, message).bad_requestFST_ERR_CTP_EMPTY_JSON_BODY
401Missing or wrong bearer token (unauthorized)
403The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin

Error bodies use the error format.

Example

Request
curl -X POST "http://127.0.0.1:7385/auth/chatgpt/complete" \
  -H "Authorization: Bearer $ADF_DAEMON_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"flowId":"string","code":"string","state":"string"}'

Sign out of ChatGPT

POST/auth/chatgpt/logout

Operation logoutChatGptAuthBearer token

No body.

Responses

StatusDescriptionBody
200Signed outSuccessResponse
successrequiredboolean
Errors 401 · 403
401Missing or wrong bearer token (unauthorized)
403The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin

Error bodies use the error format.

Example

Request
curl -X POST "http://127.0.0.1:7385/auth/chatgpt/logout" \
  -H "Authorization: Bearer $ADF_DAEMON_TOKEN"
Response 200
{
  "success": true
}

Grok (xAI) subscription sign-in status

GET/auth/grok/status

Operation getGrokAuthStatusAuthBearer token

flowPending while a device-code flow runs; a failed flow surfaces flowError.

Responses

StatusDescriptionBody
200StatusSubscriptionAuthStatus
authenticatedrequiredboolean
emailstring
expiresAtinteger

Epoch ms

flowPendingboolean
flowErrorstring
Errors 401 · 403
401Missing or wrong bearer token (unauthorized)
403The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin

Error bodies use the error format.

Example

Request
curl "http://127.0.0.1:7385/auth/grok/status" \
  -H "Authorization: Bearer $ADF_DAEMON_TOKEN"
Response 200
{
  "authenticated": true,
  "email": "me@example.com",
  "expiresAt": 1790003600000
}

Start a Grok device-code sign-in

POST/auth/grok/start

Operation startGrokAuthAuthBearer token

OAuth device-code flow (RFC 8628): no localhost callback, so it works against a remote daemon. Open verificationUriComplete (or verificationUri and enter userCode) in any browser, then poll GET /auth/grok/status; the daemon polls xAI in the background. No body.

Responses

StatusDescriptionBody
200Flow startedGrokAuthStartResponse
startedrequiredboolean

Value true

userCoderequiredstring
verificationUrirequiredstring
verificationUriCompleterequiredstring
expiresInrequiredinteger

Seconds

Errors 401 · 403
401Missing or wrong bearer token (unauthorized)
403The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin

Error bodies use the error format.

Example

Request
curl -X POST "http://127.0.0.1:7385/auth/grok/start" \
  -H "Authorization: Bearer $ADF_DAEMON_TOKEN"
Response 200
{
  "started": true,
  "userCode": "ABCD-EFGH",
  "verificationUri": "https://accounts.x.ai/device",
  "verificationUriComplete": "https://accounts.x.ai/device?code=ABCD-EFGH",
  "expiresIn": 900
}

Sign out of Grok

POST/auth/grok/logout

Operation logoutGrokAuthBearer token

No body.

Responses

StatusDescriptionBody
200Signed outSuccessResponse
successrequiredboolean
Errors 401 · 403
401Missing or wrong bearer token (unauthorized)
403The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin

Error bodies use the error format.

Example

Request
curl -X POST "http://127.0.0.1:7385/auth/grok/logout" \
  -H "Authorization: Bearer $ADF_DAEMON_TOKEN"
Response 200
{
  "success": true
}

Attach or update a provider in the agent config

POST/agents/{id}/providers

Operation attachAgentProviderAuthBearer token

Path parameters

NameTypeDescription
idrequiredstring

Loaded agent: its id, handle or name.

example: agent-1

Request bodyapplication/json · ProviderAttachBody · required

FieldTypeDescription
providerrequiredobject

A provider carried in the agent's own config. Its API key is a credential (PUT …/providers/{providerId}/credential), never part of this object.

8 fields of provider · AgentProviderConfig
idrequiredstring

anthropic, openai, … or custom:<id>

typerequiredstring

One of anthropic, openai, openai-compatible, openrouter

namerequiredstring
baseUrlrequiredstring
presetstring
defaultModelstring
paramsarray<object>
2 fields of params
keyrequiredstring
valuerequiredstring
requestDelayMsinteger

Responses

StatusDescriptionBody
200AttachedProviderAttachResponse
agentIdrequiredstring

Agent id

providerIdrequiredstring
successrequiredboolean

Value true

alreadyAttachedrequiredboolean
configrequiredobject

The agent's ADF v0.2 config (adf_config). Only the most used fields are listed; the full shape is the ADF spec's AgentConfig. Secret values never appear here.

25 fields of config · AgentConfig
adf_versionrequiredstring

Value 0.2

idrequiredstring

Agent id (stable, the daemon addresses the agent by it)

namerequiredstring
descriptionrequiredstring
handlestring
iconstring
staterequiredstring

Display (fleet-map) state of an agent

One of active, idle, hibernate, suspended, off

autonomousrequiredboolean
autostartboolean
modelrequiredobject
9 fields of model · ModelConfig
providerrequiredstring

Provider id (app provider or one of the agent's own providers)

model_idrequiredstring
temperaturenumber | null
max_tokensinteger | null
top_pnumber | null
reasoningobject

Provider-agnostic reasoning ("thinking") config

multimodalobject
3 fields of multimodal
imageboolean
audioboolean
videoboolean
paramsarray<object>
2 fields of params
keyrequiredstring
valuerequiredstring
provider_paramsobject
instructionsrequiredstring
contextrequiredobject

compact_threshold, audit, dynamic_instructions

toolsrequiredarray<object>

Tool declarations

5 fields of tools
namerequiredstring
enabledrequiredboolean
visibleboolean
restrictedboolean
lockedboolean
triggersrequiredmap<string, TriggerConfig>

on_startup, on_inbox, on_outbox, on_file_change, on_chat, on_timer, on_tool_call, on_task_create, on_task_complete, on_logs, on_llm_call

3 fields of triggers
enabledrequiredboolean
targetsrequiredarray<TriggerTarget>
11 fields of targets
scoperequiredstring

One of agent, system

lambdastring

System scope: path/file.ts:functionName

commandstring

System scope: shell command (alternative to lambda)

warmboolean
filterobject
debounce_msinteger
interval_msinteger
batch_msinteger
batch_countinteger
lockedboolean
loopstring

Cognition loop this target wakes; absent = main

lockedboolean
securityrequiredobject
limitsrequiredobject
messagingrequiredobject

mode (proactive | respond_only | listen_only), receive, network, …

mcpobject
2 fields of mcp
serversrequiredarray<McpServerConfig>
20 fields of servers
namerequiredstring
transportrequiredstring

One of stdio, http

commandstring
argsarray<string>
urlstring
oauthboolean
headersmap<string, string>
header_envarray<object>
bearer_token_env_varstring
envmap<string, string>
env_keysarray<string>
env_schemaarray<object>
npm_packagestring
pypi_packagestring
sourcestring
available_toolsarray<object>
tool_call_timeout_msinteger
restrictedboolean
run_locationstring

One of host, shared

credential_filesarray<object>
3 fields of credential_files
pathrequiredstring
requiredboolean
write_backboolean
new_tools_restrictedboolean
adaptersmap<string, AdapterInstanceConfig>

Channel adapters by type

4 fields of adapters
enabledrequiredboolean
configobject

Adapter-specific settings (no secrets: tokens are credentials)

policyobject
limitsobject
1 field of limits
max_attachment_sizeinteger

Bytes

providersarray<AgentProviderConfig>
8 fields of providers
idrequiredstring

anthropic, openai, … or custom:<id>

typerequiredstring

One of anthropic, openai, openai-compatible, openrouter

namerequiredstring
baseUrlrequiredstring
presetstring
defaultModelstring
paramsarray<object>
2 fields of params
keyrequiredstring
valuerequiredstring
requestDelayMsinteger
loopsarray<LoopConfig>

Inner (side) loops; main is implicit

8 fields of loops
namerequiredstring

pattern: ^[a-z0-9][a-z0-9_-]{0,31}$

goalrequiredstring

Becomes the loop's instructions

enabledrequiredboolean
autostartboolean
autonomousboolean
modelobject

Fields as in ModelConfig above.

compact_thresholdinteger | null
toolsarray<string>

Absolute allow-list, intersected with the host's enabled tools

ws_connectionsarray<object>
servingobject
locked_fieldsarray<string>
metadatarequiredobject

created_at, updated_at, author, tags, version

Errors 400 · 401 · 403 · 404 · 500
400Invalid request: missing or malformed field, query parameter or body. A body Fastify cannot parse gets Fastify's own shape (statusCode, code, error, message).bad_requestFST_ERR_CTP_EMPTY_JSON_BODY
401Missing or wrong bearer token (unauthorized)
403The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin
404Unknown agent (or the named resource: loop, task, file, …)
500Unexpected runtime failure

Error bodies use the error format.

Example

Request
curl -X POST "http://127.0.0.1:7385/agents/agent-1/providers" \
  -H "Authorization: Bearer $ADF_DAEMON_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "provider": {
    "id": "custom:ab12cd",
    "type": "openai-compatible",
    "name": "Local LLM",
    "baseUrl": "http://127.0.0.1:11434/v1"
  }
}'

Detach a provider and delete its credentials

DELETE/agents/{id}/providers/{providerId}

Operation detachAgentProviderAuthBearer token

Removes the provider config and every provider:{providerId}:* identity row.

Path parameters

NameTypeDescription
idrequiredstring

Loaded agent: its id, handle or name.

example: agent-1

providerIdrequiredstring

Provider id in the agent config

example: anthropic

Responses

StatusDescriptionBody
200DetachedProviderDetachResponse
agentIdrequiredstring

Agent id

providerIdrequiredstring
successrequiredboolean

Value true

deletedCredentialsrequiredinteger
configrequiredobject

The agent's ADF v0.2 config (adf_config). Only the most used fields are listed; the full shape is the ADF spec's AgentConfig. Secret values never appear here.

Fields as in AgentConfig above.

Errors 401 · 403 · 404 · 500
401Missing or wrong bearer token (unauthorized)
403The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin
404Unknown agent (or the named resource: loop, task, file, …)
500Unexpected runtime failure

Error bodies use the error format.

Example

Request
curl -X DELETE "http://127.0.0.1:7385/agents/agent-1/providers/anthropic" \
  -H "Authorization: Bearer $ADF_DAEMON_TOKEN"