For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.
Solo Enterprise for kagent
Connect Solo Enterprise for agentregistry to a Solo Enterprise for kagent runtime so that you can deploy agents from the registry to your Kubernetes cluster.
Solo Enterprise for kagent is a Kubernetes-native AI runtime that Solo Enterprise for agentregistry uses to deploy and manage agents and MCP servers as pods in your cluster. When you connect a kagent runtime, the registry server calls the kagent controller’s management API by using its own OIDC service identity to create, update, and delete workloads on your behalf. One registry can connect to multiple kagent clusters at once. For a detailed breakdown of how the components fit together, see Runtime architectures.
Before you begin
Set up an OIDC provider. This guide assumes that you installed Keycloak. Make sure to follow the Solo Enterprise for kagent tab to install Keycloak with the required realm settings, clients, and secrets.
Verify that you have the following environment variables set before continuing.
echo "KEYCLOAK_ISSUER: $KEYCLOAK_ISSUER" echo "AR_BACKEND_SECRET: $AR_BACKEND_SECRET" echo "KAGENT_BACKEND_SECRET: $KAGENT_BACKEND_SECRET" echo "AGENTREGISTRY_OUTBOUND_SECRET: $AGENTREGISTRY_OUTBOUND_SECRET"Log in to the registry. Choose between the interactive device authorization and the static username and password credential flow.
Use this flow for interactive logins from a terminal. The CLI uses the
ar-cli-interactivepublic client and starts a device authorization grant flow that prints a URL and a one-time code for you to approve in a browser.Configure the CLI to use the Keycloak issuer and
ar-cli-interactiveclient. Then, log in to Solo Enterprise for agentregistry.export OIDC_ISSUER=$KEYCLOAK_ISSUER export OIDC_CLIENT_ID=ar-cli-interactive arctl user loginExample output:
To complete the login process, please: 1. Open: http://172.18.0.13:8080/realms/agentregistry/device 2. Enter the code: SYSQ-SNSP - or go to: http://172.18.0.13:8080/realms/agentregistry/device?user_code=SYSQ-SNSPOpen the URL in a web browser and log into Keycloak with the
admin-userusername andpasswordpassword. Confirming the code in the browser tells Keycloak to issue an access token for the CLI session. After authorization is complete, the CLI stores the token in your system keychain so you do not have to log in again until it expires.
Use this flow for scripted logins where a specific user identity is required in CI/CD pipelines. The CLI uses the
ar-cli-passwordpublic client and exchanges a username and password directly for an access token.Log in to Solo Enterprise for agentregistry with the
admin-user/passwordcredentials.export OIDC_ISSUER=$KEYCLOAK_ISSUER arctl user login \ --oidc-flow=password-credentials \ --oidc-client-id=ar-cli-password \ --oidc-username=admin-user \ --oidc-password=passwordSave the access token in the
ARCTL_API_TOKENenvironment variable.export ARCTL_API_TOKEN=$(arctl user info --show-tokens | jq -r .access_token)
Step 1: Install Solo Enterprise for kagent
Save your Solo Enterprise for kagent license key in an environment variable. To obtain the key, contact an account representative. If you prefer to specify the license key in a secret instead, see Licensing.
export KAGENT_LICENSE_KEY="<key>"Save the API key for the LLM that you want to use as an environment variable. This example uses Gemini. For a list of supported LLMs, see Supported LLMs in the Solo Enterprise for kagent documentation.
export GOOGLE_API_KEY="<key>"Set the Solo Enterprise for kagent patch version. This example uses the latest version. You can find other versions in the reference documentation.
export KAGENT_ENT_VERSION=0.5.6Install the
kagent-mgmtchart for Solo Enterprise for kagent.helm upgrade -i kagent-mgmt \ oci://us-docker.pkg.dev/solo-public/solo-enterprise-helm/charts/management \ -n kagent --create-namespace \ --version "$KAGENT_ENT_VERSION" \ --set cluster=mgmt-cluster \ --set products.kagent.enabled=true \ --set products.agentregistry.enabled=true \ --set-string licensing.licenseKey="$KAGENT_LICENSE_KEY" \ --set-string oidc.issuer="$KEYCLOAK_ISSUER" \ --set-string ui.backend.oidc.clientId=kagent-backend \ --set-string ui.backend.oidc.secret="$KAGENT_BACKEND_SECRET" \ --set-string ui.frontend.oidc.clientId=kagent-uiVerify that the management component pods have a status of
Running.kubectl get po -n kagent- The
clickhousepod runs a ClickHouse exporter for local data storage. - The
uipod runs the UI that you can use to monitor and manage agents. - The
telemetry-collectorpod runs the OTel collector that collects telemetry data from your cluster.
NAME READY STATUS RESTARTS AGE kagent-mgmt-clickhouse-shard0-0 1/1 Running 0 4s solo-enterprise-telemetry-collector-0 1/1 Running 0 4s solo-enterprise-ui-76c85c7d6b-xftcj 5/5 Running 0 4s- The
Install the kagent-enterprise CRDs chart.
helm upgrade --install kagent-crds \ oci://us-docker.pkg.dev/solo-public/kagent-enterprise-helm/charts/kagent-enterprise-crds \ -n kagent \ --version "$KAGENT_ENT_VERSION"Create an OBO token for the Solo Enterprise for kagent controller and store it in a Kubernetes secret. The controller watches for a secret named
jwtin its own namespace and uses the token to provide authentication so that agents can execute actions on behalf of the user. If the secret is missing, the OBO token handler stays in anot readystate and A2A chat requests to agents fail with anupstream auth failed: obo token handler not readyerror.openssl genrsa -out /tmp/key.pem 2048 kubectl create secret generic jwt \ -n kagent --from-file=jwt=/tmp/key.pem \ --dry-run=client -o yaml | kubectl apply -f -Create a values file for the RBAC configuration in Solo Enterprise for kagent.
roleMappingsis a lookup table that maps a Keycloak group name to a Solo Enterprise for kagent role. In this guide, any token that carriesagentregistryin itsGroupsclaim is granted theglobal.Writerrole in Solo Enterprise for kagent. Tokens with otherGroupsclaim values or tokens that do not have aGroupsclaim at all, are denied with a 401 Unauthorized response.cat > /tmp/kagent-rbac.yaml << 'EOF' rbac: roleMapping: roleMapper: 'has(claims.Groups) ? claims.Groups.transformList(i, v, v in rolesMap, rolesMap[v]) : []' roleMappings: agentregistry: global.Writer EOFInstall the
kagent-enterprisechart to deploy the Solo Enterprise for kagent controller and UI.helm upgrade -i kagent \ oci://us-docker.pkg.dev/solo-public/kagent-enterprise-helm/charts/kagent-enterprise \ -n kagent \ --version "$KAGENT_ENT_VERSION" \ --set-string licensing.licenseKey="$KAGENT_LICENSE_KEY" \ --set agents.k8s-agent.enabled=true \ --set kagent-tools.enabled=true \ --set kmcp.licensing.createSecret=false \ --set-string oidc.issuer="$KEYCLOAK_ISSUER" \ --set oidc.clientId=kagent-backend \ --set-string oidc.secret="$KAGENT_BACKEND_SECRET" \ --set providers.openAI.apiKey=$GOOGLE_API_KEY \ -f /tmp/kagent-rbac.yamlVerify that the controller and UI deployments are ready.
kubectl get po -n kagentExample output:
kagent-controller-dfc4c966c-zzds5 1/1 Running 0 3m kagent-mgmt-clickhouse-shard0-0 1/1 Running 0 5m48s kagent-postgresql-57c4f5597f-x4mjg 1/1 Running 0 3m kagent-tools-69bdb559df-cb9bw 1/1 Running 0 3m kmcp-enterprise-controller-manager-dbd59bcbf-j5hjt 1/1 Running 0 3m solo-enterprise-telemetry-collector-0 1/1 Running 0 5m48s solo-enterprise-ui-66cbb6687c-6czzk 4/4 Running 0 5m48s
Step 2: Connect to Solo Enterprise for kagent
Create a Runtime resource that points Solo Enterprise for agentregistry at the Solo Enterprise for kagent controller you deployed in Step 1. Choose between the following setup paths:
- General setup: Choose this tab if you run Solo Enterprise for kagent in a standard Kubernetes cluster.
- Inject AWS credentials at agent runtime: Choose this tab if you installed Solo Enterprise for kagent in an AWS EKS cluster and your deployed agents need AWS credentials injected at runtime to access other AWS services, such as an S3 bucket.
Use these instructions for a standard Kubernetes setup where deployed agents do not need AWS credentials. If your agents need to call AWS services such as Bedrock AgentCore, use the Inject AWS credentials at agent runtime tab instead.
Create a Solo Enterprise for agentregistry Secret that stores the client secret for the
agentregistryKeycloak client. The runtime references this secret when it mints outbound tokens to call the Solo Enterprise for kagent controller.arctl apply -f- <<EOF apiVersion: ar.dev/v1alpha1 kind: Secret metadata: name: kagent-oidc spec: type: Opaque stringData: clientSecret: "$AGENTREGISTRY_OUTBOUND_SECRET" EOFExample output:
✓ Secret/kagent-oidc appliedCreate the Solo Enterprise for kagent runtime in Solo Enterprise for agentregistry. The runtime points to the Solo Enterprise for kagent controller that you deployed to the
kagentnamespace. Theauth.oidcblock tells the registry server which credentials to use when it calls the kagent controller on your behalf.arctl apply -f- <<EOF apiVersion: ar.dev/v1alpha1 kind: Runtime metadata: name: kagent spec: type: Kagent telemetryEndpoint: http://agentregistry-enterprise-telemetry-collector.agentregistry-system.svc.cluster.local:4318 config: kagentUrl: http://kagent-controller.kagent:8083 namespace: kagent auth: oidc: issuer: $KEYCLOAK_ISSUER clientId: agentregistry clientSecretRef: name: kagent-oidc key: clientSecret EOFExample output:
✓ Runtime/kagent appliedNote
If your kagent controller uses Microsoft Entra ID as the OIDC provider, add a
scopefield to theauth.oidcblock as shown in the following snippet. Entra requires ascopeparameter onclient_credentialsrequests that Keycloak does not include by default. Setscopeto the application ID URI of your kagent app registration followed by/.default.auth: oidc: issuer: https://login.microsoftonline.com/<tenant-id>/v2.0 clientId: <entra-client-id> scope: api://<kagent-app-id>/.default clientSecretRef: name: kagent-oidc key: clientSecretList the runtimes that are connected to Solo Enterprise for agentregistry and verify that the
kagentruntime is listed. You also see a defaultkubernetes-defaultandlocalruntime.arctl get runtimesExample output:
NAME TYPE kagent Kagent kubernetes-default Kubernetes local Local virtual-default Virtual
Use these instructions if Solo Enterprise for kagent runs on an Amazon EKS cluster and your deployed agents need AWS credentials, such as to call AWS Bedrock AgentCore agents or access an S3 bucket. Solo Enterprise for agentregistry automatically creates an EKS Pod Identity Association (PIA) before each agent deployment. This way, the agent pod gets the AWS credentials injected on first start with no manual setup and no restart required. The association is deleted when you delete the agent deployment.
Important
Solo Enterprise for agentregistry must be installed with EKS Pod Identity enabled (aws.usePodIdentity=true). If you followed the AWS Bedrock AgentCore quickstart, this is already in place and the role name is agentregistry-pod-identity-role. Cross-account is not supported. The EKS cluster and the pod execution role must be in the same AWS account as Solo Enterprise for agentregistry.
If not already installed, enable the EKS Pod Identity Agent add-on on your EKS cluster.
aws eks create-addon --cluster-name $EKS_CLUSTER_NAME --addon-name eks-pod-identity-agent --region $AWS_REGIONCreate the IAM role that agent pods assume and save the role ARN as an environment variable.
Create the trust policy file.
cat > pod-execution-trust-policy.json << 'EOF' { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": {"Service": "pods.eks.amazonaws.com"}, "Action": ["sts:AssumeRole", "sts:TagSession"] } ] } EOFCreate the IAM role and save its ARN.
export POD_EXECUTION_ROLE_NAME="kagent-agent-pod-execution-role" aws iam create-role \ --role-name "$POD_EXECUTION_ROLE_NAME" \ --assume-role-policy-document file://pod-execution-trust-policy.json export POD_EXECUTION_ROLE_ARN=$(aws iam get-role \ --role-name "$POD_EXECUTION_ROLE_NAME" \ --query 'Role.Arn' --output text) echo "POD_EXECUTION_ROLE_ARN: $POD_EXECUTION_ROLE_ARN"
Set the name of your EKS cluster and Solo Enterprise for agentregistry’s IAM role, then derive the cluster ARN.
export EKS_CLUSTER_NAME=<eks-cluster-name> export AGENTREGISTRY_ROLE_NAME=<agentregistry-iam-role-name> export EKS_CLUSTER_ARN=$(aws eks describe-cluster \ --name "$EKS_CLUSTER_NAME" \ --query 'cluster.arn' \ --output text) echo "EKS_CLUSTER_ARN: $EKS_CLUSTER_ARN"If you are not sure what the Solo Enterprise for agentregistry IAM role name is, look it up from the existing Pod Identity Association.
aws eks list-pod-identity-associations \ --cluster-name "$EKS_CLUSTER_NAME" \ --namespace agentregistry-system \ --query 'associations[].{SA:serviceAccount,Role:roleArn}' \ --output tableGrant Solo Enterprise for agentregistry’s IAM role permission to manage Pod Identity Associations on your cluster and to pass the pod execution role you created in the previous step to agent pods.
aws iam put-role-policy \ --role-name "$AGENTREGISTRY_ROLE_NAME" \ --policy-name "AgentRegistryPodIdentity" \ --policy-document "{ \"Version\": \"2012-10-17\", \"Statement\": [ { \"Effect\": \"Allow\", \"Action\": [ \"eks:CreatePodIdentityAssociation\", \"eks:DeletePodIdentityAssociation\", \"eks:ListPodIdentityAssociations\" ], \"Resource\": \"$EKS_CLUSTER_ARN\" }, { \"Effect\": \"Allow\", \"Action\": \"iam:PassRole\", \"Resource\": \"$POD_EXECUTION_ROLE_ARN\" } ] }"Create a Solo Enterprise for agentregistry Secret that stores the client secret for the
agentregistryKeycloak client.arctl apply -f- <<EOF apiVersion: ar.dev/v1alpha1 kind: Secret metadata: name: kagent-oidc spec: type: Opaque stringData: clientSecret: "$AGENTREGISTRY_OUTBOUND_SECRET" EOFExample output:
✓ Secret/kagent-oidc appliedCreate the Solo Enterprise for kagent runtime. The
auth.connectionblock tells Solo Enterprise for agentregistry to create a Pod Identity Association for each agent it deploys to this runtime.arctl apply -f- <<EOF apiVersion: ar.dev/v1alpha1 kind: Runtime metadata: name: kagent spec: type: Kagent telemetryEndpoint: http://agentregistry-enterprise-telemetry-collector.agentregistry-system.svc.cluster.local:4318 config: kagentUrl: http://kagent-controller.kagent:8083 namespace: kagent auth: oidc: issuer: $KEYCLOAK_ISSUER clientId: agentregistry clientSecretRef: name: kagent-oidc key: clientSecret connection: type: aws aws: podExecutionRoleArn: $POD_EXECUTION_ROLE_ARN clusterArn: $EKS_CLUSTER_ARN EOFField Description auth.connection.typeSet to awsto enable EKS Pod Identity.auth.connection.aws.podExecutionRoleArnThe ARN of the IAM role to attach to agent pods. auth.connection.aws.clusterArnThe ARN of the EKS cluster. Required when using pod identity. Example output:
✓ Runtime/kagent appliedNote
If your kagent controller uses Microsoft Entra ID as the OIDC provider, add a
scopefield to theauth.oidcblock as shown in the following snippet. Entra requires ascopeparameter onclient_credentialsrequests that Keycloak does not include by default. Setscopeto the application ID URI of your kagent app registration followed by/.default.auth: oidc: issuer: https://login.microsoftonline.com/<tenant-id>/v2.0 clientId: <entra-client-id> scope: api://<kagent-app-id>/.default clientSecretRef: name: kagent-oidc key: clientSecretList the runtimes that are connected to Solo Enterprise for agentregistry and verify that the
kagentruntime is listed.arctl get runtimesExample output:
NAME TYPE kagent Kagent kubernetes-default Kubernetes local Local virtual-default Virtual
Step 3: Optional: Install Solo Enterprise for Istio
Runtime authorization with AccessPolicies requires Solo Enterprise for Istio (ambient mesh) and Solo Enterprise for agentgateway. Together, they provide the ztunnel and waypoint proxy infrastructure that enforces AccessPolicies at the network level before any request reaches its target.
Note
This step is optional for basic agent deployment. You only need it if you want to restrict which MCP server tools an agent can invoke at runtime.
Install ambient mesh
Save your Solo Enterprise for Istio license key in an environment variable. The license key is included with your Solo Enterprise for kagent license. To obtain the key, contact an account representative.
export SOLO_ISTIO_LICENSE_KEY=<key>Save the Solo distribution of Istio version and image repository details.
export ISTIO_VERSION=1.29.6 export ISTIO_IMAGE=${ISTIO_VERSION}-solo export REPO=us-docker.pkg.dev/soloio-img/istio export HELM_REPO=us-docker.pkg.dev/soloio-img/istio-helmApply the Kubernetes Gateway API CRDs, which are required for waypoint proxies and other components.
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.5.0/standard-install.yamlInstall the
istio-basechart, which contains the CRDs and cluster roles required to set up Istio.helm upgrade --install istio-base oci://${HELM_REPO}/base \ --namespace istio-system \ --create-namespace \ --version ${ISTIO_IMAGE} \ -f - <<EOF defaultRevision: "" profile: ambient EOFCreate the
istiodcontrol plane.helm upgrade --install istiod oci://${HELM_REPO}/istiod \ --namespace istio-system \ --version ${ISTIO_IMAGE} \ -f - <<EOF global: hub: ${REPO} proxy: clusterDomain: cluster.local tag: ${ISTIO_IMAGE} meshConfig: accessLogFile: /dev/stdout defaultConfig: proxyMetadata: ISTIO_META_DNS_AUTO_ALLOCATE: "true" ISTIO_META_DNS_CAPTURE: "true" env: PILOT_ENABLE_IP_AUTOALLOCATE: "true" PILOT_SKIP_VALIDATE_TRUST_DOMAIN: "true" pilot: cni: namespace: istio-system enabled: true profile: ambient license: value: ${SOLO_ISTIO_LICENSE_KEY} EOFInstall the Istio CNI node agent daemonset.
helm upgrade --install istio-cni oci://${HELM_REPO}/cni \ --namespace istio-system \ --version ${ISTIO_IMAGE} \ -f - <<EOF ambient: dnsCapture: true excludeNamespaces: - istio-system - kube-system global: hub: ${REPO} tag: ${ISTIO_IMAGE} profile: ambient EOFInstall the ztunnel daemonset.
helm upgrade --install ztunnel oci://${HELM_REPO}/ztunnel \ --namespace istio-system \ --version ${ISTIO_IMAGE} \ -f - <<EOF configValidation: true enabled: true env: L7_ENABLED: "true" hub: ${REPO} istioNamespace: istio-system namespace: istio-system profile: ambient proxy: clusterDomain: cluster.local tag: ${ISTIO_IMAGE} terminationGracePeriodSeconds: 29 variant: distroless EOFVerify that the ambient mesh components are running.
kubectl get pods -n istio-systemExample output:
NAME READY STATUS RESTARTS AGE istio-cni-node-ps9vs 1/1 Running 0 80s istiod-58f745c977-q94jj 1/1 Running 0 94s ztunnel-7df9l 1/1 Running 0 62sEnroll the
kagentnamespace in the ambient mesh. This label tells ztunnel to intercept traffic for all pods in the namespace so that traffic flows through the waypoint proxies where AccessPolicies are enforced. Without this label, agent-to-MCP traffic bypasses the waypoints and policies are never applied.kubectl label namespace kagent istio.io/dataplane-mode=ambientVerify that the label was applied.
kubectl get namespace kagent --show-labelsExample output:
NAME STATUS AGE LABELS kagent Active 10m istio.io/dataplane-mode=ambient,kubernetes.io/metadata.name=kagent
Install Solo Enterprise for agentgateway
Solo Enterprise for agentgateway deploys waypoint proxies that enforce AccessPolicies. You must install it after the ambient mesh.
Save your Solo Enterprise for agentgateway license key in an environment variable. The license key is included with your Solo Enterprise for kagent license.
export AGENTGATEWAY_LICENSE_KEY=<key>Deploy the Solo Enterprise for agentgateway CRDs and control plane.
helm upgrade -i enterprise-agentgateway-crds \ oci://us-docker.pkg.dev/solo-public/enterprise-agentgateway/charts/enterprise-agentgateway-crds \ --create-namespace \ --namespace agentgateway-system \ --version v2026.7.0 helm upgrade -i enterprise-agentgateway \ oci://us-docker.pkg.dev/solo-public/enterprise-agentgateway/charts/enterprise-agentgateway \ --namespace agentgateway-system \ --version v2026.7.0 \ --set licensing.licenseKey=${AGENTGATEWAY_LICENSE_KEY}Verify that agentgateway is running.
kubectl get pods -n agentgateway-systemExample output:
NAME READY STATUS RESTARTS AGE enterprise-agentgateway-5495d98459-46dpk 1/1 Running 0 19s