> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lumovi.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Assistant tools

> The twelve tools Lumovi gives AI assistants: seven that read your clusters, four that ask to change them, and one that waits for your answer.

These are the tools an assistant gets when it connects to Lumovi. The assistant decides which to call, and with what, and may show you their names as it uses them. Lumovi answers in short YAML, with each object's health as Lumovi shows it.

<Note>
  **Desktop app only:** like [AI assistants](/assistants/overview) themselves, for now.
</Note>

| Tool | Title | What it does |
| - | - | - |
| `list_clusters` | List clusters | Your clusters, and whether each takes changes |
| `list_kinds` | List kinds | The kinds a cluster serves, custom resources' too |
| `list_resources` | List resources | Objects of a kind, with their health |
| `get_resource` | Get a resource | One object as YAML, its health first |
| `get_events` | Get events | Events, the latest first |
| `get_logs` | Get logs | A container's latest log lines |
| `find_problems` | Find problems | What's wrong in a cluster or namespace, in one answer |
| `apply_manifest` | Apply a manifest | Asks to create or change an object |
| `scale` | Scale | Asks to set a workload's replicas |
| `restart` | Restart | Asks to restart a workload's pods |
| `delete_resource` | Delete a resource | Asks to delete an object |
| `wait_for_change` | Wait for a change | Waits for your answer to a change it asked for |

When an assistant connects, Lumovi also tells it how to go about it: start with `list_clusters`; to see what's wrong, `find_problems` first, then `get_resource`, `get_events` and `get_logs` on what it finds. Changes wait for your approval, so it should say why in `reason`, tell you to look at Lumovi, and follow the note of a change you reject. A call waits for your answer up to a minute: if it says it's still waiting, the assistant calls `wait_for_change` with the id it gives, until you answer.

## Parameters they share

<ResponseField name="cluster" type="string" required>
  The cluster: a context's name, as `list_clusters` gives them. For one that isn't in your kubeconfig, the assistant is told which are: *There is no cluster called "prod". These are: demo, sandbox, …*
</ResponseField>

<ResponseField name="kind" type="string">
  A kind, as `kubectl` takes it: `Deployment`, `deploy`, `deployments`, `deployments.apps`, `svc`, or a custom resource's, like `Certificate` or `certificates.cert-manager.io`. Built-in kinds come first, so `Event` is the core one, not `events.k8s.io`'s. For one the cluster doesn't serve: *demo has no kind "gizmos". list\_kinds lists the ones it has.*
</ResponseField>

<ResponseField name="namespace" type="string">
  The object's namespace. Needed for one object of a namespaced kind: *Pods are namespaced: say which namespace.*
</ResponseField>

## Reading

These tools only read. Lumovi marks them so for the assistant (MCP's `readOnlyHint`), so an assistant that asks you before it uses a tool can tell them from the others. What each needs from your RBAC is in [Permissions](/clusters/permissions#ai-assistants).

### list\_clusters

The clusters in your kubeconfig, and which is the current one. For each: its name, its API server's address, its default namespace when the context has one, and `changes`, whether it takes an assistant's changes: `ask`, `allow`, `never` or `read-only`. See [Changes they ask for](/assistants/approvals#changes-they-ask-for).

It takes no parameters.

### list\_kinds

The kinds a cluster serves, custom resources' too: each one's name as the other tools take it, its API version, whether it's namespaced, and its short names. Built-in kinds go by their name, like `Deployment`, and custom ones by their name and group, like `Rollout.argoproj.io`.

<ResponseField name="cluster" type="string" required />

### list\_resources

Objects of a kind, in one namespace or all of them. For each: its name and namespace, its health as Lumovi shows it, with the reason when there is one (`CrashLoopBackOff (critical): back-off restarting failed container`), its age (`45s`, `12m`, `5h`, `3d`), and what its kind's list shows in Lumovi:

| Kind | Also |
| - | - |
| Pods | `ready` (`1/2`), `restarts`, `node` |
| Deployments, StatefulSets, ReplicaSets, DaemonSets | `ready` (`3/3`), `images` |
| Services | `type`, `clusterIP`, `ports` (`80/TCP`) |
| Nodes | `roles`, `version` (the kubelet's) |

It says how many there are (`total`), and how many it shows when that's fewer (`shown`).

<ResponseField name="cluster" type="string" required />

<ResponseField name="kind" type="string" required />

<ResponseField name="namespace" type="string">
  Only this namespace's objects. Every namespace's unless given.
</ResponseField>

<ResponseField name="labelSelector" type="string">
  As `kubectl -l` takes it: `app=web,tier!=db`.
</ResponseField>

<ResponseField name="limit" type="number" default="100">
  At most this many, up to 500.
</ResponseField>

### get\_resource

One object as YAML, with its health on the first line, like `# Health: Running (healthy)`. It leaves out what's long and says little, and a Secret's values: see [What's hidden](#whats-hidden).

<ResponseField name="cluster" type="string" required />

<ResponseField name="kind" type="string" required />

<ResponseField name="name" type="string" required />

<ResponseField name="namespace" type="string">
  Its namespace, for namespaced kinds.
</ResponseField>

### get\_events

What Kubernetes reported, the latest first: about one object, a namespace, or the whole cluster. Each event says how long ago it last happened, its type and reason, the object it's about, its message, and how many times it happened when that's more than once. With none, it says "No events."

<ResponseField name="cluster" type="string" required />

<ResponseField name="namespace" type="string">
  Only this namespace's events.
</ResponseField>

<ResponseField name="kind" type="string">
  With `name`: only events about this object.
</ResponseField>

<ResponseField name="name" type="string" />

<ResponseField name="warningsOnly" type="boolean">
  Only warnings.
</ResponseField>

<ResponseField name="limit" type="number" default="50">
  At most this many, up to 500.
</ResponseField>

### get\_logs

A container's latest log lines, as `kubectl logs` shows them, up to 256 KB of them. It doesn't follow the log. With none, it says "(No log lines.)"

<ResponseField name="cluster" type="string" required />

<ResponseField name="namespace" type="string" required />

<ResponseField name="pod" type="string" required />

<ResponseField name="container" type="string">
  Needed when the pod has several.
</ResponseField>

<ResponseField name="tailLines" type="number" default="200">
  The last so many lines, up to 2,000.
</ResponseField>

<ResponseField name="previous" type="boolean">
  The container's run before its last restart: what a crash-looping container said before it died.
</ResponseField>

<ResponseField name="sinceSeconds" type="number">
  Only lines this recent.
</ResponseField>

### find\_problems

What's wrong in a cluster, or in one namespace, in one call. It's where Lumovi tells assistants to start.

* **`problems`**: the nodes, pods, Deployments, StatefulSets, DaemonSets, Jobs and PersistentVolumeClaims whose [health](/explore/health) is a warning or critical, the critical ones first, each with Lumovi's reason and its age. Nodes only for the whole cluster: they aren't in a namespace.
* **`warningsInTheLastHour`**: the last hour's warning events, one for each object and reason, the most frequent first, up to 20, with how many times and how long ago.
* **`couldNotCheck`**: the kinds it couldn't list, and why, like your account not being allowed to.

When there's nothing, it says so: "Nothing is wrong in shop in demo: no unhealthy objects, and no warnings in the last hour."

<ResponseField name="cluster" type="string" required />

<ResponseField name="namespace" type="string">
  Only this namespace. The whole cluster unless given.
</ResponseField>

## Changing

These four ask for a change. Each takes a reason, which you read before you answer:

<ResponseField name="reason" type="string" required>
  Why: one or two sentences, up to 1,000 characters, about what's wrong and how the change helps. It's the dialog's **Why**.
</ResponseField>

A change goes through the same steps, whichever tool asks for it:

1. **The cluster's setting.** If its [Changes they ask for](/assistants/approvals#changes-they-ask-for) is **Never**, the change is refused, and nothing is tried.
2. **A dry run.** The API server checks the change, and your access, and says what the object would come to. If it refuses, the assistant is told why: "Restart Deployment cart wouldn't work: …". A [read-only](/changes/read-only) cluster refuses here.
3. **Your answer.** With **Allow**, the change is made at once, unless it's a deletion, or takes fields over from what manages them: those ask anyway. Otherwise it waits in Lumovi for you, up to five minutes. See [Approving changes](/assistants/approvals).
4. **A check.** Once you approve it, Lumovi tries it as a dry run again, and makes it only if it still changes the object as the diff you saw did. A deletion is made only if the object is still the one you saw, by its uid. If not: "Scale Deployment cart to 3 replicas wasn't made: cart changed after it was shown (…). Nothing was changed: ask again, to show it as it is now."
5. **The change.** Lumovi makes it with your credentials, and tells the assistant what it did, and the `kubectl` command that does the same: "Restarted cart, approved in Lumovi. The kubectl command that does the same: …". If it fails, the assistant is told why: "Restart Deployment cart failed: …".

The commands Lumovi shows for each, in the approval dialog and to the assistant:

```bash theme={"theme":{"light":"github-light","dark":"github-dark-default"}}
kubectl apply --server-side --force-conflicts --field-manager=lumovi -f feature-flags.yaml -n shop --context demo
kubectl scale deployment/storefront --replicas=5 -n shop --context demo
kubectl rollout restart deployment/cart -n shop --context demo
kubectl delete pod/checkout-7d9f8-x2k4q -n shop --context demo
```

### apply\_manifest

Creates an object, or changes one, from a manifest, as `kubectl apply --server-side` does: the fields the manifest has are set, and the others are left as they are. In Lumovi, it's **Create** *kind name* for an object that isn't there yet, and **Change** *kind name* for one that is.

* **One object a call**, in YAML or JSON, with its namespace in its `metadata`.
* **Lumovi applies it as the field manager `lumovi`, and forces conflicts**, as `--force-conflicts` does. Fields the manifest sets become Lumovi's, even when something else manages them, like a Helm release, Argo CD or an autoscaler.
* **It tries it without forcing first.** When that fails because something else manages fields the manifest sets, the approval dialog says whose and which: "It takes fields over from what manages them (Helm, Argo CD, an autoscaler…), which may change them back: …". Such a change asks you even where the cluster allows assistants' changes.
* **What's refused before the dry run**: "Apply one object at a time: this has 2.", "The manifest isn't valid YAML: …", and "A manifest needs apiVersion, kind and metadata.name."

The approval dialog shows the manifest as the assistant gave it, under **The manifest Claude Code gave**.

<ResponseField name="cluster" type="string" required />

<ResponseField name="manifest" type="string" required>
  One object, as YAML or JSON.
</ResponseField>

<ResponseField name="reason" type="string" required />

### scale

Sets how many replicas a workload runs, as `kubectl scale` does: a Deployment, StatefulSet or ReplicaSet, or a custom kind that can be scaled (through its `scale` subresource), like an Argo Rollout.

* **Nothing to change, nothing to approve**: "storefront already runs 5 replicas: nothing to change."
* **Kinds that don't scale say so**: "ConfigMaps can't be scaled."

<ResponseField name="cluster" type="string" required />

<ResponseField name="kind" type="string" required />

<ResponseField name="namespace" type="string" required />

<ResponseField name="name" type="string" required />

<ResponseField name="replicas" type="number" required>
  From 0 to 10,000.
</ResponseField>

<ResponseField name="reason" type="string" required />

### restart

Restarts a Deployment's, StatefulSet's or DaemonSet's pods, as `kubectl rollout restart` does: it sets the `kubectl.kubernetes.io/restartedAt` annotation on its pod template, which the diff shows, and the workload replaces its pods as its rollout does. Other kinds say so: "Only Deployments, StatefulSets and DaemonSets restart; Jobs don't."

<ResponseField name="cluster" type="string" required />

<ResponseField name="kind" type="string" required />

<ResponseField name="namespace" type="string" required />

<ResponseField name="name" type="string" required />

<ResponseField name="reason" type="string" required />

### delete\_resource

Deletes an object, as `kubectl delete` does. What it owns goes too, in the background, like a Deployment's ReplicaSets and their pods. Lumovi marks it as destructive for the assistant (MCP's `destructiveHint`).

* **It always asks**, even where the cluster allows assistants' changes. The approval dialog's button reads **Approve deletion**.
* **The name, where Lumovi's own Delete asks for it**: for a Namespace, Node, PersistentVolume, PersistentVolumeClaim, StorageClass or CustomResourceDefinition, and for any deletion in a cluster whose name looks like production. You type it before you can approve.
* **Only the object you saw.** The deletion names the object's uid, so one deleted and made again under the same name meanwhile isn't deleted.

<ResponseField name="cluster" type="string" required />

<ResponseField name="kind" type="string" required />

<ResponseField name="name" type="string" required />

<ResponseField name="namespace" type="string">
  Its namespace, for namespaced kinds.
</ResponseField>

<ResponseField name="reason" type="string" required />

## Waiting

A change waits in Lumovi for your answer up to five minutes, but the call that asks for it doesn't wait that long:

* **It waits up to about 50 seconds**, under the minute many assistants give a call. Then it returns, not as an error: "Still waiting for the person's answer in Lumovi: nothing has changed yet. Tell them to look at Lumovi, and call wait\_for\_change with id "…" to keep waiting for it." The change keeps waiting in Lumovi.
* **It says how it's going**, to an assistant that asks for progress (MCP's `progressToken`): "Waiting for the person to approve it in Lumovi", every 10 seconds or so.
* **Stopping it withdraws the change.** Cancel a call that's waiting, this one or a `wait_for_change`, and the change is withdrawn: it leaves Lumovi, and nothing is changed.

### wait\_for\_change

Waits for your answer to a change the assistant asked for, after its call said it's still waiting, up to about 50 seconds a call, and says what became of it:

* **Made**: what was done, and its command, as the call that asked would have said: "Scaled cart to 3 replicas, approved in Lumovi. The kubectl command that does the same: …".
* **Not made**: rejected, with your note; not approved in time; withdrawn; changed after it was shown; or failed, with why.
* **Still waiting**: the same message as the call that asked, to call it again.

You can answer while no call is waiting: the change is made, or not, all the same, and the next `wait_for_change` says how it went. Lumovi keeps the answer until a little after the change would have expired. After that, or for an id it doesn't know: "No change with id "…" is waiting: it was answered a while ago, or never asked for."

Cancelling it withdraws the change. Lumovi marks it as read-only for the assistant: it changes nothing itself.

<ResponseField name="id" type="string" required>
  The id the change's call gave.
</ResponseField>

## What's hidden

Lumovi leaves a few things out of the objects assistants read with `get_resource`, and out of those an approval shows you:

* **A Secret's values.** Each key of its `data` and `stringData` is kept, with `(hidden by Lumovi)` for its value.
* **`managedFields`**, which is long and says little.
* **The `kubectl.kubernetes.io/last-applied-configuration` annotation**, which repeats the object, and can hold a copy of a Secret's values.

What isn't in a Secret is shown as it is: a ConfigMap's data, environment variables written in a pod's spec, custom resources' fields, events' messages and what containers log. Keep that in mind for clusters that hold sensitive data outside Secrets.

<Columns cols={2}>
  <Card title="Approving changes" icon="check-check" href="/assistants/approvals">
    What a change shows you, and how to answer it.
  </Card>

  <Card title="Permissions" icon="lock-keyhole" href="/clusters/permissions#ai-assistants">
    What your account needs for each tool.
  </Card>
</Columns>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.