AI agents¶
What kubelatch guarantees when an AI agent works on your clusters through its MCP server, and where those guarantees stop. Connecting your own agent is in AI agents; running bots, sessions and approvals, in AI agents for operators.
One path to the clusters¶
An agent connects to kubelatch at <base URL>/mcp (the Model Context Protocol over HTTP) and calls tools: list objects, read one, read logs, apply an object, and so on. The tools don't talk to the clusters themselves. Each call becomes one or more Kubernetes requests through the same proxy as kubectl (The journey of a request): the same impersonation, the same audit row written before the request leaves (if it can't be written, the request doesn't go), and the cluster's own RBAC deciding. kubelatch decides which groups the agent is sent with; the API server decides what those groups may do.
flowchart LR
a["Agent<br/>Claude Code, Cursor…"] -->|"MCP over HTTP"| m["kubelatch<br/>/mcp tools"]
m -->|"same proxy as kubectl"| k8s["Your clusters"]
m --> au[("Audit log<br/>with the session<br/>and the tool")]
Every audit row of an agent carries its agent session and the tool that made it, so everything one agent did can be followed.
Two ways to give an agent access¶
A bot. An administrator creates a bot for the agent, grants it roles and issues it a credential, which the agent sends. The clusters see bot:<name>. This is for an agent that isn't one person's: an on-call agent, a pipeline step.
On your behalf (delegated). You authorize the agent yourself, in the browser. It's the gesture of Sign in with Google: you don't hand over your password, you give a limited permission you can take back. The clusters see you, user:<login>, but only with the permissions you chose for the agent. This is for your own agent on your computer.
| Bot | Delegated | |
|---|---|---|
| Who the agent is on the cluster | bot:ops-agent |
user:sergio |
| Where its permissions come from | Those an administrator granted the bot | Yours, cut down by you |
| Who decides how much it can do | An administrator | You, up to your own limit |
| If a permission of yours is taken away | It doesn't affect it | The agent loses it at once |
Both at once. sergio is developer on shop. His Claude Code, delegated, works as him, read-only. Meanwhile the company's on-call agent, which reviews alerts at night, uses the bot ops-agent, viewer on every namespace because an administrator granted it. They are two identities that never mix.
A person's own credentials (an issued kubeconfig, a kubelatch login session, a CI credential) don't work at /mcp: a person's agent always comes in through the delegated sign-in, so that there's a ceiling and a consent. Agent tokens, in turn, work only at /mcp: the proxy and the API refuse them.
The ceiling of a delegated agent¶
When you authorize an agent, each permission you include becomes a derived permission of its session. Together they are its ceiling:
- Same cluster and scope as yours, and either your role or
viewer.vieweris offered only from a role that includes it (viewer,developer,adminandcluster-admin). Adebugger,secrets-readeror custom-role permission can only be passed as itself:viewerwould give the agent reads you don't have. The consent page leaves those out unless you include them. - Never
cluster-admin: acluster-adminpermission can only be passed asviewer. - It ends when the session ends or when your permission ends, whichever comes first. If your permission is revoked, the derived one stops counting on the agent's next call.
- A permission granted to you after you authorized the agent enters the session only as you chose on the consent page, under Permissions you get later: nothing,
viewer(the default) or the same role. It holds for a direct permission, a batch and a group membership alike. Each one becomes a derived permission under the rules above: acluster-adminyou receive later passes asviewer, never as itself, andvieweronly from a role that includes it. It ends with the session or with the permission it comes from, and leaves a control event,agent.grant.follow. To go further, the agent asks withrequest_access, or you authorize it again.
The cluster sees the agent with the groups of its derived permissions only, never with all of yours.
Approvals and temporary access¶
Approving writes. It's a switch. For a bot, an administrator turns it on in the bot's settings (it's off by default: the role alone decides). For a delegated agent, you choose it when you authorize it (on by default). With it on:
- The agent asks for a write. kubelatch first sends it to the cluster as a dry run; if the cluster refuses it, the agent gets that answer and nothing is held.
- kubelatch keeps the request and shows a person what would change, on the approval's page: a line saying what it does, and the object now against what the dry run says it becomes. A Secret's values are never shown there, and the page never says a Secret write changes nothing, since a hidden value may change.
- A person decides: you, for your delegated agent; an administrator, for a bot.
- The agent calls again. A client that can ask opens the approval page and repeats the call by itself; the others hand over the link in text, and the agent repeats the call with the
approval_id. The call waits for the decision for up to a minute. Approved, kubelatch runs the request it kept, once, and the result starts with a line naming who approved it. If the second call asks for something else, it's refused. If the object changed between the approval and the run, the write fails and has to be asked again; a deletion never removes an object recreated with the same name.
The same call repeated while its request still waits returns that request rather than a second one. A held write waits 15 minutes for a decision and, once approved, 15 more to run. Its body is kept encrypted while it waits and deleted once it's denied, runs or expires. At most 20 approvals can wait at once for one account.
Temporary access. With request_access, an agent asks for a role on a namespace (or the whole cluster) for 1 to 480 minutes, with a reason. For a bot, an administrator decides, and an ordinary permission with that expiry is granted under the usual rules. For a delegated agent, you decide, and only for a role you hold on that cluster and namespace, never cluster-admin; it becomes a derived permission. An access approval expires after an hour without a decision.
While an approved access lasts, takes effect and its role can write, the agent's writes in its cluster and namespace don't wait for approval one by one: whoever approved it already said yes to that role, there, for that time. kubelatch doesn't know which writes each role allows, so during that time the agent also writes there with everything its other permissions there allow. When it ends, writes wait for approval again. It's the comfortable path for a task with several changes: one approval of "developer on shop, 30 minutes" instead of one per change.
Secrets¶
list_resources, get_resource and apply hide every value of a Secret (<redacted, N bytes>) and drop its kubectl.kubernetes.io/last-applied-configuration annotation. In the preview of a held write, a value that the write changes reads <redacted, N bytes, changed>: the person who decides sees that it changes, never what it becomes. It isn't an access control: read_secret returns the values to any agent whose role can read Secrets there. It makes a value reach the agent only when the agent asks for it, and makes each read of values an audit row of its own. ConfigMaps, environment variables written in a pod spec, and logs are not hidden.
Signing an agent in¶
For delegated agents, kubelatch is the OAuth 2.1 authorization server, and an MCP client finds it by itself from the first 401 of /mcp:
- The agent's client registers itself (with a metadata document it publishes, or by dynamic registration) and sends you to kubelatch's consent page, with PKCE (
S256). - The consent needs your web session and a click: no link can answer it for you.
- The agent gets a 1-hour access token, valid only at
/mcpand never past the session, and a refresh token that changes on every use. A refresh token or a code presented a second time cuts the session at once. - kubelatch redirects only to an address the client registered; on your own computer (
localhost,127.0.0.1,[::1]), on any port. - The consent page states who asks, where the answer goes, what the agent would get and until when, and warns whenever the answer would leave your computer: another host, or an app that opens a private scheme.
MCP server has the endpoints and the rules in detail.
What it does not cover¶
kubelatch states these limits rather than hiding them:
- Content can carry instructions. Logs, annotations and object fields come from the cluster and may hold text written to steer a model. kubelatch doesn't filter it; the ceiling, approvals and hidden Secret values limit the harm.
- A Secret value read stays read. Once
read_secretreturns a value, it's in the agent's context and in its model provider's history. Cutting the session doesn't take it back. - An agent that controls your browser could approve its own requests. Approvals assume a person clicks.
- Other ways in. The ceiling bounds what the agent does through kubelatch. If it has another way into a cluster on your machine (a kubeconfig, a
kubelatch loginsession, a cloud CLI), it can use it. The rules and the Claude Code plugin cover that only in part: the rules advise, and the hook is a guardrail for an agent that means well, not a boundary. It can be bypassed, and it runs only in Claude Code. - No
exec,port-forward,watchorlogs -f. The tools don't offer them; a person does that with their own credential.