# services/hermes/switchyard-configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: hermes-switchyard namespace: hermes labels: app: hermes-switchyard data: routes.toml: | schema_version = 1 [llm_clients.classifier] format = "openai_chat" base_url = "http://ollama.ai.svc.cluster.local:11434/v1" max_retries = 1 [llm_clients.local_low] format = "openai_chat" base_url = "http://hermes-model-gate.hermes.svc.cluster.local:11434/v1" max_retries = 1 [llm_clients.local_medium] format = "openai_chat" base_url = "http://hermes-model-gate.hermes.svc.cluster.local:11434/v1" max_retries = 1 [llm_clients.codex_low] format = "openai_responses" base_url = "http://hermes-codex-broker.hermes.svc.cluster.local:9003/v1" api_key_env = "ATLAS_BROKER_KEY" max_retries = 1 [llm_clients.codex_medium] format = "openai_responses" base_url = "http://hermes-codex-broker.hermes.svc.cluster.local:9003/v1" api_key_env = "ATLAS_BROKER_KEY" max_retries = 1 [llm_clients.codex_high] format = "openai_responses" base_url = "http://hermes-codex-broker.hermes.svc.cluster.local:9003/v1" api_key_env = "ATLAS_BROKER_KEY" max_retries = 1 [llm_clients.codex_xhigh] format = "openai_responses" base_url = "http://hermes-codex-broker.hermes.svc.cluster.local:9003/v1" api_key_env = "ATLAS_BROKER_KEY" max_retries = 1 [llm_clients.claude_low] format = "anthropic_messages" base_url = "http://127.0.0.1:9006/v1" api_key_env = "ATLAS_BROKER_KEY" max_retries = 1 [llm_clients.claude_medium] format = "anthropic_messages" base_url = "http://127.0.0.1:9006/v1" api_key_env = "ATLAS_BROKER_KEY" max_retries = 1 [llm_clients.claude_high] format = "anthropic_messages" base_url = "http://127.0.0.1:9006/v1" api_key_env = "ATLAS_BROKER_KEY" max_retries = 1 [llm_clients.claude_xhigh] format = "anthropic_messages" base_url = "http://127.0.0.1:9006/v1" api_key_env = "ATLAS_BROKER_KEY" max_retries = 1 [llm_clients.worker_decision] format = "openai_chat" base_url = "http://127.0.0.1:9007/v1" max_retries = 0 [targets.classifier] id = "qwen2.5:3b-instruct-q4_0" llm_client = "classifier" [targets.local_qwen_low] id = "route/local/qwen2.5-14b/low" llm_client = "local_low" extra_body = { reasoning_effort = "low" } [targets.local_qwen_medium] id = "route/local/qwen2.5-14b/medium" llm_client = "local_medium" extra_body = { reasoning_effort = "medium" } [targets.codex_luna_low] id = "route/codex/luna/low" llm_client = "codex_low" extra_body = { reasoning = { effort = "low" } } [targets.codex_terra_low] id = "route/codex/terra/low" llm_client = "codex_low" extra_body = { reasoning = { effort = "low" } } [targets.codex_terra_medium] id = "route/codex/terra/medium" llm_client = "codex_medium" extra_body = { reasoning = { effort = "medium" } } [targets.codex_terra_high] id = "route/codex/terra/high" llm_client = "codex_high" extra_body = { reasoning = { effort = "high" } } [targets.codex_sol_medium] id = "route/codex/sol/medium" llm_client = "codex_medium" extra_body = { reasoning = { effort = "medium" } } [targets.codex_sol_high] id = "route/codex/sol/high" llm_client = "codex_high" extra_body = { reasoning = { effort = "high" } } [targets.codex_sol_xhigh] id = "route/codex/sol/xhigh" llm_client = "codex_xhigh" extra_body = { reasoning = { effort = "xhigh" } } [targets.claude_haiku_low] id = "route/claude/haiku/low" llm_client = "claude_low" extra_body = { thinking = { type = "adaptive" }, output_config = { effort = "low" } } [targets.claude_sonnet_medium] id = "route/claude/sonnet/medium" llm_client = "claude_medium" extra_body = { thinking = { type = "adaptive" }, output_config = { effort = "medium" } } [targets.claude_sonnet_high] id = "route/claude/sonnet/high" llm_client = "claude_high" extra_body = { thinking = { type = "adaptive" }, output_config = { effort = "high" } } [targets.claude_opus_high] id = "route/claude/opus/high" llm_client = "claude_high" extra_body = { thinking = { type = "adaptive" }, output_config = { effort = "high" } } [targets.claude_opus_xhigh] id = "route/claude/opus/xhigh" llm_client = "claude_xhigh" extra_body = { thinking = { type = "adaptive" }, output_config = { effort = "xhigh" } } [targets.worker_codex_luna_low] id = "worker/codex/luna/low" llm_client = "worker_decision" [targets.worker_codex_terra_medium] id = "worker/codex/terra/medium" llm_client = "worker_decision" [targets.worker_codex_sol_high] id = "worker/codex/sol/high" llm_client = "worker_decision" [targets.worker_codex_sol_xhigh] id = "worker/codex/sol/xhigh" llm_client = "worker_decision" [targets.worker_claude_haiku_low] id = "worker/claude/haiku/low" llm_client = "worker_decision" [targets.worker_claude_sonnet_medium] id = "worker/claude/sonnet/medium" llm_client = "worker_decision" [targets.worker_claude_sonnet_high] id = "worker/claude/sonnet/high" llm_client = "worker_decision" [targets.worker_claude_opus_xhigh] id = "worker/claude/opus/xhigh" llm_client = "worker_decision" [routes.auto_fast] id = "atlas/auto/fast" type = "llm_classifier" mode = "custom" classifier_target = "classifier" targets = ["codex_terra_medium", "claude_sonnet_medium", "codex_luna_low", "claude_haiku_low", "local_qwen_low", "local_qwen_medium", "codex_terra_low", "codex_terra_high", "codex_sol_medium", "codex_sol_high", "codex_sol_xhigh", "claude_sonnet_high", "claude_opus_high", "claude_opus_xhigh"] default_target = "codex_terra_medium" max_output_tokens = 96 session_affinity = false recent_turn_window = 8 context_window = 272000 tool_calling = true reasoning = true prompt = """ You are the routing authority for a private family assistant. Choose exactly one configured target for this model-call boundary. Mildly favor fast and economical answers, but never trade away correctness for difficult, ambiguous, safety-sensitive, tool-heavy, or consequential work. Use local Qwen only for simple low-risk conversation, formatting, or continuity. Prefer Codex for implementation, debugging, tests, and direct repository work. Prefer Claude for architecture, ambiguity, long-context synthesis, risk analysis, and independent review. Interpret requests such as "answer quickly", "think hard", or "use Claude" semantically. An explicit user provider, model, or depth instruction wins unless it would undercut a clear safety floor. Every request is a fresh boundary; classify the actual current objective and recent context, including referential instructions like "continue" or "do it". Never select effort above xhigh. """ response_schema = ''' {"type":"object","properties":{"decision":{"type":"object","properties":{"target":{"type":"string","enum":["codex_terra_medium","claude_sonnet_medium","codex_luna_low","claude_haiku_low","local_qwen_low","local_qwen_medium","codex_terra_low","codex_terra_high","codex_sol_medium","codex_sol_high","codex_sol_xhigh","claude_sonnet_high","claude_opus_high","claude_opus_xhigh"]}},"required":["target"],"additionalProperties":false}},"required":["decision"],"additionalProperties":false} ''' [routes.auto_fast.policy] type = "target_selector" selector = "/decision/target" [routes.auto_balanced] id = "atlas/auto/balanced" type = "llm_classifier" mode = "custom" classifier_target = "classifier" targets = ["codex_terra_medium", "claude_sonnet_medium", "codex_luna_low", "claude_haiku_low", "local_qwen_low", "local_qwen_medium", "codex_terra_low", "codex_terra_high", "codex_sol_medium", "codex_sol_high", "codex_sol_xhigh", "claude_sonnet_high", "claude_opus_high", "claude_opus_xhigh"] default_target = "codex_terra_medium" max_output_tokens = 96 session_affinity = false recent_turn_window = 8 context_window = 272000 tool_calling = true reasoning = true prompt = """ You are the routing authority for a private general assistant. Choose exactly one configured target for this model-call boundary. Balance latency, cost, and intelligence while giving difficult, uncertain, tool-heavy, or consequential work enough capability. Use local Qwen only for simple low-risk conversation, formatting, or continuity. Prefer Codex for implementation, debugging, tests, and direct repository work. Prefer Claude for architecture, ambiguity, long-context synthesis, risk analysis, and independent review. Interpret speed/depth and provider requests semantically; explicit user intent wins unless it undercuts a clear safety floor. Classify the actual current objective and recent context, including referential instructions such as "continue" or "do it". Never select effort above xhigh. """ response_schema = ''' {"type":"object","properties":{"decision":{"type":"object","properties":{"target":{"type":"string","enum":["codex_terra_medium","claude_sonnet_medium","codex_luna_low","claude_haiku_low","local_qwen_low","local_qwen_medium","codex_terra_low","codex_terra_high","codex_sol_medium","codex_sol_high","codex_sol_xhigh","claude_sonnet_high","claude_opus_high","claude_opus_xhigh"]}},"required":["target"],"additionalProperties":false}},"required":["decision"],"additionalProperties":false} ''' [routes.auto_balanced.policy] type = "target_selector" selector = "/decision/target" [routes.auto_deep] id = "atlas/auto/deep" type = "llm_classifier" mode = "custom" classifier_target = "classifier" targets = ["claude_sonnet_high", "codex_sol_high", "codex_terra_medium", "claude_sonnet_medium", "codex_terra_high", "codex_sol_medium", "claude_opus_high", "codex_sol_xhigh", "claude_opus_xhigh", "codex_luna_low", "claude_haiku_low", "local_qwen_medium", "local_qwen_low", "codex_terra_low"] default_target = "claude_sonnet_high" max_output_tokens = 96 session_affinity = false recent_turn_window = 12 context_window = 272000 tool_calling = true reasoning = true prompt = """ You are the routing authority for operations triage. Choose exactly one configured target for this model-call boundary. Favor evidence, diagnosis, uncertainty handling, and correctness over marginal latency savings. Cheap routes are appropriate only for genuinely mechanical low-risk steps. Prefer Codex for implementation, debugging, tests, and repository work; prefer Claude for diagnosis, architecture, ambiguity, synthesis, risk analysis, and independent review. Interpret requests for speed, depth, or a provider semantically. Explicit user intent wins unless it violates a safety floor. Re-evaluate every current boundary using recent tool evidence and resolve referential instructions such as "continue" or "do it" from that context. Never select effort above xhigh. """ response_schema = ''' {"type":"object","properties":{"decision":{"type":"object","properties":{"target":{"type":"string","enum":["claude_sonnet_high","codex_sol_high","codex_terra_medium","claude_sonnet_medium","codex_terra_high","codex_sol_medium","claude_opus_high","codex_sol_xhigh","claude_opus_xhigh","codex_luna_low","claude_haiku_low","local_qwen_medium","local_qwen_low","codex_terra_low"]}},"required":["target"],"additionalProperties":false}},"required":["decision"],"additionalProperties":false} ''' [routes.auto_deep.policy] type = "target_selector" selector = "/decision/target" [routes.auto_maximum] id = "atlas/auto/maximum" type = "llm_classifier" mode = "custom" classifier_target = "classifier" targets = ["codex_sol_high", "claude_opus_high", "claude_sonnet_high", "codex_terra_high", "codex_sol_xhigh", "claude_opus_xhigh", "codex_terra_medium", "claude_sonnet_medium", "codex_sol_medium", "codex_luna_low", "claude_haiku_low", "local_qwen_medium", "local_qwen_low", "codex_terra_low"] default_target = "codex_sol_high" max_output_tokens = 96 session_affinity = false recent_turn_window = 16 context_window = 272000 tool_calling = true reasoning = true prompt = """ You are the routing authority for an owner-only engineering agent. Choose exactly one configured target for this model-call boundary. Strongly favor correctness, verification, and task completion; do not waste premium capacity on truly mechanical steps. Prefer Codex for implementation, debugging, tests, and direct repository changes. Prefer Claude for architecture, difficult ambiguity, long-context synthesis, risk analysis, and independent review. Production changes, security, migrations, data-loss risk, destructive work, and critical final review require high or xhigh. Interpret user requests for speed, deeper thought, or a specific provider semantically. Explicit user intent wins unless it undercuts the safety floor. Re-evaluate every current boundary from the objective and recent tool evidence, including referential instructions such as "continue" or "do it". Never select effort above xhigh. """ response_schema = ''' {"type":"object","properties":{"decision":{"type":"object","properties":{"target":{"type":"string","enum":["codex_sol_high","claude_opus_high","claude_sonnet_high","codex_terra_high","codex_sol_xhigh","claude_opus_xhigh","codex_terra_medium","claude_sonnet_medium","codex_sol_medium","codex_luna_low","claude_haiku_low","local_qwen_medium","local_qwen_low","codex_terra_low"]}},"required":["target"],"additionalProperties":false}},"required":["decision"],"additionalProperties":false} ''' [routes.auto_maximum.policy] type = "target_selector" selector = "/decision/target" [routes.worker_auto_maximum] id = "atlas/worker/auto/maximum" type = "llm_classifier" mode = "custom" classifier_target = "classifier" targets = ["worker_codex_sol_high", "worker_claude_sonnet_high", "worker_codex_sol_xhigh", "worker_claude_opus_xhigh", "worker_codex_terra_medium", "worker_claude_sonnet_medium", "worker_codex_luna_low", "worker_claude_haiku_low"] default_target = "worker_codex_sol_high" max_output_tokens = 96 session_affinity = false recent_turn_window = 16 context_window = 272000 tool_calling = false reasoning = true prompt = """ You are the sole routing authority for one durable engineering-worker launch. Choose exactly one configured worker target from the current objective, acceptance criteria, risk, and any prior-provider failure in the request. Prefer Codex for implementation, debugging, tests, and repository changes. Prefer Claude for architecture, ambiguity, synthesis, adversarial analysis, and independent review. Use low only for mechanical bounded work, medium for ordinary work, high for difficult or consequential work, and xhigh for critical security, migration, destructive-risk, or independent final review. Never exceed xhigh. If the request says a provider has failed or exhausted capacity, do not select that provider. """ response_schema = ''' {"type":"object","properties":{"decision":{"type":"object","properties":{"target":{"type":"string","enum":["worker_codex_sol_high","worker_claude_sonnet_high","worker_codex_sol_xhigh","worker_claude_opus_xhigh","worker_codex_terra_medium","worker_claude_sonnet_medium","worker_codex_luna_low","worker_claude_haiku_low"]}},"required":["target"],"additionalProperties":false}},"required":["decision"],"additionalProperties":false} ''' [routes.worker_auto_maximum.policy] type = "target_selector" selector = "/decision/target" [routes.worker_manual_codex_low] id = "atlas/worker/manual/codex/low" type = "random" targets = ["worker_codex_luna_low"] [routes.worker_manual_codex_medium] id = "atlas/worker/manual/codex/medium" type = "random" targets = ["worker_codex_terra_medium"] [routes.worker_manual_codex_high] id = "atlas/worker/manual/codex/high" type = "random" targets = ["worker_codex_sol_high"] [routes.worker_manual_codex_xhigh] id = "atlas/worker/manual/codex/xhigh" type = "random" targets = ["worker_codex_sol_xhigh"] [routes.worker_manual_claude_low] id = "atlas/worker/manual/claude/low" type = "random" targets = ["worker_claude_haiku_low"] [routes.worker_manual_claude_medium] id = "atlas/worker/manual/claude/medium" type = "random" targets = ["worker_claude_sonnet_medium"] [routes.worker_manual_claude_high] id = "atlas/worker/manual/claude/high" type = "random" targets = ["worker_claude_sonnet_high"] [routes.worker_manual_claude_xhigh] id = "atlas/worker/manual/claude/xhigh" type = "random" targets = ["worker_claude_opus_xhigh"] # A zero-weight target is not selected initially. Switchyard still walks # this ordered list after 403/408/429/5xx, timeout, or transport failure. [routes.manual_codex_luna] id = "atlas/manual/codex/luna" type = "random" targets = ["codex_luna_low", "claude_haiku_low", "codex_terra_medium", "claude_sonnet_medium", "local_qwen_low"] weights = [1, 0, 0, 0, 0] context_window = 272000 tool_calling = true reasoning = true [routes.manual_codex_terra] id = "atlas/manual/codex/terra" type = "random" targets = ["codex_terra_medium", "claude_sonnet_medium", "codex_sol_high", "claude_sonnet_high", "local_qwen_medium"] weights = [1, 0, 0, 0, 0] context_window = 272000 tool_calling = true reasoning = true [routes.manual_codex_sol] id = "atlas/manual/codex/sol" type = "random" targets = ["codex_sol_high", "claude_opus_high", "claude_sonnet_high", "codex_terra_high", "local_qwen_medium"] weights = [1, 0, 0, 0, 0] context_window = 272000 tool_calling = true reasoning = true [routes.manual_claude_haiku] id = "atlas/manual/claude/haiku" type = "random" targets = ["claude_haiku_low", "codex_luna_low", "claude_sonnet_medium", "codex_terra_medium", "local_qwen_low"] weights = [1, 0, 0, 0, 0] context_window = 272000 tool_calling = true reasoning = true [routes.manual_claude_sonnet] id = "atlas/manual/claude/sonnet" type = "random" targets = ["claude_sonnet_high", "codex_sol_high", "claude_opus_high", "codex_terra_high", "local_qwen_medium"] weights = [1, 0, 0, 0, 0] context_window = 272000 tool_calling = true reasoning = true [routes.manual_claude_opus] id = "atlas/manual/claude/opus" type = "random" targets = ["claude_opus_high", "codex_sol_high", "claude_sonnet_high", "codex_terra_high", "local_qwen_medium"] weights = [1, 0, 0, 0, 0] context_window = 272000 tool_calling = true reasoning = true [routes.manual_local_qwen] id = "atlas/manual/local/qwen-14b" type = "random" targets = ["local_qwen_medium", "codex_terra_medium", "claude_sonnet_medium", "codex_luna_low", "claude_haiku_low"] weights = [1, 0, 0, 0, 0] context_window = 131072 tool_calling = true reasoning = false