This guide walks through deploying the agentic controller, creating a Gateway with LLM credentials, defining an Agent, and creating an AgentRun to trigger execution.
- Kubernetes 1.33+ or OpenShift 4.20+ (the controller mounts skills via
the ImageVolume feature — a beta gate that is off by default on
Kubernetes 1.33–1.34, so enable
ImageVolumethere; it is on by default from 1.35 and GA in 1.36) - Agent Sandbox v0.5.x installed in the cluster
kubectlandhelmconfigured to talk to the cluster- LLM provider credentials (e.g. GCP Vertex AI, OpenAI, Anthropic, AWS Bedrock)
The controller creates Agent Sandbox CRs to run agent workloads. Agent Sandbox must be installed before the controller can execute AgentRuns.
AGENT_SANDBOX_TAG=v0.5.5
# Clone and install via Helm
git clone --depth 1 --branch $AGENT_SANDBOX_TAG \
https://github.com/kubernetes-sigs/agent-sandbox.git /tmp/agent-sandbox
helm install agent-sandbox /tmp/agent-sandbox/helm/ \
--namespace agent-sandbox-system \
--create-namespace \
--set image.tag=$AGENT_SANDBOX_TAG
# Wait for the controller to be ready
kubectl wait deployment/agent-sandbox-controller \
--namespace agent-sandbox-system \
--for=condition=Available \
--timeout=120sNote: The clone +
helm installpath above and the upstream release manifest (kubectl apply -f .../<tag>/sandbox-with-extensions.yaml) are alternative install methods — use one, not both. Mixing them makes helm andkubectl applyfight over the same cluster-scoped CRDs, and backing out means deleting those CRDs (taking every Sandbox on the cluster with them). Note also that the release assets were renamed at v0.5.2 (manifest.yaml→sandbox.yaml), so pin a v0.5.2+ tag if you follow the release-manifest path.
Future: OpenShell will replace the direct Agent Sandbox dependency. When integrated, the controller will provision sandboxes through the OpenShell gateway API instead of creating Sandbox CRs directly. See ADR 0004.
The default image quay.io/konveyor/agentic-controller:latest is public
and rebuilt on every merge to main, so you can deploy straight away
with no build step:
# Deploy CRDs, RBAC, and the controller manager
make deployTo build and push your own image instead (e.g. to test local changes),
set IMG to a registry you can push to:
export IMG=quay.io/<your-org>/agentic-controller:dev
make docker-build docker-push IMG=$IMG
make deploy IMG=$IMGThis creates the agentic-controller-system namespace and deploys
the controller. Verify it's running:
kubectl get pods -n agentic-controller-systemDeploy the default SkillCard and SkillCollection resources (these
are not included in make deploy to avoid name-prefix conflicts):
kubectl apply -k config/samples/To install only the CRDs without deploying the controller (e.g. for
local development with make run):
make installAlternatively, generate a single consolidated YAML containing CRDs and the controller deployment — useful when you don't want to build from source:
make build-installer IMG=$IMG
kubectl apply -f dist/install.yamlA Gateway represents a single LLM provider/model combination with credentials. Each Gateway serves exactly one model.
Note: Gateway replaces the former
LLMProviderCRD. If you have existingLLMProviderresources, they must be recreated as Gateways — one Gateway per provider/model combination.
The Secret commands below use --from-literal for brevity, which
records the key value in your shell history. For anything beyond a
throwaway test cluster, prefer --from-file (reading the value from a
protected file) or an external secret manager.
Create a Secret with your GCP application default credentials:
gcloud auth application-default login
kubectl create secret generic vertex-credentials \
--from-file=GOOGLE_APPLICATION_CREDENTIALS_JSON="$HOME/.config/gcloud/application_default_credentials.json" \
--from-literal=GCP_PROJECT_ID="$(gcloud config get-value project)" \
--from-literal=GCP_LOCATION=globalThe whole Secret is exposed to the agent via envFrom, so GCP_PROJECT_ID
and GCP_LOCATION ride along with the credentials file. goose's Vertex
provider requires GCP_PROJECT_ID (there is no default and the run
fails at first token without it). GCP_LOCATION is optional — goose
defaults to us-central1 — but global matches the sample Gateway
endpoint.
Apply the Gateway:
kubectl apply -f config/samples/gateway_vertex_ai.yamlkubectl create secret generic openai-credentials \
--from-literal=api-key="<your-openai-api-key>"
kubectl apply -f config/samples/gateway_openai.yamlkubectl create secret generic anthropic-credentials \
--from-literal=api-key="<your-anthropic-api-key>"
kubectl apply -f config/samples/gateway_anthropic.yamlkubectl create secret generic bedrock-credentials \
--from-literal=AWS_ACCESS_KEY_ID="<your-access-key-id>" \
--from-literal=AWS_SECRET_ACCESS_KEY="<your-secret-access-key>" \
--from-literal=AWS_REGION="us-east-1"
kubectl apply -f config/samples/gateway_aws_bedrock.yamlAWS_REGION is what goose actually uses to reach Bedrock — the harness
derives the Bedrock endpoint from it and ignores the Gateway endpoint,
which only feeds the controller's connectivity check. Keep the Gateway
endpoint in the same region as AWS_REGION so that check stays
meaningful. The model's us. prefix is a cross-region inference
profile spanning the US regions (us-east-1/us-east-2/us-west-2), so
switching between US regions needs no model change — only moving to
another geo (eu., apac.) requires a new prefix.
kubectl create secret generic grok-credentials \
--from-literal=api-key="<your-xai-api-key>"
kubectl apply -f config/samples/gateway_xai.yamlVerify the Gateway is ready:
kubectl get gateways.konveyor.ioNote: Use the fully-qualified
gateways.konveyor.iorather than the baregateways. On any cluster with the Gateway API CRDs installed (OpenShift 4.19+ does this by default),gatewaysresolves togateways.gateway.networking.k8s.ioinstead, sokubectl get gatewayswould report no resources right after you applied your Gateway.
The Verified column shows whether the controller confirmed
connectivity to the endpoint.
An Agent is a template that declares what is available for execution: a container image, gateways, skills, a prompt, and typed parameters. Creating an Agent does not execute anything.
Note: The example
agent_example.yamlandagentrun_example.yamlreference the Vertex AI Gateway (gcp-vertex-ai) from Option A. If you created a different Gateway (Options B–D), update thespec.gateways[].refin the Agent and thespec.gatewayin the AgentRun to match your Gateway's name before applying them.
Verify the default SkillCards were deployed (from step 2):
kubectl get skillcardsApply the example Agent:
kubectl apply -f config/samples/agent_example.yamlCheck that the Agent is ready (referenced Gateways and SkillCards must exist and be healthy):
kubectl get agentsAn AgentRun triggers execution of an Agent. It references an Agent, selects a Gateway, carries task-specific instructions, and sets the environment the entry point needs. The controller validates the configuration, creates an Agent Sandbox, and tracks the run to completion.
Prerequisite — Konveyor Hub. The
agent-javaimage resolves the repository to migrate and its git credentials from a Konveyor Hub, keyed byAPP_ID. Before running, install Hub —hack/install-konveyor.shinstalls the tackle2-operator with auth disabled — and register the application you want to migrate, noting itsAPP_ID. The sample AgentRun'sspec.envpoints at the in-cluster Hub service withAPP_ID: "1"; editHUB_BASE_URL,APP_ID, andTARGET_BRANCHto match your Hub and application. Hub-free standalone runs are not supported yet (#122).
Apply the example AgentRun:
kubectl apply -f config/samples/agentrun_example.yamlWatch the run:
kubectl get agentruns -wOnce the phase moves to Running, the Sandbox pod is live. View
agent logs:
# Get the sandbox pod name from the AgentRun status
SANDBOX=$(kubectl get agentrun migration-run-001 -o jsonpath='{.status.sandboxName}')
kubectl logs -f $SANDBOXThe AgentRun spec is immutable — to change values, delete the AgentRun and create a new one.
For multi-stage work (e.g. plan, execute, verify), use
AgentWorkflow and AgentWorkflowRun. See
hack/harness-test/workflow-resources.yaml for a complete example
that migrates a Java EE application to Quarkus using three stages.
All sample CRs are in config/samples/:
| File | Kind | Description |
|---|---|---|
gateway_vertex_ai.yaml |
Gateway | GCP Vertex AI with Claude |
gateway_openai.yaml |
Gateway | OpenAI GPT-4o |
gateway_anthropic.yaml |
Gateway | Anthropic direct API |
gateway_aws_bedrock.yaml |
Gateway | AWS Bedrock |
gateway_xai.yaml |
Gateway | xAI (Grok) |
agent_example.yaml |
Agent | Java migration agent |
agentrun_example.yaml |
AgentRun | Triggers the migration agent |
skillcard_*.yaml |
SkillCard | Migration skills (applied via kubectl apply -k config/samples/) |
skillcollection_*.yaml |
SkillCollection | Grouped skills (applied via kubectl apply -k config/samples/) |
Run the controller locally against a cluster (CRDs must be installed):
make install # Install CRDs
make run # Run the controller from your hostThe project includes scripts for running the full stack in a Kind cluster:
make e2e-setup # Create Kind cluster + deploy Agent Sandbox + controller
make e2e-run # Run e2e tests
make e2e-cleanup # Tear down the Kind clusterkubectl delete --all acts on the current namespace — set your
context (or add -n <namespace>) so you don't remove resources you
meant to keep:
# Delete runs, agents, and gateways in the current namespace
kubectl delete agentruns --all
kubectl delete agents --all
kubectl delete gateways.konveyor.io --allWarning:
make undeployandmake uninstalldelete the CRDs, which are cluster-scoped. Deleting a CRD removes every custom resource of that type across all namespaces — not just the ones from this guide. Run these only if you intend to tear down the controller entirely.
# Undeploy the controller
make undeploy
# Or just uninstall CRDs
make uninstallThe deployment method described here (kustomize / dist/install.yaml)
is a stopgap. The planned path is OLM-managed operator packaging,
which will provide catalog integration, upgrade lifecycle, and
dependency resolution for Agent Sandbox. The sample CRs in
config/samples/ are structured to be compatible with OLM bundle
conventions (one resource per file, no templated placeholders).
Gateway shows Verified: false
The controller could not reach the endpoint. Check:
- The endpoint URL is correct
- The credential Secret exists and has the right keys
- Network policies allow egress from the controller namespace
Agent shows Ready: False
The Agent references Gateways or SkillCards that don't exist or aren't ready. Check:
kubectl get gateways.konveyor.io— all referenced gateways must existkubectl get skillcards— all referenced skills must be resolved
AgentRun stuck in Pending
The controller is waiting for dependencies. Check:
- The referenced Agent is
Ready - The selected Gateway is in the Agent's gateway list
- Agent Sandbox is installed and healthy (step 1)
- Controller logs:
kubectl logs -n agentic-controller-system deploy/agentic-controller-controller-manager