Skip to content

Credentials

KSquad is vendor-neutral by construction: every agent authenticates with its own per-user Kubernetes Secret, and KSquad holds no shared master credential. Credential type and lifecycle are treated as capability metadata, so the core hardcodes no vendor’s auth flow.

Three credential shapes ship at v1.

Runtime familyHow you connectLifecycleSecret holds
Claude-familyOne-time OAuth — console Connect Claude or CLI ksquad auth loginZero-touch — a controller auto-refreshes the ~8h access token; re-login only after the refresh window (~9 days idle) expiresOAuth access + refresh token
Non-Claude runtime (e.g. OpenClaw, Hermes)Supply a long-lived API key / provider tokenStatic — refresh only if the provider rotates the keyAPI key
BYO model endpoint (Ollama / OpenAI-compatible)Supply an endpoint URL (+ optional token)Static — a local/self-hosted model, no vendor OAuthEndpoint URL (+ token)

This is the smoothest path and the one most teams start with.

  1. In the console, open CredentialsConnect Claude (or run ksquad auth login).
  2. Complete the browser OAuth flow once.
  3. KSquad writes the access + refresh tokens to a per-user Secret. You never handle token strings again.

Under the hood, a leader-elected credential controllernot each agent pod — watches token expiry and refreshes the access token before it expires, writing the new token back to the same Secret. Every agent pod that mounts that Secret benefits at once, so concurrent Runs on one subscription just work. Agents never refresh tokens themselves.

If the subscription goes unused long enough that the refresh token itself expires (~9 days idle), the controller marks the Secret expired and the console surfaces “credential expired — click to re-login” — a single OAuth click, not a recurring manual task.

For runtimes that authenticate with a long-lived key, create a Secret with the provider token and reference it from the agent:

Terminal window
kubectl create secret generic hermes-key \
--namespace ksquad-system \
--from-literal=token='<provider-api-key>'
apiVersion: ksquad.io/v1alpha1
kind: Agent
metadata: { name: writer-1, namespace: ksquad-system }
spec:
runtimeRef: hermes
roleRef: docs-writer
credentialSecretRef: hermes-key
model: <provider-model>

There’s no interactive OAuth step; the key is static. Rotate it by updating the Secret (below).

Point an agent at your own Ollama or OpenAI-compatible server — no paid credits, no vendor OAuth:

Terminal window
kubectl create secret generic my-ollama \
--namespace ksquad-system \
--from-literal=endpoint='http://ollama.internal:11434' \
--from-literal=token='' # optional
spec:
runtimeRef: opencode
model: llama3.3
modelEndpointRef: my-ollama

Whatever the credential type, KSquad never turns an auth failure into an opaque crash:

  • The shim detects an auth-failure signal from the runtime and reports it.
  • The Run transitions to Paused with an operator-legible condition — not a Failed.
  • Resume triggers automatically when the referenced Secret updates — rotate the token (or complete a re-login) and KSquad re-drives the Run.

To rotate a static key, update the Secret:

Terminal window
kubectl create secret generic hermes-key -n ksquad-system \
--from-literal=token='<new-key>' --dry-run=client -o yaml | kubectl apply -f -

Because each credential is a per-user Secret, provider throttling is a per-credential condition — one subscription hitting its limit never blocks or mis-charges another. KSquad auto-pauses and auto-resumes on the provider’s Retry-After, applies exponential backoff on repeats, and can re-route work to an agent whose credential isn’t throttled. See Runs → rate-limit recovery.

  • Tokens live only in the per-user Secret — never logged, echoed, or embedded in a CRD.
  • The credential controller holds no shared master credential; each principal’s Secret is its own.
  • Consumption is attributable to the owning principal by construction (there’s no shared-credential disambiguation problem) — see Observability → consumption metering.