# 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/router-wire-contract: ollama-numeric-keepalive ai.bstein.dev/execution: Hermes Kanban with durable direct Codex and Claude Code CLI workers 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: "20260816-auth-health-quarantine-v6" prometheus.io/scrape: "true" prometheus.io/path: /metrics prometheus.io/port: "9010" vault.hashicorp.com/agent-inject: "true" vault.hashicorp.com/role: hermes-agent vault.hashicorp.com/agent-inject-secret-agent-api-key: kv/data/atlas/hermes/agent-tokens vault.hashicorp.com/agent-inject-template-agent-api-key: | {{- with secret "kv/data/atlas/hermes/agent-tokens" -}} {{ .Data.data.agent_api_key }} {{- end }} vault.hashicorp.com/agent-inject-secret-claude-credentials: kv/data/atlas/hermes/agent-tokens vault.hashicorp.com/agent-inject-template-claude-credentials: | {{- with secret "kv/data/atlas/hermes/agent-tokens" -}} {{ .Data.data.claude_credentials_json }} {{- end }} vault.hashicorp.com/agent-inject-secret-codex-auth: kv/data/atlas/hermes/agent-tokens vault.hashicorp.com/agent-inject-template-codex-auth: | {{- with secret "kv/data/atlas/hermes/agent-tokens" -}} {{ .Data.data.codex_auth_json }} {{- end }} vault.hashicorp.com/agent-inject-secret-gitea-token: kv/data/atlas/hermes/developer-gitea vault.hashicorp.com/agent-inject-template-gitea-token: | {{- with secret "kv/data/atlas/hermes/developer-gitea" -}} {{ .Data.data.token }} {{- end }} vault.hashicorp.com/agent-inject-secret-gitea-username: kv/data/atlas/hermes/developer-gitea vault.hashicorp.com/agent-inject-template-gitea-username: | {{- with secret "kv/data/atlas/hermes/developer-gitea" -}} {{ .Data.data.username }} {{- end }} vault.hashicorp.com/agent-inject-secret-node-ssh-private-key: kv/data/atlas/hermes/developer-ssh vault.hashicorp.com/agent-inject-template-node-ssh-private-key: | {{- with secret "kv/data/atlas/hermes/developer-ssh" -}} {{ .Data.data.private_key }} {{- end }} vault.hashicorp.com/agent-inject-secret-node-ssh-config: kv/data/atlas/hermes/developer-ssh vault.hashicorp.com/agent-inject-template-node-ssh-config: | {{- with secret "kv/data/atlas/hermes/developer-ssh" -}} {{ .Data.data.config }} {{- end }} vault.hashicorp.com/agent-inject-secret-node-ssh-known-hosts: kv/data/atlas/hermes/developer-ssh vault.hashicorp.com/agent-inject-template-node-ssh-known-hosts: | {{- with secret "kv/data/atlas/hermes/developer-ssh" -}} {{ .Data.data.known_hosts }} {{- end }} vault.hashicorp.com/agent-inject-secret-chat-relay-key: kv/data/atlas/hermes/chat-telegram vault.hashicorp.com/agent-inject-template-chat-relay-key: | {{- with secret "kv/data/atlas/hermes/chat-telegram" -}} {{ .Data.data.relay_key }} {{- end }} vault.hashicorp.com/agent-inject-secret-oidc-config: kv/data/atlas/hermes/agent-oidc vault.hashicorp.com/agent-inject-template-oidc-config: | {{- with secret "kv/data/atlas/hermes/agent-oidc" -}} client_id = "{{ .Data.data.client_id }}" client_secret = "{{ .Data.data.client_secret }}" cookie_secret = "{{ .Data.data.cookie_secret }}" {{- 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 enableServiceLinks: false 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-04, titan-08, titan-13, titan-14, titan-17, titan-18, titan-19] 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 profile_file=/opt/data/home/.profile mkdir -p \ /opt/data/home/.claude \ /opt/data/home/.codex \ /opt/data/home/.kube \ /opt/data/home/.ssh \ /opt/data/cli-lanes \ /opt/data/logs \ /opt/data/provider-health \ /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 # OpenSSH resolves ~/.ssh from the account's passwd home # (/opt/data), not the HOME override used by Hermes. Keep one # Vault-populated directory visible through both paths. if [ ! -e /opt/data/.ssh ] && [ ! -L /opt/data/.ssh ]; then ln -s home/.ssh /opt/data/.ssh 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 rm -f \ /opt/data/auth.json \ /opt/data/home/.claude/.credentials.json \ /opt/data/home/.codex/auth.json \ /opt/data/home/.ssh/config \ /opt/data/home/.ssh/known_hosts \ /opt/data/home/.ssh/id_ed25519_atlas_nodes ln -s /runtime-access/node-ssh-config /opt/data/home/.ssh/config ln -s /runtime-access/node-ssh-known-hosts /opt/data/home/.ssh/known_hosts ln -s /runtime-access/node-ssh-private-key /opt/data/home/.ssh/id_ed25519_atlas_nodes chmod 0700 /opt/data/home/.ssh 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}" } for key in ANTHROPIC_API_KEY API_SERVER_KEY CLAUDE_API_KEY CLAUDE_CODE_OAUTH_TOKEN GITEA_TOKEN GITEA_USERNAME HERMES_IMAGE_BROKER_KEY OPENAI_API_KEY; do grep -v "^${key}=" "${env_file}" > "${env_file}.tmp" || true mv "${env_file}.tmp" "${env_file}" done for profile_env in /opt/data/profiles/*/.env; do [ -f "${profile_env}" ] || continue for key in ANTHROPIC_API_KEY API_SERVER_KEY CLAUDE_API_KEY CLAUDE_CODE_OAUTH_TOKEN GITEA_TOKEN GITEA_USERNAME HERMES_IMAGE_BROKER_KEY OPENAI_API_KEY; do grep -v "^${key}=" "${profile_env}" > "${profile_env}.tmp" || true mv "${profile_env}.tmp" "${profile_env}" done chmod 0600 "${profile_env}" chown 10000:10000 "${profile_env}" done upsert_env GIT_ASKPASS /opt/coordinator/gitea_askpass.sh upsert_env GIT_TERMINAL_PROMPT 0 upsert_env GITEA_BASE_URL https://scm.bstein.dev upsert_env JENKINS_BASE_URL http://jenkins.jenkins.svc.cluster.local:8080 upsert_env ARIADNE_BASE_URL http://ariadne.maintenance.svc.cluster.local upsert_env VICTORIA_METRICS_URL http://victoria-metrics-single-server.monitoring.svc.cluster.local:8428 upsert_env GRAFANA_BASE_URL https://metrics.bstein.dev chmod 0600 "${env_file}" touch "${profile_file}" if ! grep -qxF '# Hermes managed operator PATH.' "${profile_file}"; then printf '%s\n' \ '' \ '# Hermes managed operator PATH.' \ 'case ":${PATH}:" in' \ ' *":/opt/data/tools/bin:"*) ;;' \ ' *) PATH="/opt/coordinator:/opt/data/tools/bin:/opt/hermes/.venv/bin:/opt/hermes/bin:${PATH}" ;;' \ 'esac' \ 'export PATH' >> "${profile_file}" fi chmod 0644 "${profile_file}" # Existing owner data is already written as uid/gid 10000. A # recursive chown made every routine rollout walk the full 20Gi # workspace while the dashboard had no endpoint. Own only the # paths this init container creates or updates. chown 10000:10000 \ /opt/data \ /opt/data/home \ /opt/data/home/.claude \ /opt/data/home/.codex \ /opt/data/home/.kube \ /opt/data/home/.ssh \ /opt/data/cli-lanes \ /opt/data/logs \ /opt/data/provider-health \ /opt/data/tools \ /opt/data/tools/bin \ /opt/data/workspace \ /opt/data/workspace/coordinator \ /opt/data/workspace/projects \ /opt/data/workspace/skills \ /opt/data/config.yaml \ /opt/data/SOUL.md \ /opt/data/workspace/AGENTS.md \ /opt/data/workspace/START-HERE.md \ "${profile_file}" \ "${env_file}" 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: stage-runtime-access image: registry.bstein.dev/bstein/hermes-agent@sha256:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 imagePullPolicy: IfNotPresent command: - /opt/hermes/.venv/bin/python - /opt/coordinator/stage_runtime_access.py - agent securityContext: allowPrivilegeEscalation: false runAsUser: 0 runAsGroup: 0 seccompProfile: type: RuntimeDefault volumeMounts: - {name: home, mountPath: /opt/data} - {name: coordinator, mountPath: /opt/coordinator, readOnly: true} - {name: runtime-access, mountPath: /runtime-access} resources: requests: {cpu: 25m, memory: 32Mi} limits: {cpu: 100m, memory: 64Mi} - name: install-agent-tools image: registry.bstein.dev/bstein/hermes-agent@sha256:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 imagePullPolicy: IfNotPresent command: - sh - -c - | set -eu tools=/opt/data/tools mkdir -p "${tools}/bin" 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 /bin/sh /opt/coordinator/install_agent_tools.sh HOME=/opt/data/home git config --global user.name "Hermes Agent" HOME=/opt/data/home git config --global user.email "hermes@bstein.dev" securityContext: allowPrivilegeEscalation: false runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - name: home mountPath: /opt/data - name: coordinator mountPath: /opt/coordinator readOnly: true resources: requests: {cpu: 100m, memory: 256Mi} limits: {cpu: "1", memory: 1Gi} - name: repair-cassandra-kanban image: registry.bstein.dev/bstein/hermes-agent@sha256:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 imagePullPolicy: IfNotPresent command: - /opt/hermes/.venv/bin/python - /opt/coordinator/repair_cassandra_kanban.py - --database - /opt/data/kanban/boards/cassandra/kanban.db securityContext: allowPrivilegeEscalation: false runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - {name: home, mountPath: /opt/data} - {name: coordinator, mountPath: /opt/coordinator, readOnly: true} resources: requests: {cpu: 25m, memory: 64Mi} limits: {cpu: 250m, memory: 256Mi} - name: recover-cassandra-workers image: registry.bstein.dev/bstein/hermes-agent@sha256:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 imagePullPolicy: IfNotPresent command: - /opt/hermes/.venv/bin/python - /opt/coordinator/recover_cassandra_workers.py securityContext: allowPrivilegeEscalation: false runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - {name: home, mountPath: /opt/data} - {name: coordinator, mountPath: /opt/coordinator, readOnly: true} resources: requests: {cpu: 25m, memory: 64Mi} limits: {cpu: 250m, memory: 256Mi} - name: patch-auth image: registry.bstein.dev/bstein/hermes-agent@sha256:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 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: patch-tui-gateway image: registry.bstein.dev/bstein/hermes-agent@sha256:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 imagePullPolicy: IfNotPresent command: - /opt/hermes/.venv/bin/python - /opt/coordinator/patch_tui_gateway.py - /opt/hermes/tui_gateway/server.py - /patched/server.py securityContext: allowPrivilegeEscalation: false runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - name: coordinator mountPath: /opt/coordinator readOnly: true - name: tui-gateway-patch mountPath: /patched resources: requests: {cpu: 25m, memory: 64Mi} limits: {cpu: 100m, memory: 128Mi} - name: patch-api-server-sessions image: registry.bstein.dev/bstein/hermes-agent@sha256:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 imagePullPolicy: IfNotPresent command: - /opt/hermes/.venv/bin/python - /opt/coordinator/patch_api_server_sessions.py - /opt/hermes/gateway/platforms/api_server.py - /patched/api_server.py securityContext: allowPrivilegeEscalation: false runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - name: coordinator mountPath: /opt/coordinator readOnly: true - name: api-server-patch mountPath: /patched resources: requests: {cpu: 25m, memory: 64Mi} limits: {cpu: 100m, memory: 128Mi} - name: patch-web-session-activity image: registry.bstein.dev/bstein/hermes-agent@sha256:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 imagePullPolicy: IfNotPresent command: - /opt/hermes/.venv/bin/python - /opt/coordinator/patch_web_session_activity.py - /opt/hermes/hermes_cli/web_server.py - /patched/web_server.py securityContext: allowPrivilegeEscalation: false runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - name: coordinator mountPath: /opt/coordinator readOnly: true - name: web-server-patch mountPath: /patched resources: requests: {cpu: 25m, memory: 64Mi} limits: {cpu: 100m, memory: 128Mi} - name: patch-subprocess-secret-boundary image: registry.bstein.dev/bstein/hermes-agent@sha256:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 imagePullPolicy: IfNotPresent command: - /bin/sh - -ec - | /opt/hermes/.venv/bin/python /opt/coordinator/patch_subprocess_secret_boundary.py \ /opt/hermes/tools/environments/local.py /patched/local.py /opt/hermes/.venv/bin/python /opt/coordinator/patch_process_output_redaction.py \ /opt/hermes/tools/process_registry.py /patched/process_registry.py securityContext: allowPrivilegeEscalation: false runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - {name: coordinator, mountPath: /opt/coordinator, readOnly: true} - {name: subprocess-secret-patch, mountPath: /patched} resources: requests: {cpu: 25m, memory: 64Mi} limits: {cpu: 100m, memory: 128Mi} - name: patch-codex-runtime image: registry.bstein.dev/bstein/hermes-agent@sha256:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 imagePullPolicy: IfNotPresent command: - /opt/hermes/.venv/bin/python - /opt/coordinator/patch_codex_runtime.py - /opt/hermes/hermes_cli/runtime_provider.py - /patched/runtime_provider.py - /opt/hermes/agent/transports/codex_app_server_session.py - /patched/codex_app_server_session.py - /opt/hermes/agent/codex_runtime.py - /patched/codex_runtime.py - /opt/hermes/agent/chat_completion_helpers.py - /patched/chat_completion_helpers.py - /opt/hermes/agent/conversation_loop.py - /patched/conversation_loop.py - /opt/hermes/agent/auxiliary_client.py - /patched/auxiliary_client.py securityContext: allowPrivilegeEscalation: false runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - name: coordinator mountPath: /opt/coordinator readOnly: true - name: codex-runtime-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:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 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: /runtime-access/hermes-auth.json} - {name: HOME, value: /opt/data/home} - {name: CODEX_HOME, value: /runtime-access/codex} - {name: CLAUDE_CONFIG_DIR, value: /runtime-access/claude} - {name: PYTHONPATH, value: /opt/hermes} - {name: HERMES_ROUTING_CATALOG_PATH, value: /routing-catalog/catalog.json} - {name: HERMES_CASSANDRA_ACTIVE_WORKTREE, value: /opt/data/workspace/projects/cassandra-hermes-v69} - {name: PATH, value: /opt/coordinator:/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} - {name: runtime-access, mountPath: /runtime-access} - {name: coordinator, mountPath: /opt/coordinator, readOnly: true} - {name: auth-patch, mountPath: /opt/hermes/hermes_cli/auth.py, subPath: auth.py} - {name: routing-catalog, mountPath: /routing-catalog} resources: requests: {cpu: 50m, memory: 128Mi} limits: {cpu: 500m, memory: 512Mi} - name: configure-agent-clients image: registry.bstein.dev/bstein/hermes-agent@sha256:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 imagePullPolicy: IfNotPresent command: - sh - -ec - | set -a . /opt/data/.env set +a /opt/hermes/.venv/bin/python /opt/coordinator/configure_agent_clients.py /opt/hermes/.venv/bin/python /opt/coordinator/migrate_herdr_state.py /opt/hermes/.venv/bin/python /opt/coordinator/migrate_api_session_lineage.py # Client configuration restores the persisted Codex CLI login. # Refresh routing afterwards so AUTO sees the app-server lane on # the first request instead of waiting for the hourly steward. /opt/hermes/.venv/bin/python /opt/coordinator/hermes_coordinator.py --once env: - {name: HERMES_HOME, value: /opt/data} - {name: HERMES_AUTH_FILE, value: /runtime-access/hermes-auth.json} - {name: HOME, value: /opt/data/home} - {name: CODEX_HOME, value: /runtime-access/codex} - {name: CLAUDE_CONFIG_DIR, value: /runtime-access/claude} - {name: PYTHONPATH, value: /opt/hermes} - {name: HERMES_ROUTING_CATALOG_PATH, value: /routing-catalog/catalog.json} - {name: HERMES_CASSANDRA_ACTIVE_WORKTREE, value: /opt/data/workspace/projects/cassandra-hermes-v69} - {name: PATH, value: /opt/coordinator:/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} - {name: runtime-access, mountPath: /runtime-access} - {name: coordinator, mountPath: /opt/coordinator, readOnly: true} - {name: auth-patch, mountPath: /opt/hermes/hermes_cli/auth.py, subPath: auth.py} - {name: routing-catalog, mountPath: /routing-catalog} resources: requests: {cpu: 25m, memory: 128Mi} limits: {cpu: 500m, memory: 512Mi} - name: prepare-ttyd-index image: registry.bstein.dev/bstein/hermes-agent@sha256:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 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:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 imagePullPolicy: IfNotPresent command: [/bin/sh, -ec] args: - | set -a . /opt/data/.env set +a API_SERVER_KEY="$(tr -d '\r\n' < /runtime-access/agent-api-key)" test -n "${API_SERVER_KEY}" export API_SERVER_KEY exec /init /opt/hermes/docker/main-wrapper.sh gateway run ports: - {name: api, containerPort: 8642, protocol: TCP} - {name: dashboard, containerPort: 9119, protocol: TCP} env: - {name: HERMES_HOME, value: /opt/data} - {name: HERMES_AUTH_FILE, value: /runtime-access/hermes-auth.json} - {name: HOME, value: /opt/data/home} - {name: CODEX_HOME, value: /runtime-access/codex} - {name: CLAUDE_CONFIG_DIR, value: /runtime-access/claude} - {name: KUBECONFIG, value: /opt/data/home/.kube/config} - {name: PATH, value: /opt/coordinator:/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: "1"} - {name: HERMES_DASHBOARD_HOST, value: 127.0.0.1} - {name: HERMES_DASHBOARD_PORT, value: "9119"} - {name: HERMES_DASHBOARD_FILES_ROOT, value: /opt/data/workspace} - {name: HERMES_DASHBOARD_PUBLIC_URL, value: https://agent.hermes.bstein.dev} - {name: HERMES_TUI_AGENT_INIT_TIMEOUT_S, value: "180"} - {name: HERMES_STREAM_STALE_TIMEOUT, value: "600"} - {name: HERMES_API_CALL_STALE_TIMEOUT, value: "600"} - {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} - {name: HERMES_MEDIA_DELIVERY_STRICT, value: "1"} - {name: HERMES_MEDIA_ALLOW_DIRS, value: /opt/data/workspace} - {name: HERMES_AUTO_ROUTER_PROFILE, value: agent} - {name: HERMES_ROUTING_CATALOG_PATH, value: /routing-catalog/catalog.json} - {name: HERMES_CODEX_HEALTH_PATH, value: /opt/data/provider-health/codex.json} - {name: HERMES_CLAUDE_HEALTH_PATH, value: /opt/data/provider-health/claude.json} - {name: HERMES_IMAGE_BROKER_KEY_FILE, value: /runtime-access/chat-relay-key} volumeMounts: - {name: home, mountPath: /opt/data} - {name: runtime-access, mountPath: /runtime-access} - {name: coordinator, mountPath: /opt/coordinator, readOnly: true} - {name: auth-patch, mountPath: /opt/hermes/hermes_cli/auth.py, subPath: auth.py} - {name: web-server-patch, mountPath: /opt/hermes/hermes_cli/web_server.py, subPath: web_server.py} - {name: codex-runtime-patch, mountPath: /opt/hermes/hermes_cli/runtime_provider.py, subPath: runtime_provider.py} - {name: codex-runtime-patch, mountPath: /opt/hermes/agent/transports/codex_app_server_session.py, subPath: codex_app_server_session.py} - {name: codex-runtime-patch, mountPath: /opt/hermes/agent/codex_runtime.py, subPath: codex_runtime.py} - {name: codex-runtime-patch, mountPath: /opt/hermes/agent/chat_completion_helpers.py, subPath: chat_completion_helpers.py} - {name: codex-runtime-patch, mountPath: /opt/hermes/agent/conversation_loop.py, subPath: conversation_loop.py} - {name: codex-runtime-patch, mountPath: /opt/hermes/agent/auxiliary_client.py, subPath: auxiliary_client.py} - {name: tui-gateway-patch, mountPath: /opt/hermes/tui_gateway/server.py, subPath: server.py} - {name: api-server-patch, mountPath: /opt/hermes/gateway/platforms/api_server.py, subPath: api_server.py} - {name: subprocess-secret-patch, mountPath: /opt/hermes/tools/environments/local.py, subPath: local.py} - {name: subprocess-secret-patch, mountPath: /opt/hermes/tools/process_registry.py, subPath: process_registry.py} - {name: kubeconfig, mountPath: /opt/data/home/.kube/config, subPath: config, readOnly: true} - {name: auto-router-plugin, mountPath: /opt/data/plugins/auto-router, readOnly: true} - {name: atlas-pr-skill, mountPath: /opt/data/workspace/skills/manage-atlas-pull-requests, readOnly: true} - {name: routing-catalog, mountPath: /routing-catalog, readOnly: true} - {name: tmp, mountPath: /tmp} startupProbe: exec: command: [curl, -fsS, http://127.0.0.1:9119/api/status] periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 60 readinessProbe: exec: command: [curl, -fsS, http://127.0.0.1:9119/api/status] initialDelaySeconds: 30 periodSeconds: 10 timeoutSeconds: 5 livenessProbe: exec: command: [curl, -fsS, http://127.0.0.1:9119/api/status] initialDelaySeconds: 90 periodSeconds: 30 timeoutSeconds: 10 securityContext: allowPrivilegeEscalation: false runAsUser: 0 runAsGroup: 0 seccompProfile: type: RuntimeDefault resources: requests: {cpu: 300m, memory: 768Mi} limits: {cpu: "3", memory: 6Gi} - name: oauth2-proxy image: quay.io/oauth2-proxy/oauth2-proxy:v7.15.3@sha256:10a1165743a192e1940b4708fb9647027185ce11a681a1c5519b442ff7f1f561 imagePullPolicy: IfNotPresent args: - --provider=oidc - --config=/vault/secrets/oidc-config - --redirect-url=https://agent.hermes.bstein.dev/oauth2/callback - --oidc-issuer-url=https://sso.bstein.dev/realms/atlas - --user-id-claim=sub - --oidc-groups-claim=groups - --allowed-group=/hermes-owner - --code-challenge-method=S256 - --scope=openid profile email - --email-domain=* - --authenticated-emails-file=/etc/oauth2-proxy/allowed-emails - --custom-templates-dir=/etc/oauth2-proxy/templates - --set-xauthrequest=true - --pass-user-headers=true - --pass-basic-auth=false - --pass-host-header=false - --proxy-websockets=true - --cookie-name=__Host-hermes_agent - --cookie-path=/ - --cookie-secure=true - --cookie-samesite=lax - --cookie-csrf-expire=10m - --cookie-csrf-per-request=true - --cookie-csrf-per-request-limit=8 - --cookie-refresh=19m - --cookie-expire=8h - --session-store-type=redis - --redis-connection-url=redis://hermes-oauth-sessions.hermes.svc.cluster.local:6379/0 - --upstream=http://127.0.0.1:7681/terminal/ - --upstream=http://127.0.0.1:9119/ - --http-address=0.0.0.0:4180 - --skip-provider-button=true - --reverse-proxy=true - --api-route=^/api/ - --trusted-proxy-ip=10.42.0.0/16 ports: - {name: auth-http, containerPort: 4180, protocol: TCP} readinessProbe: httpGet: {path: /ping, port: auth-http} initialDelaySeconds: 5 periodSeconds: 10 livenessProbe: httpGet: {path: /ping, port: auth-http} initialDelaySeconds: 20 periodSeconds: 20 securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] readOnlyRootFilesystem: true runAsNonRoot: true seccompProfile: type: RuntimeDefault resources: requests: {cpu: 25m, memory: 64Mi} limits: {cpu: 250m, memory: 256Mi} volumeMounts: - {name: allowlist, mountPath: /etc/oauth2-proxy, readOnly: true} - {name: oauth-templates, mountPath: /etc/oauth2-proxy/templates, readOnly: true} - {name: oauth-tmp, mountPath: /tmp} - name: terminal image: registry.bstein.dev/bstein/hermes-agent@sha256:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 imagePullPolicy: IfNotPresent command: [/bin/sh, -ec] args: - | set -a . /opt/data/.env set +a exec /opt/data/tools/bin/ttyd \ --writable \ --base-path /terminal \ --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" \ --client-option fontSize=15 \ /usr/bin/tmux new-session -A \ -s hermes-coordinator \ -c /opt/data/workspace \ /bin/sh -lc ' while true; do /opt/hermes/.venv/bin/hermes \ --continue \ --tui \ --yolo \ --accept-hooks exit_code=$? printf "\r\nHermes exited (exit %s); resuming in 2 seconds...\r\n" "${exit_code}" sleep 2 done ' ports: - {name: terminal, containerPort: 7681, protocol: TCP} env: - {name: HOME, value: /opt/data/home} - {name: HERMES_HOME, value: /opt/data} - {name: HERMES_AUTH_FILE, value: /runtime-access/hermes-auth.json} - {name: CODEX_HOME, value: /runtime-access/codex} - {name: CLAUDE_CONFIG_DIR, value: /runtime-access/claude} - {name: KUBECONFIG, value: /opt/data/home/.kube/config} - {name: PYTHONPATH, value: /opt/hermes} - {name: PATH, value: /opt/coordinator:/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"} - {name: HERMES_TUI_AGENT_INIT_TIMEOUT_S, value: "180"} - {name: HERMES_AUTO_ROUTER_PROFILE, value: agent} - {name: HERMES_ROUTING_CATALOG_PATH, value: /routing-catalog/catalog.json} - {name: HERMES_CODEX_HEALTH_PATH, value: /opt/data/provider-health/codex.json} - {name: HERMES_CLAUDE_HEALTH_PATH, value: /opt/data/provider-health/claude.json} volumeMounts: - {name: home, mountPath: /opt/data} - {name: runtime-access, mountPath: /runtime-access} - {name: coordinator, mountPath: /opt/coordinator, readOnly: true} - {name: auth-patch, mountPath: /opt/hermes/hermes_cli/auth.py, subPath: auth.py} - {name: codex-runtime-patch, mountPath: /opt/hermes/hermes_cli/runtime_provider.py, subPath: runtime_provider.py} - {name: codex-runtime-patch, mountPath: /opt/hermes/agent/transports/codex_app_server_session.py, subPath: codex_app_server_session.py} - {name: codex-runtime-patch, mountPath: /opt/hermes/agent/codex_runtime.py, subPath: codex_runtime.py} - {name: codex-runtime-patch, mountPath: /opt/hermes/agent/chat_completion_helpers.py, subPath: chat_completion_helpers.py} - {name: codex-runtime-patch, mountPath: /opt/hermes/agent/conversation_loop.py, subPath: conversation_loop.py} - {name: codex-runtime-patch, mountPath: /opt/hermes/agent/auxiliary_client.py, subPath: auxiliary_client.py} - {name: tui-gateway-patch, mountPath: /opt/hermes/tui_gateway/server.py, subPath: server.py} - {name: subprocess-secret-patch, mountPath: /opt/hermes/tools/environments/local.py, subPath: local.py} - {name: subprocess-secret-patch, mountPath: /opt/hermes/tools/process_registry.py, subPath: process_registry.py} - {name: kubeconfig, mountPath: /opt/data/home/.kube/config, subPath: config, readOnly: true} - {name: auto-router-plugin, mountPath: /opt/data/plugins/auto-router, readOnly: true} - {name: atlas-pr-skill, mountPath: /opt/data/workspace/skills/manage-atlas-pull-requests, readOnly: true} - {name: routing-catalog, mountPath: /routing-catalog, readOnly: true} - {name: tmp, mountPath: /tmp} - {name: ttyd-index, mountPath: /ttyd-index, readOnly: true} startupProbe: tcpSocket: {port: terminal} periodSeconds: 5 timeoutSeconds: 3 failureThreshold: 60 readinessProbe: tcpSocket: {port: terminal} periodSeconds: 10 timeoutSeconds: 3 livenessProbe: tcpSocket: {port: terminal} 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: cli-lane-runner image: registry.bstein.dev/bstein/hermes-agent@sha256:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 imagePullPolicy: IfNotPresent command: [/bin/sh, -ec] args: - | set -a . /opt/data/.env set +a exec /opt/hermes/.venv/bin/python /opt/coordinator/cli_lane_runner.py env: - {name: HERMES_HOME, value: /opt/data} - {name: HERMES_AUTH_FILE, value: /runtime-access/hermes-auth.json} - {name: HOME, value: /opt/data/home} - {name: CODEX_HOME, value: /runtime-access/codex} - {name: CLAUDE_CONFIG_DIR, value: /runtime-access/claude} - {name: KUBECONFIG, value: /opt/data/home/.kube/config} - {name: PYTHONPATH, value: /opt/hermes} - {name: HERMES_CLI_LANE_CONCURRENCY, value: "2"} - {name: HERMES_AUTO_ROUTER_PROFILE, value: agent} - {name: PATH, value: /opt/coordinator:/opt/data/tools/bin:/opt/data/home/.local/bin:/opt/hermes/.venv/bin:/usr/local/bin:/usr/bin:/bin} securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - {name: home, mountPath: /opt/data} - {name: runtime-access, mountPath: /runtime-access} - {name: coordinator, mountPath: /opt/coordinator, readOnly: true} - {name: auth-patch, mountPath: /opt/hermes/hermes_cli/auth.py, subPath: auth.py} - {name: kubeconfig, mountPath: /opt/data/home/.kube/config, subPath: config, readOnly: true} - {name: auto-router-plugin, mountPath: /opt/data/plugins/auto-router, readOnly: true} - {name: atlas-pr-skill, mountPath: /opt/data/workspace/skills/manage-atlas-pull-requests, readOnly: true} - {name: tmp, mountPath: /tmp} resources: requests: {cpu: 100m, memory: 256Mi} limits: {cpu: "2", memory: 6Gi} - name: model-steward image: registry.bstein.dev/bstein/hermes-agent@sha256:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 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: /runtime-access/hermes-auth.json} - {name: HOME, value: /opt/data/home} - {name: CODEX_HOME, value: /runtime-access/codex} - {name: CLAUDE_CONFIG_DIR, value: /runtime-access/claude} - {name: PYTHONPATH, value: /opt/hermes} - {name: HERMES_ROUTING_CATALOG_PATH, value: /routing-catalog/catalog.json} - {name: HERMES_CASSANDRA_ACTIVE_WORKTREE, value: /opt/data/workspace/projects/cassandra-hermes-v69} - {name: PATH, value: /opt/coordinator:/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} - {name: runtime-access, mountPath: /runtime-access} - {name: coordinator, mountPath: /opt/coordinator, readOnly: true} - {name: auth-patch, mountPath: /opt/hermes/hermes_cli/auth.py, subPath: auth.py} - {name: routing-catalog, mountPath: /routing-catalog} resources: requests: {cpu: 25m, memory: 64Mi} limits: {cpu: 250m, memory: 512Mi} - name: credential-sync image: registry.bstein.dev/bstein/hermes-agent@sha256:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 imagePullPolicy: IfNotPresent command: - /opt/hermes/.venv/bin/python - /opt/coordinator/sync_runtime_credentials.py env: - {name: HERMES_CREDENTIAL_SYNC_VAULT_ROLE, value: hermes-credential-sync} - {name: HERMES_CREDENTIAL_SYNC_INTERVAL, value: "60"} securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - {name: coordinator, mountPath: /opt/coordinator, readOnly: true} - {name: runtime-access, mountPath: /runtime-access/claude, subPath: claude, readOnly: true} - {name: runtime-access, mountPath: /runtime-access/codex, subPath: codex, readOnly: true} resources: requests: {cpu: 10m, memory: 32Mi} limits: {cpu: 100m, memory: 128Mi} - name: ai-usage-exporter image: registry.bstein.dev/bstein/hermes-agent@sha256:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 imagePullPolicy: IfNotPresent command: - /opt/hermes/.venv/bin/python - /opt/coordinator/ai_usage_exporter.py ports: - {name: ai-metrics, containerPort: 9010, protocol: TCP} env: - {name: HOME, value: /tmp} - {name: CODEX_HOME, value: /runtime-access/codex} - {name: ATLAS_AI_CODEX_BIN, value: /opt/data/tools/bin/codex} - {name: ATLAS_AI_CLAUDE_CREDENTIALS, value: /runtime-access/claude/.credentials.json} - {name: ATLAS_AI_USAGE_INTERVAL_SECONDS, value: "300"} - {name: ATLAS_AI_USAGE_PORT, value: "9010"} readinessProbe: httpGet: {path: /healthz, port: ai-metrics} initialDelaySeconds: 5 periodSeconds: 10 livenessProbe: httpGet: {path: /healthz, port: ai-metrics} initialDelaySeconds: 30 periodSeconds: 30 securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - {name: home, mountPath: /opt/data/tools, subPath: tools, readOnly: true} - {name: runtime-access, mountPath: /runtime-access/claude, subPath: claude} - {name: runtime-access, mountPath: /runtime-access/codex, subPath: codex} - {name: coordinator, mountPath: /opt/coordinator, readOnly: true} - {name: tmp, mountPath: /tmp} resources: requests: {cpu: 10m, memory: 32Mi} limits: {cpu: 250m, memory: 192Mi} - name: image-broker image: registry.bstein.dev/bstein/hermes-agent@sha256:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 imagePullPolicy: IfNotPresent command: [/bin/sh, -ec] args: - | exec /opt/hermes/.venv/bin/python /opt/coordinator/image_broker.py ports: - {name: image-broker, containerPort: 9002, protocol: TCP} env: - {name: HERMES_HOME, value: /opt/data} - {name: HERMES_AUTH_FILE, value: /runtime-access/hermes-auth.json} - {name: HOME, value: /opt/data/home} - {name: CODEX_HOME, value: /runtime-access/codex} - {name: PYTHONPATH, value: /opt/hermes} - {name: HERMES_IMAGE_BROKER_DEFAULT_MODEL, value: atlas-image-auto-high} - {name: HERMES_IMAGE_BROKER_LISTEN_PORT, value: "9002"} - {name: HERMES_IMAGE_BROKER_KEY_FILE, value: /runtime-access/chat-relay-key} - {name: HERMES_LOCAL_IMAGE_URL, value: http://hermes-local-image.hermes.svc.cluster.local:9004} - {name: HERMES_IMAGE_POLICY_PATH, value: /etc/hermes-image-policy/policy.json} readinessProbe: tcpSocket: {port: image-broker} initialDelaySeconds: 5 periodSeconds: 10 livenessProbe: tcpSocket: {port: image-broker} initialDelaySeconds: 30 periodSeconds: 30 securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - {name: home, mountPath: /opt/data} - {name: runtime-access, mountPath: /runtime-access} - {name: coordinator, mountPath: /opt/coordinator, readOnly: true} - {name: codex-runtime-patch, mountPath: /opt/hermes/agent/auxiliary_client.py, subPath: auxiliary_client.py} - {name: image-policy, mountPath: /etc/hermes-image-policy, readOnly: true} - {name: tmp, mountPath: /tmp} resources: requests: {cpu: 50m, memory: 128Mi} limits: {cpu: "1", memory: 1Gi} - name: codex-broker image: registry.bstein.dev/bstein/hermes-agent@sha256:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 imagePullPolicy: IfNotPresent command: [/bin/sh, -ec] args: - | exec /opt/hermes/.venv/bin/python /opt/coordinator/codex_broker.py ports: - {name: codex-broker, containerPort: 9003, protocol: TCP} env: - {name: HERMES_HOME, value: /opt/data} - {name: HERMES_AUTH_FILE, value: /runtime-access/hermes-auth.json} - {name: HOME, value: /opt/data/home} - {name: CODEX_HOME, value: /runtime-access/codex} - {name: PYTHONPATH, value: /opt/hermes} - {name: HERMES_CODEX_BROKER_LISTEN_PORT, value: "9003"} - {name: HERMES_CODEX_BROKER_KEY_FILE, value: /runtime-access/chat-relay-key} - {name: HERMES_CODEX_HEALTH_PATH, value: /opt/data/provider-health/codex.json} - {name: HERMES_ROUTING_CATALOG_PATH, value: /routing-catalog/catalog.json} readinessProbe: tcpSocket: {port: codex-broker} initialDelaySeconds: 5 periodSeconds: 10 livenessProbe: tcpSocket: {port: codex-broker} initialDelaySeconds: 30 periodSeconds: 30 securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - {name: home, mountPath: /opt/data} - {name: runtime-access, mountPath: /runtime-access} - {name: coordinator, mountPath: /opt/coordinator, readOnly: true} - {name: codex-runtime-patch, mountPath: /opt/hermes/agent/auxiliary_client.py, subPath: auxiliary_client.py} - {name: tmp, mountPath: /tmp} - {name: routing-catalog, mountPath: /routing-catalog, readOnly: true} resources: requests: {cpu: 50m, memory: 128Mi} limits: {cpu: "1", memory: 1Gi} - name: claude-broker image: registry.bstein.dev/bstein/hermes-agent@sha256:81970563e542f0720773e72297810b3a844b83e381e278f25c0916c78d930107 imagePullPolicy: IfNotPresent command: [/bin/sh, -ec] args: - | unset ANTHROPIC_API_KEY CLAUDE_API_KEY exec /opt/hermes/.venv/bin/python /opt/coordinator/claude_oauth_broker.py ports: - {name: claude-broker, containerPort: 9006, protocol: TCP} env: - {name: HERMES_HOME, value: /opt/data} - {name: HERMES_AUTH_FILE, value: /runtime-access/hermes-auth.json} - {name: HOME, value: /opt/data/home} - {name: CODEX_HOME, value: /runtime-access/codex} - {name: CLAUDE_CONFIG_DIR, value: /runtime-access/claude} - {name: PYTHONPATH, value: /opt/hermes} - {name: PATH, value: /opt/coordinator:/opt/data/tools/bin:/opt/data/home/.local/bin:/opt/hermes/.venv/bin:/usr/local/bin:/usr/bin:/bin} - {name: HERMES_CLAUDE_BIN, value: /opt/coordinator/claude} - {name: HERMES_CLAUDE_BROKER_PORT, value: "9006"} - {name: HERMES_CLAUDE_BROKER_KEY_FILE, value: /runtime-access/chat-relay-key} - {name: HERMES_CLAUDE_BROKER_READ_TIMEOUT, value: "1800"} - {name: HERMES_CLAUDE_BROKER_CONCURRENCY, value: "2"} - {name: HERMES_CLAUDE_HEALTH_PATH, value: /opt/data/provider-health/claude.json} - {name: HERMES_ROUTING_CATALOG_PATH, value: /routing-catalog/catalog.json} readinessProbe: tcpSocket: {port: claude-broker} initialDelaySeconds: 5 periodSeconds: 10 livenessProbe: tcpSocket: {port: claude-broker} initialDelaySeconds: 30 periodSeconds: 30 securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] readOnlyRootFilesystem: true runAsNonRoot: true runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - {name: home, mountPath: /opt/data} - {name: runtime-access, mountPath: /runtime-access} - {name: coordinator, mountPath: /opt/coordinator, readOnly: true} - {name: auth-patch, mountPath: /opt/hermes/hermes_cli/auth.py, subPath: auth.py} - {name: tmp, mountPath: /tmp} - {name: routing-catalog, mountPath: /routing-catalog, readOnly: true} resources: requests: {cpu: 100m, memory: 256Mi} limits: {cpu: "3", memory: 3Gi} volumes: - name: home persistentVolumeClaim: claimName: hermes-agent-home - name: runtime-access emptyDir: medium: Memory sizeLimit: 128Mi - name: routing-catalog persistentVolumeClaim: claimName: hermes-routing-catalog - 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: tui-gateway-patch emptyDir: {} - name: api-server-patch emptyDir: {} - name: web-server-patch emptyDir: {} - name: subprocess-secret-patch emptyDir: {} - name: codex-runtime-patch emptyDir: {} - name: auto-router-plugin configMap: name: hermes-auto-router-plugin items: - {key: __init__.py, path: __init__.py} - {key: provider_status.py, path: provider_status.py} - {key: plugin.yaml, path: plugin.yaml} - {key: dashboard-manifest.json, path: dashboard/manifest.json} - {key: dashboard-api.py, path: dashboard/plugin_api.py} - {key: dashboard-index.js, path: dashboard/dist/index.js} - {key: dashboard-style.css, path: dashboard/dist/style.css} - name: atlas-pr-skill configMap: name: hermes-atlas-pr-skill items: - {key: SKILL.md, path: SKILL.md} - {key: openai.yaml, path: agents/openai.yaml} - name: image-policy configMap: name: hermes-image-policy - name: tmp emptyDir: sizeLimit: 4Gi - name: oauth-tmp emptyDir: sizeLimit: 64Mi - name: allowlist configMap: name: hermes-owner-allowlist - name: oauth-templates configMap: name: hermes-chat-oauth-templates - name: ttyd-index emptyDir: sizeLimit: 2Mi