Skip to Content
Krad ADE
Agents API

Transport

Loopback TCP with one line of JSON per request, the envelope every request carries, the Hello handshake, limits and deadlines.

The connection

  • Endpoint. A TCP listener on 127.0.0.1 with a port the system picks, opened when the app starts. It is never bound to another interface. Terminals on an SSH host reach it through a reverse port forward the app opens on that host.
  • One request per connection. The client writes one envelope as a single line of JSON ending in \n. The app answers with one line of JSON and closes the connection.
  • Streaming. SubscribeAgents is the exception: the connection stays open and the app writes one JSON line per message until either side closes it. See Subscriptions.
  • Leaving cancels. A client that closes its connection while a request waits, such as a Wait or a Check with a wait, cancels it.

The app serves the bus only when it finds its krad-ade-agents CLI next to its own executable or on PATH.

Limits

LimitValueWhen it is passed
Length of a request line64 KiBbad_request
Time for the line to arrive after connecting10 secondsbad_request

Deadlines

Each request has a deadline after which the app answers the bare string "TimedOut".

RequestsDeadline
Most requests10 seconds
CreateWorktree, Changes, Close, PickVariant1 minute
Spawn, RunVariants1 minute
Code, ExtensionTool2 minutes
Wait, and Check with wait_secsThe time asked, at most 30 minutes, plus one second

The envelope

Every request line is an envelope:

Envelope
{"api_version":1,"token":"6f1c0d9e2b7a4c58e3f09a1d7b6c2e40","from":"Client","request":"Hello"}
FieldMeaning
api_versionThe API version the client speaks: 1. A missing field is read as 1.
tokenThe bus token: KRAD_ADE_TOKEN, or the file KRAD_ADE_TOKEN_FILE names, inside the app's terminals; the token of api.json outside them.
fromWho is calling: "Client" outside the app, {"Terminal":{"environment":"main","terminal":4}} from a terminal. See Callers.
requestOne of the requests. A request without fields is a string ("List"); the others are an object with one key ({"Wait":{"target":4,"timeout_secs":600}}).

Responses have the same shape: an object with one key such as {"Agents":[...]} or {"Error":{"code":"not_found","message":"..."}}, or a bare string such as "TimedOut".

The handshake

"Hello" answers the version the app serves, its build and its process id. The bus answers it itself, so it works even while the app is busy.

Hello
{"api_version":1,"token":"6f1c0d9e2b7a4c58e3f09a1d7b6c2e40","from":"Client","request":"Hello"}
{"Hello":{"api_version":1,"build":"0.3.3","pid":48211}}

pid may be left out of the answer when the app does not know it.

Order of checks

The line

The app reads the line. When it is not a valid envelope, the answer is bad_request.

The token

The token is compared in constant time. A wrong one is unauthorized.

The version

An envelope whose api_version is not the one the app serves is refused before anything else, Hello included.

Another version
{"Error":{"code":"unsupported_api_version","message":"This app serves the agents API v1, not v2"}}

The krad CLI exits with code 6 when that happens.

The caller and the request

The app answers according to the caller named in from. See Authentication.

Try it by hand

From one of the app's terminals on this computer, where the variables are set:

Terminal
printf '{"api_version":1,"token":"%s","from":"Client","request":"Hello"}\n' "$KRAD_ADE_TOKEN" \
  | nc "${KRAD_ADE_ENDPOINT%:*}" "${KRAD_ADE_ENDPOINT##*:}"

krad api makes the same request and prints the version.

On this page