Skip to content

CLI

kslate ships two binaries. kslate is the gateway (kslate serve), the worker and controller (kslate worker), and the command-line client (the read commands and verify). kslate-reconciler is the sidecar that drives an agent you cannot change. The kagent guide shows how to use it.

The read commands need a credential. Give it one of three ways, in this order of preference:

  1. --token-file PATH. A file holding the bearer token. This is what a projected ServiceAccount token volume gives you, and the file is re-read per request so a rotated token keeps working.
  2. --apikey TOKEN. The token on the command line. Avoid this. It shows up in ps and in your shell history.
  3. $KSLATE_APIKEY. The token in an environment variable.

Every read goes through the gateway, so you only see fields your role may read.

kslate

usage:
  kslate serve   --policy contexts.yaml --identity apikey --apikeys keys.yaml --postgres $DSN [--listen :8080] [--grpc-listen :9091] [--metrics-listen :9100]
  kslate serve   --policy k8s-crd --identity k8s-sa --postgres $DSN [--kubeconfig PATH] [--namespace NS]
  kslate serve   --policy contexts.yaml --identity k8s-sa,oidc --oidc-issuers issuers.yaml --postgres $DSN
                 [--tls-cert PEM --tls-key PEM] [--max-conns 4096] [--unauth-rate 50]
  kslate worker  --policy contexts.yaml --postgres $DSN [--interval 60s] [--metrics-listen :9090]
  kslate worker  --policy k8s-crd --postgres $DSN [--kubeconfig PATH] [--namespace NS]
  kslate get     --server URL <class>/<id> [--fields a,b] [--json]
  kslate classes --server URL
  kslate history --server URL <class>/<id> [--field NAME]
  kslate blame   --server URL <class>/<id> <field>
  kslate claims  --server URL <class>/<id>
  kslate resume  --server URL <class>/<id> [--role NAME]
  kslate verify  --server URL <class>/<id> [--move FIELD=VALUE --watch 60s] [--json]
  kslate version

credential for history/blame/claims/resume, in order of preference:
  --token-file PATH  |  --apikey TOKEN (visible in ps and shell history)  |  $KSLATE_APIKEY

kslate serve

Usage of serve:
  -apikeys string
    	apikey file: YAML map of token -> name; the identity becomes apikey:<name>
  -grpc-listen string
    	gRPC listen address; empty disables the gRPC transport
  -identity string
    	identity providers, comma-separated and tried in order: apikey | k8s-sa | oidc | mtls (default "apikey")
  -kubeconfig string
    	kubeconfig path for --identity k8s-sa / --policy k8s-crd (empty: in-cluster config)
  -listen string
    	listen address (HTTP/JSON and MCP) (default ":8080")
  -max-conns int
    	maximum concurrent connections on the API listener (0: unlimited) (default 4096)
  -metrics-listen string
    	Prometheus metrics listen address (kept off the API port: the labels are the policy graph) (default ":9100")
  -mtls-cas string
    	--identity mtls: YAML file listing trusted client CAs (name, caFile, optional subject and strength). Requires --tls-cert/--tls-key: the certificate comes from the connection, never a header
  -namespace string
    	namespace to watch for --policy k8s-crd (empty: cluster-wide)
  -oidc-issuers string
    	--identity oidc: YAML file listing trusted issuers (name, issuer, audience, jwksUrl, optional subjectClaim and strength)
  -oidc-leeway duration
    	--identity oidc: clock skew tolerated on exp and nbf (default 1m0s)
  -policy string
    	policy file (YAML stream of SharedContext documents), or "k8s-crd" to watch SharedContext custom resources
  -postgres string
    	Postgres DSN
  -tls-cert string
    	TLS certificate (PEM) for the HTTP/MCP and gRPC listeners; with --tls-key, both serve TLS. Empty: plaintext (see SECURITY.md)
  -tls-key string
    	TLS private key (PEM), paired with --tls-cert
  -unauth-rate float
    	UNAUTHENTICATED outcomes allowed per second per remote address (IPv6: per /64), on HTTP, gRPC and MCP, before RATE_LIMITED (0: off); burst is 4x (default 50)

kslate worker

Usage of worker:
  -health-listen string
    	health listen address: /readyz (schema present, SharedContext watch healthy) and /healthz, for probes; kept off the metrics port so a NetworkPolicy on metrics cannot fail them (default ":8081")
  -interval duration
    	sweep interval (default 1m0s)
  -kubeconfig string
    	kubeconfig path for --policy k8s-crd (empty: in-cluster config)
  -metrics-listen string
    	metrics listen address (default ":9090")
  -namespace string
    	namespace to watch for --policy k8s-crd (empty: cluster-wide)
  -policy string
    	policy file (YAML stream of SharedContext documents), or "k8s-crd" to run the controller against SharedContext custom resources
  -postgres string
    	Postgres DSN

kslate get

Usage of get:
  -apikey string
    	bearer token (prefer --token-file or $KSLATE_APIKEY)
  -fields string
    	comma-separated fields (default: everything you may read)
  -json
    	print the raw JSON body
  -server string
    	gateway base URL, e.g. http://localhost:8080
  -token-file string
    	file holding the bearer token, e.g. a projected ServiceAccount token

kslate classes

Usage of classes:
  -apikey string
    	bearer token (prefer --token-file or $KSLATE_APIKEY)
  -server string
    	gateway base URL, e.g. http://localhost:8080
  -token-file string
    	file holding the bearer token, e.g. a projected ServiceAccount token

kslate history

Usage of history:
  -apikey string
    	bearer token (prefer --token-file or $KSLATE_APIKEY)
  -field string
    	filter to one field
  -server string
    	gateway base URL, e.g. http://localhost:8080
  -token-file string
    	file holding the bearer token, e.g. a projected ServiceAccount token

kslate blame

Usage of blame:
  -apikey string
    	bearer token (prefer --token-file or $KSLATE_APIKEY)
  -server string
    	gateway base URL, e.g. http://localhost:8080
  -token-file string
    	file holding the bearer token, e.g. a projected ServiceAccount token

kslate claims

Usage of claims:
  -apikey string
    	bearer token (prefer --token-file or $KSLATE_APIKEY)
  -server string
    	gateway base URL, e.g. http://localhost:8080
  -token-file string
    	file holding the bearer token, e.g. a projected ServiceAccount token

kslate resume

Usage of resume:
  -apikey string
    	bearer token (prefer --token-file or $KSLATE_APIKEY)
  -role string
    	load a specific role's checkpoint (default: the caller's own)
  -server string
    	gateway base URL, e.g. http://localhost:8080
  -token-file string
    	file holding the bearer token, e.g. a projected ServiceAccount token

kslate verify

Usage of verify:
  -apikey string
    	bearer token (prefer --token-file or $KSLATE_APIKEY)
  -json
    	print the report as JSON
  -move string
    	fault injection: FIELD=VALUE — write a new version of FIELD (as this credential), then watch what the agent does
  -server string
    	gateway base URL, e.g. http://localhost:8080
  -token-file string
    	file holding the bearer token
  -watch duration
    	after --move, how long to wait before reading history again

The commands get, history, blame, claims, resume and verify take the record name, <class>/<id>, after the flags. blame also takes a field name. Put flags before the record name. For example:

kslate blame --server http://127.0.0.1:8080 incidents/inc-1 planned_action

kslate-reconciler

usage: kslate-reconciler [flags]
       kslate-reconciler version

flags:
  -a2a-endpoint string
    	--transport sidecar: the agent container's A2A endpoint, same pod (default "http://localhost:8080")
  -a2a-timeout duration
    	ceiling on one agent invocation (default 5m0s)
  -agent string
    	--transport kagent-gateway: the kagent Agent to invoke, namespace/name
  -apikey string
    	bearer token this sidecar authenticates as (--identity apikey gateways)
  -checkpoint-role string
    	role to checkpoint as (empty: infer)
  -claim-field string
    	task field to claim before acting
  -class string
    	class-scoped mode: reconcile every matching record of this class (mutually exclusive with --record)
  -concurrency int
    	class-scoped mode: how many candidate records one cycle works (default 1)
  -filter value
    	class-scoped mode: field=value equality filter, repeatable
  -instruction string
    	--transport kagent-gateway: text prepended to the task part. Empty by default; the agent's own contract is the operator's, not kslate's
  -interval duration
    	poll interval (default 5s)
  -kagent-gateway string
    	--transport kagent-gateway: kagent's controller base URL, e.g. http://kagent-controller.kagent.svc:8083
  -kagent-user-id string
    	--transport kagent-gateway: X-User-Id sent to kagent. A label, not a credential: kagent does not verify it (default "kslate-reconciler")
  -lease-seconds int
    	claim lease, seconds (default 300)
  -record string
    	single-record mode: the record to reconcile, class/id (e.g. incidents/inc-42)
  -server string
    	kslate gateway base URL
  -stalled-backoff duration
    	how long to leave a record alone after its agent asked for input (doubles per consecutive stall, capped at 30m) (default 1m0s)
  -task-encoding string
    	--transport kagent-gateway: how the task is carried to the agent: text | data | both (default "text")
  -token-file string
    	file holding the bearer token, re-read per request (--identity k8s-sa gateways: a projected ServiceAccount token, audience kslate)
  -transport string
    	how the agent is reached: sidecar | kagent-gateway (default "sidecar")
  -verify-contract string
    	--transport kagent-gateway: check kagent's A2A proto shape at startup over gRPC reflection: auto (mismatch is fatal, unreadable is a warning) | require | skip (default "auto")
  -watch-field string
    	field whose version change is the predicate

Give the sidecar either --record to watch one record, or --class to watch every record in a class. Not both.

For the credential, use --token-file with a projected ServiceAccount token. The sidecar re-reads the file on every request, so it picks up a rotated token. Use --apikey only against a gateway that runs with --identity apikey.