Manage Resources with GitOps
GitOps keeps the definition of your Agentic Data Plane (ADP) resources in Git and reconciles the live environment toward those files, instead of running imperative create, update, and delete commands by hand. With the ADP CLI, rpk ai <resource> apply -f creates what is missing and updates what has drifted, and rpk ai <resource> diff -f is a read-only dry-run that reports what apply would change. In these commands, <resource> is one of the resource command groups that support GitOps:
-
LLM providers (
rpk ai llm) -
MCP servers (
rpk ai mcp) -
OAuth providers (
rpk ai oauth) -
OAuth clients (
rpk ai oauth-client) -
Agents (
rpk ai agent)
After reading this page, you will be able to:
-
Export an ADP resource to a YAML manifest you can commit to Git
-
Reconcile resources with apply, and preview changes with diff
-
Gate continuous integration on configuration drift
Prerequisites
-
The ADP CLI installed and connected to an ADP environment.
-
Permission to create and update the resources you manage. The reconcile commands call the same APIs as
createandupdate. See Roles and Permissions Reference. -
Any secrets your manifests reference already created in ADP. Manifests name secrets by reference, for example,
OPENAI_API_KEY; the CLI does not create secrets.
How apply and diff reconcile
A manifest is plain resource YAML: the same shape a get -o yaml dump produces. The CLI compares each manifest against the live resource of the same name and resolves one of three outcomes:
- Create
-
No resource of that name exists, so
applycreates it. - Update
-
The resource exists and a field in the manifest differs from the live value, so
applyupdates the differing fields. - Unchanged
-
The resource exists and every field the manifest names already matches.
The reconcile rules are deliberate, and they are not the same as a full-object replace:
- Presence drives updates
-
A field that is present in the manifest and differs from the live resource is updated. A field you omit is left untouched. To clear a field, write it explicitly with an empty or zero value.
- Collections replace wholesale
-
Lists, maps, and provider or backend variants are replaced as a unit, not merged element by element.
- Create-only fields are immutable
-
A field that can be set only at creation time, such as an LLM provider’s
type, an MCP server’s backend kind, an OAuth provider’sclient_id, or an agent’s managed-or-self-managed kind, cannot change on an existing resource. Changing one is an error that tells you to delete and recreate the resource. - Secrets stay by reference
-
Manifests reference secrets by name, for example,
api_key_refandclient_secret_ref, and never contain secret values, so a manifest is safe to commit to Git.
The apply command does not delete resources that are absent from your manifests; there is no prune. The diff command checks only the fields a manifest names, so it does not detect a resource that exists in the environment but is missing from your manifests, nor drift in a field a manifest omits.
Export a resource to a manifest
Start from a live resource so the manifest is complete. Dump it to YAML and redirect it to a file:
rpk ai llm get openai -o yaml > openai.yaml
A dumped OpenAI provider looks like this, ready to commit:
'@type': type.googleapis.com/redpanda.api.adp.v1alpha1.LLMProvider
created_at: "2026-06-20T10:15:30Z"
display_name: OpenAI
enabled: true
name: openai
openai_config:
api_key_ref: OPENAI_API_KEY
provider_models:
- name: gpt-4o
- name: gpt-4o-mini
type: LLM_PROVIDER_TYPE_OPENAI
updated_at: "2026-06-20T10:15:30Z"
url: https://openai.aigw.d0example1cluster234.clusters.cloud.redpanda.com/openai/v1
The @type line records the resource kind. It is optional when you apply with a resource command, because rpk ai llm apply already implies the kind, but keeping it lets a reader and any validator know what the file describes.
|
The |
Preview changes with diff
Edit the manifest, then preview the effect before you touch the environment. For example, change the display name:
display_name: OpenAI (production)
Run diff to see the plan:
rpk ai llm diff -f openai.yaml
~ openai (update: display_name)
The diff command marks each manifest with one of three symbols and changes nothing:
| Symbol | Meaning |
|---|---|
|
The |
|
The |
|
The resource already matches; |
The diff command exits with a non-zero status when any change is pending, and zero when the environment already matches every manifest. That exit code is what lets continuous integration gate on drift.
Apply changes
Reconcile the environment toward the manifest:
rpk ai llm apply -f openai.yaml
The apply command prints one line per manifest as it works:
updated openai (display_name)
A first-time apply of a resource that does not yet exist prints created openai instead, and a manifest that already matches the environment prints unchanged openai. The CLI plans every manifest before it changes anything, so a malformed manifest aborts the run before any write. If a later write fails, the lines already printed tell you exactly what was applied.
Apply many manifests at once
The -f flag is repeatable and accepts a file, a directory, or a stream:
# A directory of manifests; the CLI reads every .yaml and .yml file, sorted by name.
rpk ai mcp apply -f ./manifests/
# Several paths in one run.
rpk ai llm apply -f openai.yaml -f anthropic.yaml
# Standard input, for piping a manifest from another tool.
rpk ai oauth apply -f -
A single file can hold more than one manifest. Separate documents with a line containing only ---.
Gate continuous integration on drift
Because diff exits non-zero when the environment differs from your manifests, a continuous-integration job can fail the build whenever the live environment has drifted from Git:
# Fails the job if an apply would change anything.
rpk ai llm diff -f ./llm/
rpk ai mcp diff -f ./mcp/
A common pipeline runs diff on a pull request to preview changes, then runs apply after the merge to roll them out:
# Deploy step, after merge to the main branch.
rpk ai llm apply -f ./llm/
rpk ai mcp apply -f ./mcp/
Manifests are declarative
A manifest describes the full intended state, so an omitted field means zero, not the convenience default that create fills in. A manifest that omits enabled creates a disabled resource, and diff then reports no drift, because the disabled state matches the manifest.
To avoid surprises:
-
Start from a
get -o yamldump, which is already complete, rather than hand-writing a manifest from scratch. -
Set
enabled: trueexplicitly when you want an active resource.
One subtlety follows from this: a dump of an already-disabled resource omits enabled, because false is the field’s zero value and the dump omits zero values. Reapplying that dump elsewhere also produces a disabled resource.
Troubleshooting
| Symptom | Resolution |
|---|---|
The |
You changed a create-only field, such as an LLM provider’s |
The |
A key in the manifest is not a field of the resource. The CLI rejects unknown keys rather than dropping them silently. Fix the key. Start from a |
The |
The |
A field you changed in the environment keeps coming back after |
The |