Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@
*** xref:gateway:bedrock-setup.adoc[Set Up AWS Bedrock as an LLM Provider]
** xref:gateway:connect-agent.adoc[Connect Your App to AI Gateway]

* xref:cli:index.adoc[Use the ADP CLI]
** xref:cli:gitops.adoc[Manage Resources with GitOps]

* xref:reference:index.adoc[Reference]
** xref:reference:rpk-install.adoc[Install or Update rpk]
** xref:reference:rpk/index.adoc[rpk Command Reference]
Expand Down
225 changes: 225 additions & 0 deletions modules/cli/pages/gitops.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
= Manage Resources with GitOps
:page-beta: true
:description: Keep ADP resources in Git and reconcile them with rpk ai apply and diff: declarative create-or-update, drift detection, and CI gating.
:page-topic-type: how-to
:personas: platform_engineer, agent_builder
:learning-objective-1: Export an ADP resource to a YAML manifest you can commit to Git
:learning-objective-2: Reconcile resources with apply, and preview changes with diff
:learning-objective-3: Gate continuous integration on configuration drift

// Source: cloudv2 `apps/rpai/internal/gitops/` (engine.go, command.go, manifest.go, doc.go), the per-resource policies in `apps/rpai/internal/cmd/{llm,mcp,oauth,oauthclient,agent}/gitops.go`, `proto/public/cloud/redpanda/api/adp/v1alpha1/llm_provider.proto`, and `rpk ai <resource> apply|diff --help`. Console output verified against the engine and `apps/rpai/internal/gitops/engine_test.go`. Verified against origin/main 2026-06-26.

GitOps keeps the definition of your glossterm: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 xref:cli:index.adoc[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:

* [ ] {learning-objective-1}
* [ ] {learning-objective-2}
* [ ] {learning-objective-3}

== Prerequisites

* The xref:cli:index.adoc[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 `create` and `update`. See xref:control:permissions-reference.adoc[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 `apply` creates it.

Update::
The resource exists and a field in the manifest differs from the live value, so `apply` updates 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's `client_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_ref` and `client_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:

[,bash]
----
rpk ai llm get openai -o yaml > openai.yaml
----

A dumped OpenAI provider looks like this, ready to commit:

[,yaml]
----
'@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.

[NOTE]
====
The `created_at`, `updated_at`, and `url` fields are server-managed and read-only. The `apply` command ignores them, so you can leave them in the file or strip them. The `api_key_ref` value is a reference to a secret, not the key itself.
====

== Preview changes with diff

Edit the manifest, then preview the effect before you touch the environment. For example, change the display name:

[,yaml]
----
display_name: OpenAI (production)
----

Run `diff` to see the plan:

[,bash]
----
rpk ai llm diff -f openai.yaml
----

[,text]
----
~ openai (update: display_name)
----

The `diff` command marks each manifest with one of three symbols and changes nothing:

[cols="1m,3"]
|===
|Symbol |Meaning

|+
|The `apply` command would create the resource.

|~
|The `apply` command would update the resource. The changed fields follow in parentheses.

|=
|The resource already matches; `apply` would leave it unchanged.
|===

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:

[,bash]
----
rpk ai llm apply -f openai.yaml
----

The `apply` command prints one line per manifest as it works:

[,text]
----
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:

[,bash]
----
# 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:

[,bash]
----
# 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:

[,bash]
----
# 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 yaml` dump, which is already complete, rather than hand-writing a manifest from scratch.
* Set `enabled: true` explicitly 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

[cols="2,3"]
|===
|Symptom |Resolution

|The `apply` or `diff` command reports that a field is immutable and tells you to delete and recreate the resource.
|You changed a create-only field, such as an LLM provider's `type` or an OAuth provider's `client_id`. Restore the original value, or delete the resource and recreate it from the new manifest.

|The `apply` or `diff` command fails to decode the manifest and mentions unknown or misspelled fields.
|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 `get -o yaml` dump to get the exact field names.

|The `diff` command reports no drift, but you know the environment has extra resources.
|The `diff` and `apply` commands never prune. They act only on the resources your manifests name. Delete unwanted resources with `rpk ai <resource> delete`.

|A field you changed in the environment keeps coming back after `apply`.
|The `apply` command overwrites a field only when the manifest names it and the value differs. If the change is not in your manifest, add it, then reapply.
|===

== Next steps

* xref:cli:index.adoc[]
* xref:gateway:configure-provider.adoc[]
* xref:connect:create-server.adoc[]
153 changes: 153 additions & 0 deletions modules/cli/pages/index.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
= Use the ADP CLI
:page-beta: true
:description: Manage Agentic Data Plane resources from the terminal with rpk ai. Install the CLI, connect it to an AI Gateway, and script LLM providers, MCP servers, OAuth, and agents.
:page-topic-type: how-to
:personas: platform_engineer, agent_builder
:learning-objective-1: Install the ADP CLI and connect it to an AI Gateway
:learning-objective-2: Manage ADP resources from the terminal: LLM providers, MCP servers, OAuth providers and clients, and agents
:learning-objective-3: Format command output for scripts and pipelines

// Source: cloudv2 `apps/rpai/README.md`, `apps/rpai/internal/cmd/root.go` (plugin-mode command surface + persistent flags), `apps/rpai/internal/cmd/env/cmd.go`, and `rpk ai <command> --help`, cross-referenced against `modules/gateway/pages/connect-agent.adoc` and `modules/reference/pages/rpk/rpk-ai/`. Connect/auth model reflects cloudv2 PR #27510: rpk ai is self-contained (its own `auth login` device flow + ADP environment selection), not tied to the rpk cloud session. Verified against origin/main 2026-06-29 (cloudv2 PR #27510 merged).

The ADP command-line interface, `rpk ai`, manages glossterm:Agentic Data Plane (ADP)[] resources from your terminal. It drives the same control surface as the ADP UI: glossterm:large language model (LLM)[] providers, glossterm:Model Context Protocol (MCP)[] servers, OAuth providers and clients, and agents. Because every action is a command, you can script it and run it in continuous integration.

The ADP CLI, also called the Redpanda AI CLI, runs as an xref:reference:rpk/rpk-ai/rpk-ai.adoc[`rpk`] plugin, so you install and run it through your existing `rpk` setup.

After reading this page, you will be able to:

* [ ] {learning-objective-1}
* [ ] {learning-objective-2}
* [ ] {learning-objective-3}

== Install the CLI

The ADP CLI is an `rpk` managed plugin. Install `rpk` first (see xref:reference:rpk-install.adoc[Install or Update rpk]), then install the plugin:

[,bash]
----
rpk ai install
----

Update the plugin later with xref:reference:rpk/rpk-ai/rpk-ai-upgrade.adoc[`rpk ai upgrade`], and remove it with xref:reference:rpk/rpk-ai/rpk-ai-uninstall.adoc[`rpk ai uninstall`].

== Connect to an AI Gateway

The `rpk ai` command is self-contained: it has its own login and its own environment selection, independent of any `rpk cloud` session. You sign in once, choose an ADP environment, and `rpk ai` targets that environment's AI Gateway for every command.

. Sign in to Redpanda Cloud. This runs an OAuth device-authorization flow in your browser, caches credentials in `~/.rpai/credentials` (readable only by you), then lists the ADP environments in your organization so you can pick one:
+
[,bash]
----
rpk ai auth login
----

. List the environments available to you, and switch the active one by name or ID:
+
[,bash]
----
rpk ai env list
rpk ai env use <environment>
----
+
In these commands, `<environment>` is the name or ID of an ADP environment. `rpk ai env use` repoints the active profile at that environment's AI Gateway in place. Inspect the resolved environment and token state at any time with `rpk ai env show` and `rpk ai auth status`.

. Verify the connection:
+
[,bash]
----
rpk ai llm list
----

For the full setup walkthrough, including token expiry behavior and the supported environment variables, see xref:gateway:connect-agent.adoc#authenticate-with-rpk-ai[Use `rpk ai` for local development].

To target a different AI Gateway URL for a single command without switching environments, pass `--rpai-endpoint`:

[,bash]
----
rpk ai --rpai-endpoint https://aigw.<cluster-id>.clusters.cloud.redpanda.com llm list
----

This overrides the selected environment's AI Gateway URL for that one command; the flag is not bound to an environment variable. For a local or manual gateway you use repeatedly, define it once as an environment with `rpk ai env add`:

[,bash]
----
rpk ai env add local --ai-gateway-url http://localhost:8090 --auth-mode none
rpk ai env use local
----

== Manage resources

Each ADP resource has its own command group, and each group supports the standard `create`, `get`, `list`, `update`, and `delete` actions. The model catalog is read-only.

[cols="1m,2,1a"]
|===
|Command |Manages |Reference

|rpk ai llm
|LLM providers (OpenAI, Anthropic, Google, AWS Bedrock, and OpenAI-compatible endpoints)
|xref:reference:rpk/rpk-ai/rpk-ai-llm.adoc[`rpk ai llm`]

|rpk ai mcp
|MCP servers and their tools
|xref:reference:rpk/rpk-ai/rpk-ai-mcp.adoc[`rpk ai mcp`]

|rpk ai oauth
|OAuth providers for user-delegated MCP connections
|xref:reference:rpk/rpk-ai/rpk-ai-oauth.adoc[`rpk ai oauth`]

|rpk ai oauth-client
|OAuth clients that external tools use to reach an MCP server
|xref:reference:rpk/rpk-ai/rpk-ai-oauth-client.adoc[`rpk ai oauth-client`]

|rpk ai agent
|Agents in the agent registry
|xref:reference:rpk/rpk-ai/rpk-ai-agent.adoc[`rpk ai agent`]

|rpk ai model
|The model catalog (read-only discovery)
|xref:reference:rpk/rpk-ai/rpk-ai-model.adoc[`rpk ai model`]
|===

For example, to create and inspect an LLM provider:

[,bash]
----
rpk ai llm create --name openai --type openai --api-key-ref OPENAI_API_KEY
rpk ai llm get openai
----

In this command, `--api-key-ref` names a secret already stored in ADP. The CLI never takes a raw API key, so secrets stay out of your shell history and out of any file you commit.

To create, update, and delete resources declaratively from YAML manifests instead of imperative flags, see xref:cli:gitops.adoc[Manage Resources with GitOps].

== Format command output

Every `list` and `get` command honors `-o` (`--format`):

[cols="1m,3"]
|===
|Format |Use

|table
|Default. Human-readable columns.

|wide
|Table with extra columns.

|json
|Machine-readable JSON for scripts and `jq`.

|yaml
|YAML. A `get -o yaml` dump is a complete manifest you can edit and reapply.

|markdown
|Pipe-friendly tables for documents.
|===

Set a default for the session with the `RPAI_FORMAT` environment variable. The `-o` flag always wins when both are set.

== Next steps

* xref:cli:gitops.adoc[]
* xref:gateway:configure-provider.adoc[]
* xref:reference:rpk/rpk-ai/rpk-ai.adoc[]
2 changes: 1 addition & 1 deletion modules/connect/pages/create-server.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ rpk ai mcp update github-proxy \

// TODO(rpk-ai): --auth-config does not exist on `rpk ai mcp create` today (verified against cloudv2/apps/rpai/internal/cmd/mcp/cmd.go on 2026-05-05). For non-convenience auth shapes, encode them inside `--managed-config` JSON. Re-add this row if a flag lands later.

The command resolves the gateway URL from your active rpk cloud profile and reads the cached `rpk cloud login` token.
The command targets the AI Gateway of your selected ADP environment, using credentials from `rpk ai auth login`.

== Edit, disable, and delete a server

Expand Down
Loading