一键导入
deploy-agents
Deploy agents to OpenShift with auto-detected cluster config and refresh MLflow tracking tokens.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Deploy agents to OpenShift with auto-detected cluster config and refresh MLflow tracking tokens.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | deploy-agents |
| description | Deploy agents to OpenShift with auto-detected cluster config and refresh MLflow tracking tokens. |
| argument-hint | <agent_paths or 'all'> [--token-only] |
Usage:
/agentic-starter-kits-skills:deploy-agents crewai/templates/websearch_agent— deploy one agent/agentic-starter-kits-skills:deploy-agents crewai/templates/websearch_agent langgraph/templates/react_agent— deploy multiple/agentic-starter-kits-skills:deploy-agents all— deploy all standard agents/agentic-starter-kits-skills:deploy-agents --token-only— only refresh MLflow tokens, no deployment
You are deploying agents to the agentic-mcp OpenShift cluster. This skill automates cluster config detection, .env generation, container build/push, Helm deployment, and MLflow token refresh.
Arguments: $ARGUMENTS
Parse the arguments to determine:
agents/ (e.g., crewai/templates/websearch_agent), or all--token-only is present, skip Steps 1–3 and go directly to Step 4If no arguments are provided, ask the user what to deploy.
Gate system: Pre-conditions and post-conditions are defined in
references/eval-criteria-deploy-validate.json. The PreToolUse/PostToolUse hooks fire automatically viascripts/eval-hook.py.
Run these checks in parallel. Fail immediately if any required tool is missing.
oc whoami # must be authenticated
oc project -q # capture current namespace — ALL operations scoped here
helm version --short # must be installed
If deploying (not --token-only), also check for a container CLI:
podman version 2>/dev/null || docker version 2>/dev/null
If the container CLI is podman, verify the podman machine is running:
podman machine list --format '{{.Name}}' # check if any machine exists
If no machine is listed, warn the user: "No podman machine found. Run podman machine init to create one before deploying."
If a machine exists, check whether it's running:
podman info >/dev/null 2>&1
If podman info fails, warn the user: "Podman machine exists but is not running. Start it with podman machine start before deploying." Do not auto-start the machine — the user may have stopped it intentionally.
Podman/Docker fallback: The agent Makefiles auto-detect the container CLI via command -v podman || command -v docker. If podman is installed but not running, the Makefile picks podman and fails. When Docker is available as a fallback, pass CONTAINER_CLI=docker to all make build, make push, and make deploy commands (e.g., make build CONTAINER_CLI=docker). Store whichever CLI is working and use it consistently.
Store the namespace from oc project -q — use explicit -n <namespace> on every oc command for the rest of this workflow. Never rely on the default context.
Check whether the MLflow operator CRD exists (indicates RHOAI 3.5+):
oc get crd mlflowoperators.components.platform.opendatahub.io 2>/dev/null
If the CRD exists (RHOAI 3.5+):
oc get datasciencecluster -o json | jq '.items | length'
If the count is 0, warn the user: "No DataScienceCluster found — RHOAI may not be installed correctly." If the count is greater than 1, warn: "Multiple DataScienceClusters found — checking the first one, but this is unexpected."
Then check the operator state:
oc get datasciencecluster -o json | jq '.items[0].spec.components.mlflowoperator.managementState'
If it returns "Removed", the MLflow tracking server is not deployed — all tracing will fail. Warn the user that mlflowoperator must be set to Managed in the DataScienceCluster CR before agents can trace.
oc get pods -n redhat-ods-applications -l app=mlflow --no-headers 2>/dev/null | grep -c Running
If this returns 0, the MLflow tracking server is not running — all tracing will fail. Warn the user that the MLflow pod must be running before agents can trace. Check if mlflowoperator is set to Managed (see check above) and whether the pod is in a non-Running state (CrashLoopBackOff, Pending, etc.).
RESOURCE_DOES_NOT_EXIST: Workspace '<namespace>' not found ... matches the configured selector ('mlflow-tracking in (enabled)').oc get namespace <namespace> -o jsonpath='{.metadata.labels.mlflow-tracking}'
If the label is missing or not set to enabled, apply it:
oc label namespace <namespace> mlflow-tracking=enabled
If the CRD does not exist (RHOAI < 3.5): Skip these checks — the standalone MLflow service is managed differently in older versions and does not require namespace labeling.
Gate:
agentic-starter-kits-skills:deploy-agents.step-0a-mlflow-infra— consult eval-criteria. Verify MLflow infrastructure is ready.
If argument is all:
agents/ (structure: agents/<framework>/templates/<agent>/) that contain both agent.yaml and a MakefileCHART_DIR pointing to ../../deployment or a helm upgrade command)langflow/templates/simple_tool_calling_agent (docker-compose based, uses COMPOSE_FILE instead of Helm)If specific paths given:
agents/<path>/agent.yaml exists (paths can be either <framework>/<agent> or <framework>/templates/<agent> — resolve both)helm upgrade in their Makefile)Report the final list of agents to deploy before proceeding.
Gate:
agentic-starter-kits-skills:deploy-agents.step-1-resolve— consult eval-criteria. Verify agent directories (agents/<framework>/templates/<agent>/), agent.yaml, Makefile exist; non-standard agents (docker-compose based) excluded.
Detect config from existing deployments in the namespace to avoid asking the user for values they've already configured.
oc get deployments -n <namespace> -o json
From the first standard agent deployment found, extract:
| Value | Source |
|---|---|
BASE_URL | env var from deployment spec |
MODEL_ID | env var from deployment spec |
API_KEY | from the deployment's referenced secret (base64-decode) |
MLFLOW_TRACKING_URI | env var from deployment spec |
MLFLOW_EXPERIMENT_NAME | env var from deployment spec |
MLFLOW_TRACKING_INSECURE_TLS | env var from deployment spec |
MLFLOW_WORKSPACE | env var from deployment spec |
| Container image registry prefix | from deployment image spec (e.g., quay.io/adonheis/) |
Security: Never log, display, or include API_KEY or MLFLOW_TRACKING_TOKEN values in output. These are sensitive credentials — extract them silently and write them only to .env files (which are gitignored).
If no existing deployments are found in the namespace, ask the user for all required values.
Gate:
agentic-starter-kits-skills:deploy-agents.step-2-config— consult eval-criteria. Verify config values extracted and credentials not logged.
Loop over each resolved agent. For each:
oc get deployment <agent-name> -n <namespace> 2>/dev/null
If it already exists, ask the user whether to redeploy or skip.
Read agent.yaml in the agent directory to discover required env vars. For agents with extra requirements beyond the standard set (e.g., POSTGRES_* for db-memory agents, MCP_SERVER_URL for autogen agents):
Check if the container image already exists in the registry:
podman manifest inspect <registry>/<image>:<tag> 2>/dev/null || skopeo inspect docker://<registry>/<image>:<tag> 2>/dev/null
agent.yamlWrite the .env file in the agent directory with:
MLFLOW_TRACKING_TOKEN from oc whoami -tMLFLOW_WORKSPACE set to the current namespace (oc project -q) — mandatory for OpenShift MLflow, without it the MLflow API returns "Workspace context is required"MLFLOW_TRACKING_INSECURE_TLS=true (required when the cluster does not use trusted certificates)CONTAINER_IMAGE using registry prefix + agent nameNever commit .env files — they are already in .gitignore.
If building:
cd agents/<path>
make build CONTAINER_CLI=<container-cli>
make push CONTAINER_CLI=<container-cli>
cd agents/<path>
make deploy CONTAINER_CLI=<container-cli>
Where <container-cli> is the working container CLI determined in Step 0 (e.g., docker or podman).
Wait a few seconds for the pod to start, then:
# Get the route
oc get route <agent-name> -n <namespace> -o jsonpath='{.spec.host}'
# Health check
# -k disables TLS verification — acceptable for dev/test clusters only
curl -sk https://<route>/health
Note: /health returns 200 OK even when MLflow tracing is broken — it only checks that the agent process is running. Tracing is verified separately in Step 4f.
If health check fails, check pod status and logs:
oc get pods -n <namespace> -l app.kubernetes.io/name=<agent-name> --sort-by=.metadata.creationTimestamp
oc logs deployment/<agent-name> -n <namespace> --tail=30
Report the result (healthy/unhealthy) and move to the next agent.
Gate:
agentic-starter-kits-skills:deploy-agents.step-3-deployandagentic-starter-kits-skills:deploy-agents.step-3g-health— consult eval-criteria. Verify .env written, deployment succeeded, health OK.
This step always runs — even with --token-only, even if no agents were just deployed. It refreshes tokens for every agent in the namespace, not just the ones targeted in this run.
TOKEN=$(oc whoami -t)
TOKEN_B64=$(echo -n "$TOKEN" | base64)
oc get secrets -n <namespace> -o json | jq -r '.items[] | select(.data["mlflow-tracking-token"] != null) | .metadata.name'
Warning — Helm field ownership: oc patch secret takes field ownership of .data.mlflow-tracking-token away from Helm. This causes subsequent make deploy (which uses helm upgrade --install with server-side apply) to fail with: conflict with "kubectl-patch" using v1: .data.mlflow-tracking-token.
For each secret found, update the token while preserving Helm's field ownership:
oc get secret <secret-name> -n <namespace> -o json \
| jq ".data[\"mlflow-tracking-token\"]=\"$TOKEN_B64\"" \
| oc apply --server-side --force-conflicts --field-manager=helm -f -
This uses server-side apply with --field-manager=helm so Helm retains ownership and future make deploy won't conflict. This intentionally impersonates Helm's field manager identity — using a different manager name would re-introduce the conflict. The trade-off is that field ownership audit trails will attribute this change to Helm rather than the skill.
If you already have a conflict from a previous oc patch: delete the secret (oc delete secret <secret-name>) and run helm uninstall <release> followed by make deploy to do a clean install that restores Helm's field ownership.
For each agent whose token was refreshed:
oc rollout restart deployment/<agent-name> -n <namespace>
After patching secrets, verify each deployment actually reads the token from the secret (not a hardcoded value). For each agent:
oc get deployment <agent-name> -n <namespace> -o json | jq '.spec.template.spec.containers[0].env[] | select(.name == "MLFLOW_TRACKING_TOKEN")'
Expected (correct — reads from secret):
{
"name": "MLFLOW_TRACKING_TOKEN",
"valueFrom": { "secretKeyRef": { "name": "<agent>-secret", "key": "mlflow-tracking-token" } }
}
Broken (hardcoded — secret patch will have no effect):
{
"name": "MLFLOW_TRACKING_TOKEN",
"value": "sha256~..."
}
If any deployment has a hardcoded value instead of valueFrom.secretKeyRef, the secretKeyRef was overwritten — likely by a previous oc set env command. Fix by redeploying via make deploy from the agent directory (with a fresh token in .env). This restores the Helm-managed secretKeyRef. Do NOT use oc set env to set MLFLOW_TRACKING_TOKEN — it replaces the secretKeyRef with a plain value.
Gate:
agentic-starter-kits-skills:deploy-agents.step-4-tokensandagentic-starter-kits-skills:deploy-agents.step-4e-secretref— consult eval-criteria. Verify all secrets patched, rollouts restarted, no hardcoded tokens.
For each agent, wait for rollout and check startup logs for tracing status:
oc rollout status deployment/<agent-name> -n <namespace> --timeout=120s
oc logs deployment/<agent-name> -n <namespace> 2>&1 | grep -E "\[Tracing\]|ERROR.*mlflow|ERROR.*crewai"
Healthy — look for:
[Tracing] MLflow server is reachable at ...
[Tracing Enabled] MLflow -> ..., Experiment: ..., LLM Provider: ...
Broken — look for:
[Tracing] Failed to configure MLflow tracing ... Error: Expecting value: line 1 column 1 (char 0)
This JSONDecodeError means the MLflow API returned a non-JSON response (usually a 302 OAuth redirect because the token is expired/invalid).
Also check for these RHOAI 3.5+ error patterns:
RESOURCE_DOES_NOT_EXIST: Workspace '<namespace>' not found ... matches the configured selector ('mlflow-tracking in (enabled)')
Fix: the namespace needs the mlflow-tracking=enabled label — see Step 0a.
401 {"error_code":"UNAUTHENTICATED","message":"Authentication to the MLflow tracking server failed..."}
Fix: the MLflow operator is not deployed or the tracking server is not running — see Step 0a.
To confirm, test the token directly against the MLflow API:
TOKEN=$(oc get secret <agent-name>-secret -n <namespace> -o jsonpath='{.data.mlflow-tracking-token}' | base64 -d)
MLFLOW_URI=$(oc get deployment <agent-name> -n <namespace> -o jsonpath='{.spec.template.spec.containers[0].env[?(@.name=="MLFLOW_TRACKING_URI")].value}')
curl -sk -H "Authorization: Bearer $TOKEN" "$MLFLOW_URI/api/3.0/mlflow/server-info"
{"store_type":"SqlStore",...}) means the token is validVerify health as in Step 3g. Remember that /health returns 200 OK even when tracing is broken — always check the startup logs for [Tracing Enabled] to confirm tracing is working.
Gate:
agentic-starter-kits-skills:deploy-agents.step-4f-mlflow— consult eval-criteria. Verify rollouts complete, tracing enabled in logs, no JSONDecodeError.
Print a summary table:
Agent | Status | Route | Health | Token
-----------------------------------------|-------------|------------------------------------------|--------|--------
crewai/templates/websearch_agent | deployed | websearch-agent-agentic-mcp.apps.xxx | OK | refreshed
langgraph/templates/react_agent | redeployed | react-agent-agentic-mcp.apps.xxx | OK | refreshed
langgraph/templates/human_in_the_loop | skipped | hitl-agent-agentic-mcp.apps.xxx | OK | refreshed
autogen/templates/mcp_agent | failed | — | — | —
If any agents failed, show the failure reason and suggest next steps.
Gate:
agentic-starter-kits-skills:deploy-agents.post— consult eval-criteria. Verify all steps completed and summary was generated.
Scope note: This section is reference material for debugging EvalHub eval runs. It is not part of the deployment workflow (Steps 0-5).
The EvalHub adapter runs as a pod inside the cluster and needs to communicate with MLflow. This section documents known environmental issues that cause mlflow_run_id: null in eval results.
The adapter pod has two containers:
The sidecar injects these env vars into the adapter container:
MLFLOW_TRACKING_URI=http://localhost:8080 — but the sidecar only proxies EvalHub API calls, not MLflow API calls (returns 400 unknown proxy call for MLflow paths)MLFLOW_TRACKING_SERVER_CERT_PATH=/etc/pki/ca-trust/source/anchors/service-ca.crt — OpenShift service CA cert for internal TLSMLFLOW_TRACKING_TOKEN — auth token from the provider registrationThe adapter code reads mlflow_tracking_uri from the benchmark parameters (in the eval YAML config) and passes it to MLflowTraceClient, which calls mlflow.set_tracking_uri() — overriding the sidecar's MLFLOW_TRACKING_URI env var.
MLFLOW_TRACKING_INSECURE_TLS conflicts with MLFLOW_TRACKING_SERVER_CERT_PATHSymptom: MlflowException: When 'ignore_tls_verification' is true then 'server_cert_path' must not be set!
Cause: The run-e2e.sh script passes MLFLOW_TRACKING_INSECURE_TLS=true as a provider env var. The sidecar also mounts the service CA cert at MLFLOW_TRACKING_SERVER_CERT_PATH. MLflow SDK 3.12+ refuses to accept both simultaneously.
Fix: Do NOT set MLFLOW_TRACKING_INSECURE_TLS in the provider env vars. The service CA cert is the correct path for in-cluster TLS verification.
Symptom: SSLCertVerificationError: certificate verify failed: unable to get local issuer certificate
Cause: The run-e2e.sh script discovers the MLflow URI from agent deployments, which use the external route (e.g., https://rh-ai.apps.rosa.<cluster>/mlflow). This external route's certificate is signed by a public CA, but the adapter pod only has the OpenShift service CA cert mounted — it can't validate the external route's certificate.
Fix: Use the internal service URL for mlflow_tracking_uri in the eval YAML benchmark parameters: https://mlflow.redhat-ods-applications.svc.cluster.local:8443. The adapter pod's mounted service CA cert can validate this internal endpoint.
Symptom: 400 unknown proxy call: /api/3.0/mlflow/server-info
Cause: The sidecar's MLFLOW_TRACKING_URI=http://localhost:8080 env var implies the sidecar proxies MLflow, but the sidecar (v0.3.0) only proxies EvalHub API calls (/api/v1/evaluations/...). MLflow SDK 3.x calls /api/3.0/mlflow/server-info which the sidecar doesn't recognize.
Fix: Do NOT use http://localhost:8080 as mlflow_tracking_uri. Use the internal service URL instead. The MLFLOW_TRACKING_URI env var set by the sidecar is misleading for direct MLflow SDK usage.
/mlflow path suffixSymptom: Active workspace 'X' cannot be used because the remote server does not support workspaces.
Cause: The EvalHub deployment's MLFLOW_TRACKING_URI is https://mlflow.redhat-ods-applications.svc.cluster.local:8443/mlflow — it includes a /mlflow path prefix that the EvalHub Go code uses for its own routing. When the Python MLflow SDK uses this URI, it appends /api/3.0/mlflow/server-info after the path, hitting a different endpoint that doesn't support workspaces. The SDK then fails because MLFLOW_WORKSPACE is set but the server says it doesn't support workspaces.
Fix: Strip the path suffix when discovering the internal URI from the EvalHub deployment. The Python MLflow SDK only needs the base URL (https://mlflow.redhat-ods-applications.svc.cluster.local:8443). The run-e2e.sh script does this automatically with urlparse.
In the provider registration JSON:
MLFLOW_TRACKING_INSECURE_TLS in the Env arrayMLFLOW_TRACKING_TOKEN, MLFLOW_WORKSPACE, and EVALHUB_ALLOW_LOCALHOSTIn the eval YAML benchmark parameters:
mlflow_tracking_uri to the internal MLflow service URL (discovered dynamically via MLFLOW_INTERNAL_URI in run-e2e.sh)MLFLOW_TRACKING_URI env var, or falls back to the MLflow service in redhat-ods-applicationsMLFLOW_TRACKING_SERVER_CERT_PATHIf mlflow_run_id is null in eval results, check the adapter pod logs:
# Find the adapter pod for a specific job
oc get pods -n <namespace> --sort-by=.metadata.creationTimestamp | grep <job-id-prefix>
# Check adapter container logs for MLflow errors
oc logs <pod-name> -n <namespace> --all-containers | grep -E "ERROR|MLflow|mlflow"
Common error patterns:
ignore_tls_verification is true then server_cert_path must not be set → remove MLFLOW_TRACKING_INSECURE_TLSCERTIFICATE_VERIFY_FAILED → switch to internal service URLunknown proxy call → don't use localhost:8080, use internal service URLcannot be used because the remote server does not support workspaces → strip /mlflow path suffix from the internal URIExpecting value: line 1 column 1 (char 0)Cause: The MLFLOW_TRACKING_TOKEN is expired or invalid. The MLflow API returns a 302 redirect instead of JSON. See Step 4f for full diagnosis (including direct curl test) and Step 4a-4d for the fix. If the deployment has a hardcoded token instead of secretKeyRef, see Step 4e.
RESOURCE_DOES_NOT_EXIST: Workspace '<namespace>' not foundCause (RHOAI 3.5+): The namespace is missing the mlflow-tracking=enabled label. MLflow workspaces map 1:1 to namespaces, and only namespaces with this label are recognized. See Step 0a for the fix.
401 UNAUTHENTICATED with message about MLFLOW_TRACKING_AUTH=kubernetes-namespacedCause (RHOAI 3.5+): The MLflow operator is not deployed, or the MLflow tracking server is not running. The external route serves the RHOAI dashboard frontend (HTML) instead of the MLflow API. Check:
oc get datasciencecluster -o json | jq '.items[0].spec.components.mlflowoperator' — must be Managed, not Removedoc get pods -n redhat-ods-applications | grep mlflow — MLflow pod must exist and be Runningmlflowoperator is Removed, it needs to be enabled in the DataScienceCluster CRmake deploy fails with conflict with "kubectl-patch"Cause: A previous oc patch secret command took field ownership of .data.mlflow-tracking-token away from Helm. Helm's server-side apply refuses to overwrite fields owned by another manager.
Fix: Delete the conflicting secret and Helm release, then reinstall:
oc delete secret <agent-name>-secret -n <namespace>
helm uninstall <agent-name> -n <namespace>
make deploy # clean install restores Helm field ownership
See Step 4c for the correct patching approach that avoids this conflict.
Cause: The deployment's MLFLOW_TRACKING_TOKEN env var is a hardcoded value instead of a valueFrom.secretKeyRef. See Step 4e for full diagnosis and fix.
Cause: The agent is not producing MLflow traces, so the test harness's MLflowTraceClient finds nothing. This is almost always a token issue (see above). The /health endpoint returns 200 OK regardless of tracing status, so health checks won't catch this.
Diagnosis:
[Tracing Enabled] vs [Tracing] Failed to configureoc commands use explicit -n <namespace>. Never touch resources outside the current namespace.agents/<framework>/deployment/ templates..env files are written but never staged or committed.Add integration deployment tests (health-check on OpenShift) to any agent in the agentic-starter-kits repo — standard, external-registry, or pre-deployed. Creates conftest.py, test_deployment.py, __init__.py, adds test-integration Makefile target, and updates the CI workflow matrix. Use when implementing integration tests, deployment tests, or health-check tests for a new agent.
Validate whether a new agent template or example belongs in the agentic-starter-kits repo. Two modes: idea mode (interactive questionnaire, no code yet) or existing agent mode (auto-extract from code). Produces a GitHub Discussion draft with fit score and recommendations. Use when proposing a new agent, reviewing an existing contribution's fit, or before writing code for a new template.
Add behavioral testing (pytest + EvalHub) to an agent in the agentic-starter-kits repo. Covers runner compatibility, test files, golden queries, thresholds, EvalHub fixture, Containerfile, docs, and MLflow tracing verification. Use when implementing behavioral tests for a new agent or when the user mentions btest, behavioral tests, eval coverage, or test harness integration.
Adds manual MLflow trace wrapping for tool and agent spans in Level B and C agents where autolog doesn't cover everything.
Researches and classifies a framework's MLflow autolog support level (A, B, or C) to determine what manual tracing is needed.
Creates the tracing.py module with enable_tracing(), health check, and framework-specific autolog configuration.