Skip to content
Your agent on Kubernetes

Your agent on Kubernetes

Your first agent runs unchanged in a pod. Two lines differ.

# on your laptop
client = Client("http://127.0.0.1:8080", api_key="rem-token")

# in a pod
client = Client("http://kslate-gateway.kslate.svc",
                token_file="/var/run/secrets/kslate/token")

decide, Write, Agent, run(), the rejections, the claims and the checkpoints are all identical. So is the class: the SharedContext you kubectl apply is the same document, with the same spec, that --policy reads from a file.

Why a token file and not a key

token_file is re-read on every request. A projected ServiceAccount token is rotated by the kubelet, so a value read once at startup would expire; reading the file each time picks up the rotation.

The identity that lands on every write is then sa:<namespace>/<name>, proved by the Kubernetes API rather than asserted by your pod — which is why it is worth more than an API key. Identity strength covers what the difference buys you.

Mounting the token

An agent pod authenticates as its own ServiceAccount. Mount a projected token with audience kslate:

volumes:
  - name: kslate-token
    projected:
      sources:
        - serviceAccountToken: {audience: kslate, expirationSeconds: 3600, path: token}
volumeMounts:
  - {name: kslate-token, mountPath: /var/run/secrets/kslate}

The ServiceAccount must appear in a role of the class as sa:<namespace>/<name>, exactly as apikey:<name> did on your laptop. That is the same identities list from adding a second agent.

One copy per pod is not one identity per pod

Every pod of one Deployment shares its ServiceAccount, so kslate sees them as a single identity. A claim from the identity that already owns a task is a re-claim, not contention — so scaling a Deployment to three replicas does not give you three workers competing safely for tasks. Give each worker its own identity, or run them as separate Deployments with separate ServiceAccounts. One identity, not one process has the shape of a role that covers a fleet.

In Go

client := kslate.NewWithTokenSource("http://kslate-gateway.kslate.svc",
    kslate.TokenFile("/var/run/secrets/kslate/token"))

The Go agent page has the rest.

Next

  • kagent to connect an agent you cannot modify, as a sidecar or over MCP.
  • Honest limits before a real network: traffic is plaintext unless you enable TLS.