# services/hermes/agent-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: hermes-agent namespace: hermes labels: app: hermes-agent spec: replicas: 1 revisionHistoryLimit: 2 progressDeadlineSeconds: 2700 strategy: type: Recreate selector: matchLabels: app: hermes-agent template: metadata: labels: app: hermes-agent annotations: ai.bstein.dev/role: project-coordinator ai.bstein.dev/execution: Herdr-supervised Codex and Claude Code ai.bstein.dev/model-policy: Jetson-assisted AUTO routing, low through xhigh, cross-provider fallback ai.bstein.dev/placement: rpi5 preferred; Jetson deferred until state storage is available ai.bstein.dev/config-rev: "20260809-terminal-recovery-v2" vault.hashicorp.com/agent-inject: "true" vault.hashicorp.com/role: hermes-agent vault.hashicorp.com/agent-inject-secret-anthropic-token: kv/data/atlas/hermes/agent-tokens vault.hashicorp.com/agent-inject-template-anthropic-token: | {{- with secret "kv/data/atlas/hermes/agent-tokens" -}} {{ .Data.data.anthropic_oauth_token }} {{- end }} vault.hashicorp.com/agent-inject-secret-gitea-token: kv/data/atlas/hermes/agent-tokens vault.hashicorp.com/agent-inject-template-gitea-token: | {{- with secret "kv/data/atlas/hermes/agent-tokens" -}} {{- with index .Data.data "gitea_token" -}} {{ . }} {{- end -}} {{- end }} vault.hashicorp.com/agent-pre-populate-only: "true" vault.hashicorp.com/agent-init-first: "true" vault.hashicorp.com/agent-requests-cpu: 25m vault.hashicorp.com/agent-requests-mem: 32Mi vault.hashicorp.com/agent-limits-cpu: 100m vault.hashicorp.com/agent-limits-mem: 128Mi spec: serviceAccountName: hermes-agent automountServiceAccountToken: true securityContext: fsGroup: 10000 fsGroupChangePolicy: OnRootMismatch seccompProfile: type: RuntimeDefault affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/arch operator: In values: [arm64] - key: node-role.kubernetes.io/worker operator: In values: ["true"] - key: kubernetes.io/hostname operator: NotIn values: [titan-08, titan-13, titan-14, titan-17, titan-18] preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 preference: matchExpressions: - key: hardware operator: In values: [rpi5] initContainers: - name: init-config image: busybox:1.37 imagePullPolicy: IfNotPresent command: - sh - -c - | set -eu env_file=/opt/data/.env mkdir -p \ /opt/data/home/.claude \ /opt/data/home/.codex \ /opt/data/home/.config/herdr \ /opt/data/home/.kube \ /opt/data/herdr \ /opt/data/logs \ /opt/data/tools/bin \ /opt/data/workspace/coordinator \ /opt/data/workspace/projects \ /opt/data/workspace/skills if [ ! -e /opt/data/home/.hermes ]; then ln -s /opt/data /opt/data/home/.hermes fi cp /config/config.yaml /opt/data/config.yaml cp /config/SOUL.md /opt/data/SOUL.md cp /config/AGENTS.md /opt/data/workspace/AGENTS.md cp /config/START-HERE.md /opt/data/workspace/START-HERE.md touch "${env_file}" upsert_env() { key="$1" value="$2" { grep -v "^${key}=" "${env_file}" || true; printf '%s=%s\n' "${key}" "${value}"; } > "${env_file}.tmp" mv "${env_file}.tmp" "${env_file}" } if ! grep -q '^API_SERVER_KEY=' "${env_file}"; then api_key="$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | od -An -tx1 | tr -d ' \n')" upsert_env API_SERVER_KEY "${api_key}" fi if [ -s /vault/secrets/anthropic-token ]; then token="$(tr -d '\r\n' < /vault/secrets/anthropic-token)" [ -z "${token}" ] || upsert_env CLAUDE_CODE_OAUTH_TOKEN "${token}" fi if [ -s /vault/secrets/gitea-token ]; then token="$(tr -d '\r\n' < /vault/secrets/gitea-token)" case "${token}" in ""|""|"") ;; *) upsert_env GITEA_TOKEN "${token}" ;; esac fi upsert_env GITEA_USERNAME bstein upsert_env GIT_ASKPASS /opt/coordinator/gitea_askpass.sh upsert_env GIT_TERMINAL_PROMPT 0 chmod 0600 "${env_file}" chown -R 10000:10000 /opt/data securityContext: allowPrivilegeEscalation: false runAsUser: 0 runAsGroup: 0 seccompProfile: type: RuntimeDefault volumeMounts: - name: home mountPath: /opt/data - name: config mountPath: /config readOnly: true resources: requests: {cpu: 25m, memory: 32Mi} limits: {cpu: 100m, memory: 64Mi} - name: install-agent-tools image: registry.bstein.dev/bstein/hermes-agent@sha256:7a1daefae2f068dcf14e7eb1f2f9aab2e1ce79c1b55b4bb0aa1092fbf4019bbc imagePullPolicy: IfNotPresent command: - sh - -c - | set -eu tools=/opt/data/tools mkdir -p "${tools}/bin" herdr_version="$("${tools}/bin/herdr" --version 2>/dev/null || true)" case "${herdr_version}" in *0.8.0*) herdr_ready=1 ;; *) herdr_ready=0 ;; esac if [ "${herdr_ready}" != "1" ]; then curl -fsSL -o "${tools}/bin/herdr.tmp" https://github.com/herdrdev/herdr/releases/download/v0.8.0/herdr-linux-aarch64 printf '%s %s\n' f647ac66468d9efbc642fe534fb284468f0aea60641606fc008dfc0d82a3ca87 "${tools}/bin/herdr.tmp" | sha256sum -c - chmod 0755 "${tools}/bin/herdr.tmp" mv "${tools}/bin/herdr.tmp" "${tools}/bin/herdr" fi ttyd_version="$("${tools}/bin/ttyd" --version 2>/dev/null || true)" case "${ttyd_version}" in *1.7.7*) ttyd_ready=1 ;; *) ttyd_ready=0 ;; esac if [ "${ttyd_ready}" != "1" ]; then curl -fsSL -o "${tools}/bin/ttyd.tmp" https://github.com/tsl0922/ttyd/releases/download/1.7.7/ttyd.aarch64 printf '%s %s\n' b38acadd89d1d396a0f5649aa52c539edbad07f4bc7348b27b4f4b7219dd4165 "${tools}/bin/ttyd.tmp" | sha256sum -c - chmod 0755 "${tools}/bin/ttyd.tmp" mv "${tools}/bin/ttyd.tmp" "${tools}/bin/ttyd" fi if [ ! -f "${tools}/.cli-versions-0.147.0-2.1.226" ]; then npm install --global --omit=dev --no-audit --no-fund --prefix "${tools}" \ @openai/codex@0.147.0 \ @anthropic-ai/claude-code@2.1.226 touch "${tools}/.cli-versions-0.147.0-2.1.226" fi kubectl_version="$("${tools}/bin/kubectl" version --client --output=json 2>/dev/null || true)" case "${kubectl_version}" in *\"gitVersion\":\"v1.33.3\"*) kubectl_ready=1 ;; *) kubectl_ready=0 ;; esac if [ "${kubectl_ready}" != "1" ]; then curl -fsSL -o "${tools}/bin/kubectl.tmp" https://dl.k8s.io/release/v1.33.3/bin/linux/arm64/kubectl printf '%s %s\n' 3d514dbae5dc8c09f773df0ef0f5d449dfad05b3aca5c96b13565f886df345fd "${tools}/bin/kubectl.tmp" | sha256sum -c - chmod 0755 "${tools}/bin/kubectl.tmp" mv "${tools}/bin/kubectl.tmp" "${tools}/bin/kubectl" fi securityContext: allowPrivilegeEscalation: false runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - name: home mountPath: /opt/data resources: requests: {cpu: 100m, memory: 256Mi} limits: {cpu: "1", memory: 1Gi} - name: patch-auth image: registry.bstein.dev/bstein/hermes-agent@sha256:7a1daefae2f068dcf14e7eb1f2f9aab2e1ce79c1b55b4bb0aa1092fbf4019bbc imagePullPolicy: IfNotPresent command: - /opt/hermes/.venv/bin/python - /opt/coordinator/patch_hermes_auth.py - /opt/hermes/hermes_cli/auth.py - /patched/auth.py securityContext: allowPrivilegeEscalation: false runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - name: coordinator mountPath: /opt/coordinator readOnly: true - name: auth-patch mountPath: /patched resources: requests: {cpu: 25m, memory: 64Mi} limits: {cpu: 100m, memory: 128Mi} - name: bootstrap-coordinator image: registry.bstein.dev/bstein/hermes-agent@sha256:7a1daefae2f068dcf14e7eb1f2f9aab2e1ce79c1b55b4bb0aa1092fbf4019bbc imagePullPolicy: IfNotPresent command: - /opt/hermes/.venv/bin/python - /opt/coordinator/hermes_coordinator.py - --once env: - {name: HERMES_HOME, value: /opt/data} - {name: HERMES_AUTH_FILE, value: /shared-auth/auth.json} - {name: HOME, value: /opt/data/home} - {name: PYTHONPATH, value: /opt/hermes} securityContext: allowPrivilegeEscalation: false runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - {name: home, mountPath: /opt/data} - {name: provider-auth, mountPath: /shared-auth} - {name: coordinator, mountPath: /opt/coordinator, readOnly: true} - {name: auth-patch, mountPath: /opt/hermes/hermes_cli/auth.py, subPath: auth.py} resources: requests: {cpu: 50m, memory: 128Mi} limits: {cpu: 500m, memory: 512Mi} - name: install-herdr-integrations image: registry.bstein.dev/bstein/hermes-agent@sha256:7a1daefae2f068dcf14e7eb1f2f9aab2e1ce79c1b55b4bb0aa1092fbf4019bbc imagePullPolicy: IfNotPresent command: - sh - -ec - | herdr integration install codex herdr integration install claude herdr integration install hermes env: - {name: HERMES_HOME, value: /opt/data} - {name: HOME, value: /opt/data/home} - {name: CODEX_HOME, value: /opt/data/home/.codex} - {name: CLAUDE_CONFIG_DIR, value: /opt/data/home/.claude} - {name: PATH, value: /opt/data/tools/bin:/opt/hermes/.venv/bin:/usr/local/bin:/usr/bin:/bin} securityContext: allowPrivilegeEscalation: false runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - {name: home, mountPath: /opt/data} resources: requests: {cpu: 25m, memory: 32Mi} limits: {cpu: 250m, memory: 128Mi} - name: prepare-ttyd-index image: registry.bstein.dev/bstein/hermes-agent@sha256:7a1daefae2f068dcf14e7eb1f2f9aab2e1ce79c1b55b4bb0aa1092fbf4019bbc imagePullPolicy: IfNotPresent command: - /opt/hermes/.venv/bin/python - /opt/coordinator/patch_ttyd_index.py - /opt/data/tools/bin/ttyd - /ttyd-index/index.html securityContext: allowPrivilegeEscalation: false runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - {name: home, mountPath: /opt/data} - {name: coordinator, mountPath: /opt/coordinator, readOnly: true} - {name: ttyd-index, mountPath: /ttyd-index} resources: requests: {cpu: 25m, memory: 32Mi} limits: {cpu: 250m, memory: 128Mi} containers: - name: hermes image: registry.bstein.dev/bstein/hermes-agent@sha256:7a1daefae2f068dcf14e7eb1f2f9aab2e1ce79c1b55b4bb0aa1092fbf4019bbc imagePullPolicy: IfNotPresent command: [/opt/hermes/.venv/bin/hermes] args: [gateway, run, --no-supervise] ports: - {name: api, containerPort: 8642, protocol: TCP} env: - {name: HERMES_HOME, value: /opt/data} - {name: HERMES_AUTH_FILE, value: /shared-auth/auth.json} - {name: HOME, value: /opt/data/home} - {name: CODEX_HOME, value: /opt/data/home/.codex} - {name: CLAUDE_CONFIG_DIR, value: /opt/data/home/.claude} - {name: HERDR_CONFIG_PATH, value: /opt/data/home/.config/herdr/config.toml} - {name: HERDR_SOCKET_PATH, value: /opt/data/herdr/herdr.sock} - {name: KUBECONFIG, value: /opt/data/home/.kube/config} - {name: PATH, value: /opt/data/tools/bin:/opt/data/home/.local/bin:/opt/hermes/.venv/bin:/opt/hermes/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin} - {name: PLAYWRIGHT_BROWSERS_PATH, value: /opt/hermes/.playwright} - {name: AGENT_BROWSER_EXECUTABLE_PATH, value: /opt/hermes/.playwright/chromium_headless_shell-1228/chrome-linux/headless_shell} - {name: AGENT_BROWSER_ARGS, value: "--no-sandbox,--disable-dev-shm-usage"} - {name: HERMES_DASHBOARD, value: "0"} - {name: HERMES_DASHBOARD_PUBLIC_URL, value: https://agent.hermes.bstein.dev} - {name: API_SERVER_ENABLED, value: "true"} - {name: API_SERVER_HOST, value: 0.0.0.0} - {name: API_SERVER_PORT, value: "8642"} - {name: API_SERVER_CORS_ORIGINS, value: https://agent.hermes.bstein.dev} volumeMounts: - {name: home, mountPath: /opt/data} - {name: provider-auth, mountPath: /shared-auth} - {name: coordinator, mountPath: /opt/coordinator, readOnly: true} - {name: auth-patch, mountPath: /opt/hermes/hermes_cli/auth.py, subPath: auth.py} - {name: coordinator, mountPath: /opt/data/home/.local/bin/herdr-dispatch, subPath: herdr_dispatch.py, readOnly: true} - {name: kubeconfig, mountPath: /opt/data/home/.kube/config, subPath: config, readOnly: true} - {name: auto-router-plugin, mountPath: /opt/data/plugins/auto-router, readOnly: true} startupProbe: tcpSocket: {port: api} periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 60 readinessProbe: tcpSocket: {port: api} initialDelaySeconds: 30 periodSeconds: 10 timeoutSeconds: 5 livenessProbe: tcpSocket: {port: api} initialDelaySeconds: 90 periodSeconds: 30 timeoutSeconds: 10 securityContext: allowPrivilegeEscalation: false runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault resources: requests: {cpu: 250m, memory: 512Mi} limits: {cpu: "2", memory: 4Gi} - name: webui image: registry.bstein.dev/bstein/hermes-webui@sha256:a771858bd668d25e19c74864baea5425101c8cd5215d1ba3a312f3312ce6c5e1 imagePullPolicy: IfNotPresent command: [/bin/sh, -ec] args: - | api_key="$(sed -n 's/^API_SERVER_KEY=//p' /opt/data/.env | tail -n 1)" test -n "${api_key}" export API_SERVER_KEY="${api_key}" export HERMES_WEBUI_GATEWAY_API_KEY="${api_key}" exec /opt/hermes/.venv/bin/python /opt/hermes-webui/server.py ports: - {name: dashboard, containerPort: 8787, protocol: TCP} env: - {name: HERMES_HOME, value: /opt/data} - {name: HERMES_AUTH_FILE, value: /shared-auth/auth.json} - {name: HOME, value: /opt/data/home} - {name: HERMES_WEBUI_AGENT_DIR, value: /opt/hermes} - {name: HERMES_WEBUI_HOST, value: 0.0.0.0} - {name: HERMES_WEBUI_PORT, value: "8787"} - {name: HERMES_WEBUI_STATE_DIR, value: /opt/data/webui} - {name: HERMES_WEBUI_DEFAULT_WORKSPACE, value: /opt/data/workspace} - {name: HERMES_WEBUI_CHAT_BACKEND, value: gateway} - {name: HERMES_WEBUI_GATEWAY_BASE_URL, value: http://127.0.0.1:8642} - {name: HERMES_WEBUI_GATEWAY_USE_RUNS_API, value: "true"} - {name: HERMES_WEBUI_SKIP_ONBOARDING, value: "1"} - {name: HERMES_WEBUI_SECURE, value: "1"} - {name: HERMES_WEBUI_ALLOWED_ORIGINS, value: https://agent.hermes.bstein.dev} - {name: HERMES_WEBUI_TRUST_FORWARDED_HOST, value: "1"} - {name: HERMES_WEBUI_TRUST_FORWARDED_PROTO, value: "1"} volumeMounts: - {name: home, mountPath: /opt/data} - {name: provider-auth, mountPath: /shared-auth, readOnly: true} - {name: tmp, mountPath: /tmp} readinessProbe: httpGet: {path: /health, port: dashboard} initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 livenessProbe: httpGet: {path: /health, port: dashboard} initialDelaySeconds: 30 periodSeconds: 30 timeoutSeconds: 10 securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault resources: requests: {cpu: 50m, memory: 128Mi} limits: {cpu: 750m, memory: 1Gi} - name: herdr-tui image: registry.bstein.dev/bstein/hermes-agent@sha256:7a1daefae2f068dcf14e7eb1f2f9aab2e1ce79c1b55b4bb0aa1092fbf4019bbc imagePullPolicy: IfNotPresent command: [/bin/sh, -ec] args: - | set -a . /opt/data/.env set +a exec /opt/data/tools/bin/ttyd \ --writable \ --check-origin \ --interface 0.0.0.0 \ --port 7681 \ --cwd /opt/data/workspace \ --terminal-type xterm-256color \ --index /ttyd-index/index.html \ --client-option disableReconnect=true \ --client-option "titleFixed=Hermes Agent - HERDR" \ --client-option fontSize=15 \ /bin/sh -c ' while true; do /opt/data/tools/bin/herdr exit_code=$? printf "\r\nHerdr disconnected (exit %s); reconnecting in 2 seconds...\r\n" "${exit_code}" sleep 2 done ' ports: - {name: herdr-tui, containerPort: 7681, protocol: TCP} env: - {name: HOME, value: /opt/data/home} - {name: CODEX_HOME, value: /opt/data/home/.codex} - {name: CLAUDE_CONFIG_DIR, value: /opt/data/home/.claude} - {name: HERDR_CONFIG_PATH, value: /opt/data/home/.config/herdr/config.toml} - {name: HERDR_SOCKET_PATH, value: /opt/data/herdr/herdr.sock} - {name: PATH, value: /opt/data/tools/bin:/opt/hermes/.venv/bin:/usr/local/bin:/usr/bin:/bin} volumeMounts: - {name: home, mountPath: /opt/data} - {name: tmp, mountPath: /tmp} - {name: ttyd-index, mountPath: /ttyd-index, readOnly: true} startupProbe: tcpSocket: {port: herdr-tui} periodSeconds: 5 timeoutSeconds: 3 failureThreshold: 60 readinessProbe: tcpSocket: {port: herdr-tui} periodSeconds: 10 timeoutSeconds: 3 livenessProbe: tcpSocket: {port: herdr-tui} initialDelaySeconds: 30 periodSeconds: 30 timeoutSeconds: 5 securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault resources: requests: {cpu: 25m, memory: 64Mi} limits: {cpu: 500m, memory: 512Mi} - name: herdr-server image: registry.bstein.dev/bstein/hermes-agent@sha256:7a1daefae2f068dcf14e7eb1f2f9aab2e1ce79c1b55b4bb0aa1092fbf4019bbc imagePullPolicy: IfNotPresent command: - sh - -c - | set -eu set -a . /opt/data/.env set +a herdr server & server_pid=$! trap 'kill "${server_pid}" 2>/dev/null || true' TERM INT for attempt in $(seq 1 60); do if herdr status server >/dev/null 2>&1; then break; fi sleep 1 done pane_file=/opt/data/herdr/coordinator-pane-id pane="$(cat "${pane_file}" 2>/dev/null || true)" pane_live=no if [ -n "${pane}" ]; then for attempt in $(seq 1 20); do if herdr pane process-info --pane "${pane}" >/dev/null 2>&1; then pane_live=yes break fi sleep 1 done fi if [ "${pane_live}" != "yes" ]; then if [ -n "${pane}" ]; then workspace="${pane%%:*}" herdr workspace close "${workspace}" >/dev/null 2>&1 || true fi created="$(herdr workspace create \ --cwd /opt/data/workspace \ --label coordinator \ --env HERMES_HOME=/opt/data \ --env HERMES_AUTH_FILE=/shared-auth/auth.json \ --env HOME=/opt/data/home \ --env KUBECONFIG=/opt/data/home/.kube/config \ --env PYTHONPATH=/opt/hermes \ --env PLAYWRIGHT_BROWSERS_PATH=/opt/hermes/.playwright \ --env AGENT_BROWSER_EXECUTABLE_PATH=/opt/hermes/.playwright/chromium_headless_shell-1228/chrome-linux/headless_shell \ --env AGENT_BROWSER_ARGS=--no-sandbox,--disable-dev-shm-usage \ --focus)" pane="$(printf '%s' "${created}" | /opt/hermes/.venv/bin/python -c \ 'import json,sys; print(json.load(sys.stdin)["result"]["root_pane"]["pane_id"])')" printf '%s\n' "${pane}" > "${pane_file}" fi active_workspace="${pane%%:*}" coordinator_workspaces="$(herdr workspace list | /opt/hermes/.venv/bin/python -c \ 'import json,sys; active=sys.argv[1]; payload=json.load(sys.stdin); print(" ".join(item["workspace_id"] for item in payload["result"]["workspaces"] if item.get("label") == "coordinator" and item["workspace_id"] != active))' \ "${active_workspace}")" for stale_workspace in ${coordinator_workspaces}; do herdr workspace close "${stale_workspace}" >/dev/null 2>&1 || true done process_info="$(herdr pane process-info --pane "${pane}" 2>/dev/null || printf '%s\n' '{"result":{"process_info":{"foreground_processes":[]}}}')" coordinator_running="$(printf '%s' "${process_info}" | /opt/hermes/.venv/bin/python -c \ 'import json,sys; processes=json.load(sys.stdin)["result"]["process_info"].get("foreground_processes", []); print("yes" if any("hermes" in " ".join(str(p.get(k) or "") for k in ("name", "argv0", "cmdline")) for p in processes) else "no")')" if [ "${coordinator_running}" != "yes" ]; then herdr agent start coordinator \ --kind hermes \ --pane "${pane}" \ --timeout 60000 fi /opt/hermes/.venv/bin/python /opt/coordinator/herdr_tab_router.py \ --workspace-label coordinator \ --interval 1 & router_pid=$! trap 'kill "${router_pid}" "${server_pid}" 2>/dev/null || true' TERM INT wait "${server_pid}" env: - {name: HERMES_HOME, value: /opt/data} - {name: HERMES_AUTH_FILE, value: /shared-auth/auth.json} - {name: HOME, value: /opt/data/home} - {name: CODEX_HOME, value: /opt/data/home/.codex} - {name: CLAUDE_CONFIG_DIR, value: /opt/data/home/.claude} - {name: HERDR_CONFIG_PATH, value: /opt/data/home/.config/herdr/config.toml} - {name: HERDR_SOCKET_PATH, value: /opt/data/herdr/herdr.sock} - {name: KUBECONFIG, value: /opt/data/home/.kube/config} - {name: PYTHONPATH, value: /opt/hermes} - {name: PATH, value: /opt/data/tools/bin:/opt/data/home/.local/bin:/opt/hermes/.venv/bin:/usr/local/bin:/usr/bin:/bin} - {name: PLAYWRIGHT_BROWSERS_PATH, value: /opt/hermes/.playwright} - {name: AGENT_BROWSER_EXECUTABLE_PATH, value: /opt/hermes/.playwright/chromium_headless_shell-1228/chrome-linux/headless_shell} - {name: AGENT_BROWSER_ARGS, value: "--no-sandbox,--disable-dev-shm-usage"} securityContext: allowPrivilegeEscalation: false runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - {name: home, mountPath: /opt/data} - {name: provider-auth, mountPath: /shared-auth} - {name: coordinator, mountPath: /opt/coordinator, readOnly: true} - {name: auth-patch, mountPath: /opt/hermes/hermes_cli/auth.py, subPath: auth.py} - {name: coordinator, mountPath: /opt/data/home/.local/bin/herdr-dispatch, subPath: herdr_dispatch.py, readOnly: true} - {name: kubeconfig, mountPath: /opt/data/home/.kube/config, subPath: config, readOnly: true} - {name: auto-router-plugin, mountPath: /opt/data/plugins/auto-router, readOnly: true} resources: requests: {cpu: 50m, memory: 128Mi} limits: {cpu: "1", memory: 2Gi} - name: model-steward image: registry.bstein.dev/bstein/hermes-agent@sha256:7a1daefae2f068dcf14e7eb1f2f9aab2e1ce79c1b55b4bb0aa1092fbf4019bbc imagePullPolicy: IfNotPresent command: [/opt/hermes/.venv/bin/python, /opt/coordinator/hermes_coordinator.py, --loop, --interval, "3600"] env: - {name: HERMES_HOME, value: /opt/data} - {name: HERMES_AUTH_FILE, value: /shared-auth/auth.json} - {name: HOME, value: /opt/data/home} - {name: PYTHONPATH, value: /opt/hermes} securityContext: allowPrivilegeEscalation: false runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - {name: home, mountPath: /opt/data} - {name: provider-auth, mountPath: /shared-auth} - {name: coordinator, mountPath: /opt/coordinator, readOnly: true} - {name: auth-patch, mountPath: /opt/hermes/hermes_cli/auth.py, subPath: auth.py} resources: requests: {cpu: 25m, memory: 64Mi} limits: {cpu: 250m, memory: 512Mi} volumes: - name: home persistentVolumeClaim: claimName: hermes-agent-home - name: provider-auth persistentVolumeClaim: claimName: hermes-provider-auth - name: config configMap: name: hermes-agent-config - name: coordinator configMap: name: hermes-coordinator defaultMode: 0555 - name: kubeconfig configMap: name: hermes-agent-kubeconfig defaultMode: 0444 - name: auth-patch emptyDir: {} - name: auto-router-plugin configMap: name: hermes-auto-router-plugin - name: tmp emptyDir: sizeLimit: 256Mi - name: ttyd-index emptyDir: sizeLimit: 2Mi