Skip to content
Draft
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
16 changes: 7 additions & 9 deletions docs-site/content/kagent/1.x/agents/agent-harness.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ spec:
env:
- name: LOG_LEVEL
value: info
- name: MY_API_KEY
credentialRef:
name: my-secret
key: api-key
substrate:
workerPoolRef:
name: kagent-default
Expand All @@ -50,7 +46,7 @@ EOF
| `workload.image` | Yes | The runtime image, pinned by `sha256` digest. A tag alone is rejected, because a revision must be reproducible. |
| `workload.command` | For `byo` | Overrides the image entrypoint, up to 32 entries. Required for the `byo` runtime, optional otherwise. |
| `workload.args` | No | Overrides the image arguments, up to 64 entries. |
| `env` | No | Environment variables for the runtime, up to 100. Each entry sets either a literal `value` or a `credentialRef` naming a key in a same-namespace Secret, never both. |
| `env` | No | Environment variables for the runtime, up to 100. Each entry sets a literal `value`. A `credentialRef` is accepted by the API and then rejected at compile time on every runtime, so put credentials on a ModelConfig or a RemoteMCPServer instead. For more information, see [About model providers]({{< link path="setup/model-providers/about-model-providers#credentials-that-do-not-compile" >}}). |
| `substrate.workerPoolRef.name` | Yes | The {{< gloss "WorkerPool" >}}WorkerPool{{< /gloss >}} that this Harness's Actors are scheduled onto. An operator must provision one before any agent can run. |
| `substrate.snapshotPolicy.location` | Yes | The object storage location for Actor {{< gloss "Snapshot" >}}snapshots{{< /gloss >}}. |
| `allowedAgentTemplates.selector` | No | A label selector naming which AgentTemplates this Harness admits. Omitting it admits none, which makes the Harness unusable. Admission is a one-way match. An {{< gloss "AgentTemplate" >}}AgentTemplate{{< /gloss >}} has no field naming a Harness, so whoever controls a Harness's selector decides what it accepts. |
Expand Down Expand Up @@ -97,14 +93,16 @@ The runtime that a Harness selects decides which ModelConfig its AgentTemplates
| `OpenAI` | ✅ | ✅ | ✅ | ❌ |
| `Anthropic` | ✅ | ✅ | ❌ | ✅ |
| `Bedrock` | ✅ | ✅ | ✅ | ✅ |
| `AnthropicVertexAI` | ❌ | ❌ | ❌ | ✅ |
| `AnthropicVertexAI` | ❌ | ❌ | ❌ | ❌ |
| `GeminiVertexAI` | ❌ | ❌ | ❌ | ❌ |
| `AzureOpenAI` | ✅ | ✅ | ❌ | ❌ |
| `Gemini` | ✅ | ✅ | ❌ | ❌ |
| `Ollama` | ✅ | ✅ | ❌ | ❌ |
| `SAPAICore` | ✅ | ✅ | ❌ | ❌ |
| `SAPAICore` | ❌ | ❌ | ❌ | ❌ |
| `Foundry` | ✅ | ✅ | ❌ | ❌ |

`AnthropicVertexAI`, `GeminiVertexAI`, and `SAPAICore` run on no runtime today. Each authenticates with a credential that the egress gateway cannot place in an HTTP header, so kagent rejects the ModelConfig before it compiles. For the alternatives, see [About model providers]({{< link path="setup/model-providers/about-model-providers#credentials-that-do-not-compile" >}}).

Some supported combinations still carry restrictions.

| Combination | Restriction |
Expand All @@ -113,10 +111,10 @@ Some supported combinations still carry restrictions.
| `codex` with `Bedrock` | Accepts only OpenAI `gpt-*` model IDs, and no `bedrock` settings beyond `region`. |
| `claude` with `Anthropic` | Accepts no `anthropic` settings beyond `baseUrl`. |
| `claude` with `Bedrock` | Accepts no `bedrock` settings beyond `region`. |
| `claude` with `AnthropicVertexAI` | Accepts only `projectID` and `location`. The Secret must hold a `service_account` key whose `project_id` matches and whose `token_uri` is `https://oauth2.googleapis.com`. |
| `Bedrock` on any runtime | The Secret must hold an `AWS_BEARER_TOKEN_BEDROCK` key. A Secret of IAM access keys is rejected, because IAM signs each request locally. |

> [!IMPORTANT]
> Neither `codex` nor `claude` accepts a ModelConfig that sets `defaultHeaders`, `tls`, or `apiKeyPassthrough`. Separately, the `kagent` and `byo` runtimes cannot use a ModelConfig whose credential is a file rather than a string. This restriction rules out both Vertex AI providers there. For more information about that limitation, see [About model providers]({{< link path="setup/model-providers/about-model-providers" >}}).
> Neither `codex` nor `claude` accepts a ModelConfig that sets `defaultHeaders`, `tls`, or `apiKeyPassthrough`. Separately, every runtime rejects a credential that the egress gateway cannot place in an HTTP header, such as an IAM key pair or a Google service account key. For more information about that limitation, see [About model providers]({{< link path="setup/model-providers/about-model-providers#credentials-that-do-not-compile" >}}).

## Tool and skill support

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,52 @@ Every ModelConfig shares the same three parts, regardless of the provider that i

Credentials come from a Kubernetes Secret in the same namespace as the ModelConfig. The `apiKeySecret` field names the Secret, and `apiKeySecretKey` names the key within that Secret. To forward the bearer token from the incoming request to the provider instead, set `apiKeyPassthrough: true`. A ModelConfig cannot set both `apiKeyPassthrough` and `apiKeySecret`. For every ModelConfig field, including its type, default, and validation rules, see the [API reference]({{< link path="reference/api-ref#modelconfigspec" >}}).

**Credential files**
## How a credential reaches the provider

kagent passes model credentials to an agent as environment variables. A ModelConfig that instead requires a credential **file** mounted into the agent does not compile. The AgentTemplate reports the `Compatible` condition as `False`, with the reason `UnsupportedConfiguration` and the message `ModelConfig requires volume mounts unsupported by Substrate ActorTemplate`. kagent compiles no revision from that AgentTemplate, so no agent runs from it, and any AgentInstance that already exists keeps running the last revision that compiled. Three configurations encounter this today.
- **The Vertex AI providers, on the `kagent` and `byo` runtimes.** `GeminiVertexAI` and `AnthropicVertexAI` mount the Google credentials file that `apiKeySecret` names. Leaving `apiKeySecret` unset compiles, but a Substrate Actor does not inherit cloud workload identity, so the agent still has no credentials to send. The `claude` runtime is the exception: it passes the same credentials as an environment variable, so `AnthropicVertexAI` works there. For more information, see [Google Vertex AI]({{< link path="setup/model-providers/google-vertexai" >}}).
- **A private certificate authority (CA), on any provider.** Setting `tls.caCertSecretRef` mounts the CA bundle as a file. Every provider accepts the `tls` block, so this affects all of them, not only the Vertex AI providers. You cannot reach a provider endpoint that presents a certificate from a private CA, unless you set `tls.disableVerify: true`, which skips certificate verification entirely and belongs only in a test environment.
- **OpenAI token exchange.** The `openAI.tokenExchange` block acquires a bearer token by reading a mounted service account file, so a ModelConfig that sets it never compiles. An OpenAI-compatible endpoint must accept a static API key instead. For more information, see [OpenAI]({{< link path="setup/model-providers/openai" >}}).
A credential never enters the agent. kagent compiles the Secret that a ModelConfig names into a destination-scoped binding, and the {{< gloss "Agent Substrate" >}}Agent Substrate{{< /gloss >}} egress gateway fetches the Secret and writes the value into an outgoing HTTP header. Where an SDK requires an API key, the runtime receives the inert placeholder `kagent-credential-injected`. A compiled {{< gloss "Revision" >}}revision{{< /gloss >}} therefore records the Secret name, key, destination, and header, and never the credential itself.

To rotate a credential, update the Secret. The gateway refreshes its cache within five minutes, so neither a recompile nor a restart is needed.

Each provider carries its credential in the one header that the provider expects, and the destination is the endpoint that the ModelConfig resolves to.

| Credential | Header |
| ---------- | ------ |
| `OpenAI` API key | `authorization: Bearer <key>` |
| `Anthropic` API key | `x-api-key: <key>` |
| `AzureOpenAI` API key, and `Foundry` in OpenAI format | `api-key: <key>` |
| `Foundry` API key in Anthropic format | `x-api-key: <key>` |
| `Gemini` API key | `x-goog-api-key: <key>` |
| `Bedrock` bearer token | `authorization: Bearer <token>` |
| A Secret-backed `RemoteMCPServer` header | The header that the server names |

Substrate matches a destination on the exact DNS hostname, without path, port, or scheme. Two credentials that target the same hostname and header are rejected, including a conflict between an agent's model, a memory embedding model, and an MCP server. Give such origins distinct DNS names. A destination given as an IP address cannot carry an injected credential at all.

### Credentials that do not compile

Header injection accepts one shape of credential: a static string. A credential that requires a local signature, a token exchange, or a file mounted into the agent cannot be injected, so kagent rejects the configuration instead of passing the credential to the runtime. The AgentTemplate reports the `Compatible` condition as `False` with the reason `UnsupportedConfiguration`, and kagent compiles no revision from that template. Any AgentInstance that already exists keeps running the last revision that compiled.

| Configuration | Why it cannot be injected | What to use instead |
| ------------- | ------------------------- | ------------------- |
| `Bedrock` with `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` | IAM keys sign each request locally. | A Bedrock bearer token in `AWS_BEARER_TOKEN_BEDROCK`. See [Amazon Bedrock]({{< link path="setup/model-providers/amazon-bedrock" >}}). |
| `AnthropicVertexAI` and `GeminiVertexAI` | A Google service account key is signed locally to obtain a token, and the `kagent` and `byo` runtimes also mount it as a file. | `Anthropic` or `Bedrock` for Claude models, and `Gemini` for Gemini models. See [Google Vertex AI]({{< link path="setup/model-providers/google-vertexai" >}}). |
| `SAPAICore` | OAuth2 client credentials are exchanged for a token before any request. | A provider that authenticates with an API key. See [SAP AI Core]({{< link path="setup/model-providers/sap-ai-core" >}}). |
| A `credentialRef` in a Harness `spec.env` entry | An arbitrary variable names no destination and no header to bind it to. | A ModelConfig or a RemoteMCPServer, each of which carries a destination. See [Agent harness]({{< link path="agents/agent-harness#configure-a-harness" >}}). |
| `openAI.tokenExchange` | The block reads a mounted service account file to acquire a token. | An endpoint that accepts a static API key. See [OpenAI]({{< link path="setup/model-providers/openai" >}}). |
| `tls.caCertSecretRef`, on any provider | The CA bundle is mounted as a file. | An endpoint whose certificate chains to a public CA. Setting `tls.disableVerify: true` skips certificate verification entirely and belongs only in a test environment. |

A rejected credential reports one of two messages. A credential that cannot be injected reports `cannot use gateway header injection`, and one that needs a mounted file reports `ModelConfig requires volume mounts unsupported by Substrate ActorTemplate`.

The `Ollama` provider is unaffected, because it authenticates with no credential.

## The Harness runtime decides which providers are available

A ModelConfig is only half of the decision. The runtime that a {{< gloss "Harness" >}}Harness{{< /gloss >}} selects also constrains which providers an agent can use, because each runtime integrates a different set.

- The **`kagent`** runtime supports every provider, and the **`byo`** runtime supports the same set, because both compile through the same path.
- The **`codex`** runtime supports only `OpenAI` and `Bedrock`.
- The **`claude`** runtime supports only `Anthropic`, `Bedrock`, and `AnthropicVertexAI`.
- The **`kagent`** runtime integrates every provider, and the **`byo`** runtime integrates the same set, because both compile through the same path.
- The **`codex`** runtime integrates only `OpenAI` and `Bedrock`.
- The **`claude`** runtime integrates only `Anthropic` and `Bedrock`.

Integration alone is not enough. A provider whose credential cannot be injected as a header is rejected on every runtime that integrates it, so `AnthropicVertexAI`, `GeminiVertexAI`, and `SAPAICore` run nowhere today. For the alternatives, see [Credentials that do not compile](#credentials-that-do-not-compile).

Neither `codex` nor `claude` accepts a ModelConfig that sets `defaultHeaders`, `tls`, or `apiKeyPassthrough`, and each narrows the provider settings it takes. A pair that asks for a provider its runtime does not integrate fails to compile, and the AgentTemplate reports the `Compatible` condition as `False` with the reason `UnsupportedConfiguration`.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,36 @@ Amazon Bedrock serves models from several families behind one AWS API. {{< reuse
Prefer the native provider. If you need the OpenAI request format, or an inference profile that only that endpoint exposes, use the OpenAI-compatible path.

> [!NOTE]
> Bedrock is the only provider that every runtime supports. A `codex` Harness accepts only OpenAI `gpt-*` model IDs, and both `codex` and `claude` accept no `bedrock` settings beyond `region`. For more information, see [Agent harness]({{< link path="agents/agent-harness#model-provider-support" >}}).
> Bedrock is the only provider that every runtime supports, and on every one of them the credential must be a bearer token. A `codex` Harness accepts only OpenAI `gpt-*` model IDs, and both `codex` and `claude` accept no `bedrock` settings beyond `region`. For more information, see [Agent harness]({{< link path="agents/agent-harness#model-provider-support" >}}).

> [!IMPORTANT]
> Both paths authenticate with credentials from a Kubernetes Secret. Attaching an AWS IAM role to the agent, such as with [EKS IAM Roles for Service Accounts](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html), is not currently supported: an agent runs as a Substrate Actor rather than as a pod that kagent controls, so there is no per-agent ServiceAccount to attach a role to.

## Before you begin

1. Create an IAM user or role with permissions for Bedrock. At minimum you need `bedrock:InvokeModel` for the models that you use. For more information, see the [AWS Bedrock model access docs](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html).
1. Grant the identity that issues your API key permission to call Bedrock. At minimum you need `bedrock:InvokeModel` for the models that you use. For more information, see the [AWS Bedrock model access docs](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html).

2. Choose an AWS region and a Bedrock model, and confirm that your account has access to that model in that region. For the available models, see the [AWS Bedrock supported models docs](https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html).

## Native Bedrock provider

1. Create a Kubernetes Secret that stores your AWS access keys. Create it in the same namespace as the AgentTemplates that use it, such as `kagent`.
The native provider authenticates with a Bedrock API key, which kagent sends as a bearer token.

1. Create a Bedrock API key. For more information, see the [AWS Bedrock API keys guide](https://docs.aws.amazon.com/bedrock/latest/userguide/getting-started-api-keys.html).
```bash
export AWS_BEARER_TOKEN_BEDROCK=<your-bedrock-api-key>
```

2. Create a Kubernetes Secret that holds the token under the key `AWS_BEARER_TOKEN_BEDROCK`. kagent looks that key up by name, so no other key works. Create the Secret in the same namespace as the AgentTemplates that use it, such as `kagent`.
```bash
kubectl create secret generic bedrock-credentials -n kagent \
--from-literal AWS_ACCESS_KEY_ID=<your-access-key> \
--from-literal AWS_SECRET_ACCESS_KEY=<your-secret-key>
--from-literal AWS_BEARER_TOKEN_BEDROCK=$AWS_BEARER_TOKEN_BEDROCK
```

2. Create a `ModelConfig` that uses the `Bedrock` provider.
> [!IMPORTANT]
> A Secret that holds `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` instead does not work on any runtime. IAM credentials sign each request locally, and an agent reaches its provider through an egress gateway that injects a static header, so kagent rejects the ModelConfig at compile time. The AgentTemplate reports the `Compatible` condition as `False` with the message `environment credential "AWS_ACCESS_KEY_ID" cannot use gateway header injection`. For more information, see [About model providers]({{< link path="setup/model-providers/about-model-providers#credentials-that-do-not-compile" >}}).

3. Create a `ModelConfig` that uses the `Bedrock` provider.
```yaml
kubectl apply -f - <<EOF
apiVersion: kagent.dev/v1alpha3
Expand All @@ -49,7 +58,7 @@ Prefer the native provider. If you need the OpenAI request format, or an inferen

| Field | Description |
| ----- | ----------- |
| `apiKeySecret` | The name of the Kubernetes Secret that holds `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`. |
| `apiKeySecret` | The name of the Kubernetes Secret that holds `AWS_BEARER_TOKEN_BEDROCK`. |
| `model` | The Bedrock model ID. For the format, see the [AWS Bedrock model IDs](https://docs.aws.amazon.com/bedrock/latest/userguide/model-ids.html). |
| `provider` | The provider to use, `Bedrock`. |
| `bedrock.region` | The AWS region that serves the model. This field is required. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ author: kagent.dev
The `Anthropic` provider calls the Anthropic API directly.

> [!NOTE]
> This provider works on the `kagent`, `byo`, and `claude` runtimes, but not on `codex`. A `claude` Harness accepts no `anthropic` settings beyond `baseUrl`. For more information, see [Agent harness]({{< link path="agents/agent-harness#model-provider-support" >}}). To reach Claude models through Google Cloud instead, see [Google Vertex AI]({{< link path="setup/model-providers/google-vertexai" >}}).
> This provider works on the `kagent`, `byo`, and `claude` runtimes, but not on `codex`. A `claude` Harness accepts no `anthropic` settings beyond `baseUrl`. For more information, see [Agent harness]({{< link path="agents/agent-harness#model-provider-support" >}}). Claude models served through Google Cloud Vertex AI do not run on 1.0. For the reason and the alternatives, see [Google Vertex AI]({{< link path="setup/model-providers/google-vertexai" >}}).

## Create the ModelConfig

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ weight: 20
author: kagent.dev
---

The `Gemini` provider reaches Google's Gemini models through the Google AI Studio API, authenticating with a single API key. To reach Gemini through Google Cloud instead, see [Google Vertex AI]({{< link path="setup/model-providers/google-vertexai" >}}).
The `Gemini` provider reaches Google's Gemini models through the Google AI Studio API, authenticating with a single API key. Gemini models served through Google Cloud Vertex AI do not run on 1.0. For the reason, see [Google Vertex AI]({{< link path="setup/model-providers/google-vertexai" >}}).

## Before you begin

Expand Down
Loading
Loading