[Tool: skill_view]
{"success": true, "name": "hermes-agent", "description": "Configure, extend, or contribute to Hermes Agent.", "tags": ["hermes", "setup", "configuration", "multi-agent", "spawning", "cli", "gateway", "development"], "related_skills": ["claude-code", "codex", "opencode"], "content": "---\nname: hermes-agent\ndescription: \"Configure, extend, or contribute to Hermes Agent.\"\nversion: 2.0.0\nauthor: Hermes Agent + Teknium\nlicense: MIT\nmetadata:\n hermes:\n tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]\n homepage: https://github.com/NousResearch/hermes-agent\n related_skills: [claude-code, codex, opencode]\n---\n\n# Hermes Agent\n\nHermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw — autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.\n\nWhat makes Hermes different:\n\n- **Self-improving through skills** — Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.\n- **Persistent memory across sessions** — remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.\n- **Multi-platform gateway** — the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.\n- **Provider-agnostic** — swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.\n- **Profiles** — run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.\n- **Extensible** — plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.\n\nPeople use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.\n\n**This skill helps you work with Hermes Agent effectively** — setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.\n\n**Docs:** https://hermes-agent.nousresearch.com/docs/\n\n## Quick Start\n\n```bash\n# Install\ncurl -fsSL https://raw.githubuserco
... [33791 chars total, truncated]
2026-07-22 22:11
ASSISTANT (hermes, glm-5.2)
Let me check your current config and saved API keys.
[Tool: terminal]
{"output": "# LLM PROVIDER (Ollama Cloud)\n# Cloud-hosted open models via Ollama's OpenAI-compatible endpoint.\n# Get your key at: https://ollama.com/settings\n# OLLAMA_API_KEY=***REDACTED***\n# Optional base URL override (default: https://ollama.com/v1)\n# OLLAMA_BASE_URL=***REDACTED***\n# LLM PROVIDER (Kimi / Moonshot)\n# Kimi Code provides access to Moonshot AI coding models (kimi-k2.5, etc.)\n# Get your key at: https://platform.kimi.ai (Kimi Code console)\n# Keys prefixed sk-kimi- use the Kimi Code API (api.kimi.com) by default.\n# Legacy keys from platform.moonshot.ai need KIMI_BASE_URL override below.\n# KIMI_API_KEY=***REDACTED***\n# KIMI_BASE_URL=***REDACTED***\n# KIMI_BASE_URL=***REDACTED***\n# KIMI_BASE_URL=***REDACTED***\n# KIMI_CN_API_KEY=***REDACTED***\n# OpenCode Zen provides curated, tested models (GPT, Claude, Gemini, MiniMax, GLM, Kimi)\n# OpenCode Go provides access to open models (GLM-5, Kimi K2.5, MiniMax M2.5)\nOLLAMA_API_KEY=***REDACTED***\nKIMI_API_KEY=***REDACTED***", "exit_code": 0, "error": null}
Good news — you already have both keys saved. You're currently on `ollama-cloud` with `glm-5.2`. Let me check what models are available on Ollama Cloud to find the exact Kimi model name.
2026-07-22 22:12
TOOL (hermes, glm-5.2)
[Tool: terminal]
{"output": "Total models: 18\nkimi-k2.6\nkimi-k2.7-code\nkimi-k2.5", "exit_code": 0, "error": null, "approval": "Command was flagged (Security scan — [HIGH] Pipe to interpreter: curl | python3: Command pipes output from 'curl' directly to interpreter 'python3'. Downloaded content will be executed without inspection.\n Safer: tirith run https://ollama.com/v1/models — or: vet https://ollama.com/v1/models (https://getvet.sh); script execution via -e/-c flag) and auto-approved by smart approval."}
2026-07-22 22:12
ASSISTANT (hermes, glm-5.2)
Found it — `kimi-k2.7-code` is available on Ollama Cloud. Switching now.
2026-07-22 22:12
TOOL (hermes, glm-5.2)
[Tool: terminal]
{"output": "✓ Set model.default = kimi-k2.7-code in /home/ubuntu/.hermes/config.yaml", "exit_code": 0, "error": null}
2026-07-22 22:12
ASSISTANT (hermes, glm-5.2)
Done. Here's the summary:
- Your Ollama Cloud API key was already saved in `~/.hermes/.env` (OLLAMA_API_KEY) and in `config.yaml`.
- Found 3 Kimi models on Ollama Cloud: `kimi-k2.5`, `kimi-k2.6`, `kimi-k2.7-code`.
- Changed the model from `glm-5.2` to `kimi-k2.7-code`.
The provider stays `ollama-cloud`, base URL stays `https://ollama.com/v1` — only the model name changed. Start a new session (exit and relaunch `hermes`, or type `/new` here) for it to take effect.
2026-07-22 22:12
USER (hermes, glm-5.2)
looks like you connected me to ollama cloud model - i want to connect to kimi 2,7 model as is not through ollama cloud
2026-07-22 22:15
ASSISTANT (hermes, glm-5.2)
Got it — you want Kimi's own API (api.kimi.com), not Ollama Cloud. Your `KIMI_API_KEY` is already saved in `~/.hermes/.env`. Let me switch the provider and model.
[Tool: terminal]
{"output": "default: kimi-k2.7-code\n provider: ollama-cloud\n base_url: https://ollama.com/v1\n api_key: 44ddce01e9444a6293793d95a9e8de34.xedLL8oyYcSbbD5NiqiHHide\n context_length: 262144\n max_tokens: 16384\n---\n # (Kimi K2.6, MiniMax M2.7) the local total can be 10x-100x lower than\n # configured providers (OpenRouter, Nous, Z.ai, Kimi, etc.) are supported.\n \"KIMI_API_KEY\": {\n \"description\": \"Kimi / Moonshot API key\",\n \"prompt\": \"Kimi API key\",\n \"KIMI_BASE_URL\": {\n \"description\": \"Kimi / Moonshot base URL override\",\n \"prompt\": \"Kimi base URL (leave empty for default)\",\n \"KIMI_CN_API_KEY\": {\n \"description\": \"Kimi / Moonshot China API key\",\n \"prompt\": \"Kimi (China) API key\",\n# kimi-coding (KIMI_API_KEY) — Kimi / Moonshot\n# kimi-coding-cn (KIMI_CN_API_KEY) — Kimi / Moonshot (China)\n# kimi-coding (KIMI_API_KEY) — Kimi / Moonshot\n# kimi-coding-cn (KIMI_CN_API_KEY) — Kimi / Moonshot (China)", "exit_code": 0, "error": null}
[Subdirectory context discovered: .hermes/hermes-agent/AGENTS.md]
# Hermes Agent - Development Guide
Instructions for AI coding assistants and developers working on the hermes-agent codebase.
**Never give up on the right solution.**
## What Hermes Is
Hermes is a personal AI agent that runs the same agent core across a CLI, a
messaging gateway (Telegram, Discord, Slack, and ~20 other platforms), a TUI,
and an Electron desktop app. It learns across sessions (memory + skills),
delegates to subagents, runs scheduled jobs, and drives a real terminal and
browser. It is extended primarily through **plugins and skills**, not by
growing the core.
Two properties shape almost every design decision and are the lens for
reviewing any change:
- **Per-conversation prompt caching is sacred.** A long-lived conversation
reuses a cached prefix every turn. Anything that mutates past context,
swaps toolsets, or rebuilds the system prompt mid-conversation invalidates
that cache and multiplies the user's cost. We do not do it (the one
exception is context compression).
- **The core is a narrow waist; capability lives at the edges.** Every model
tool we add is sent on every API call, so the bar for a new *core* tool is
high. Most new capability should arrive as a CLI command + skill, a
service-gated tool, or a plugin — not as core surface.
## Contribution Rubric — What We Want / What We Don't
This is the project's intent layer. Use it two ways:
1. **For humans and for your own work** — what gets merged and what gets
rejected, so a contribution aims at the target.
2. **For automated review (the triage sweeper)** — guidance on when a PR is
safe to close on the three allowed reasons (`implemented_on_main`,
`cannot_reproduce`, `incoherent`) and, just as important, **when NOT to
close** one. Taste-based "we don't want this / out of scope" closes are NOT
an automated de
... [9202 chars total, truncated]
[Tool: terminal]
{"output": "# nous (OAuth — hermes auth) — Nous Portal\n# zai (ZAI_API_KEY) — Z.AI / GLM\n# kimi-coding (KIMI_API_KEY) — Kimi / Moonshot\n# kimi-coding-cn (KIMI_CN_API_KEY) — Kimi / Moonshot (China)\n# minimax (MINIMAX_API_KEY) — MiniMax\n# minimax-cn (MINIMAX_CN_API_KEY) — MiniMax (China)\n# bedrock (AWS IAM / boto3) — AWS Bedrock (Converse API)\n#\n# For custom OpenAI-compatible endpoints, add base_url and key_env.\n#\n# fallback_model:\n# provider: openrouter\n# model: anthropic/claude-sonnet-4\n\"\"\"\n\n\n_COMMENTED_SECTIONS = \"\"\"\n# ── Security ──────────────────────────────────────────────────────────\n# Secret redaction is ON by default. Set to false to pass tool output,\n--\n# nous (OAuth — hermes auth) — Nous Portal\n# zai (ZAI_API_KEY) — Z.AI / GLM\n# kimi-coding (KIMI_API_KEY) — Kimi / Moonshot\n# kimi-coding-cn (KIMI_CN_API_KEY) — Kimi / Moonshot (China)\n# minimax (MINIMAX_API_KEY) — MiniMax\n# minimax-cn (MINIMAX_CN_API_KEY) — MiniMax (China)\n# bedrock (AWS IAM / boto3) — AWS Bedrock (Converse API)\n#\n# For custom OpenAI-compatible endpoints, add base_url and key_env.\n#\n# fallback_model:\n# provider: openrouter\n# model: anthropic/claude-sonnet-4\n\"\"\"\n\n\ndef save_config(\n config: Dict[str, Any],\n *,", "exit_code": 0, "error": null}
2026-07-22 22:15
ASSISTANT (hermes, glm-5.2)
2026-07-22 22:15
TOOL (hermes, glm-5.2)
[Tool: search_files]
{"total_count": 213, "matches_format": "path-grouped: each file path on its own line, followed by indented '<line>: <content>' rows for matches in that file", "matches_text": "/home/ubuntu/.hermes/hermes-agent/run_agent.py\n 5996: \n 5997: Detection is host-driven, not model-name-driven: aggregators like\n 5998: OpenRouter that re-export Kimi/Moonshot models speak their own\n 5999: protocol and reject ``reasoning_content`` echoes. We only enable the\n 6000: kimi-reasoning replay when the request actually targets a\n 6001: kimi/moonshot endpoint or the dedicated kimi-coding provider.\n 6002: \"\"\"\n 6003: return (\n 6004: self.provider in {\"kimi-coding\", \"kimi-coding-cn\"}\n 6005: or base_url_host_matches(self.base_url, \"api.kimi.com\")\n 6006: or base_url_host_matches(self.base_url, \"moonshot.ai\")\n 6007: or base_url_host_matches(self.base_url, \"moonshot.cn\")\n 6008: )\n 6009: \n/home/ubuntu/.hermes/hermes-agent/hermes_cli/setup.py-97- \"google/gemini-3.1-pro-preview\", \"google/gemini\n 3: pro-preview\",\n/home/ubuntu/.hermes/hermes-agent/hermes_cli/setup.py-98- \"google/gemini\n 3: flash-preview\", \"google/gemini-3.1-flash-lite-preview\",\n/home/ubuntu/.hermes/hermes-agent/hermes_cli/setup.py\n 99: \"google/gemini-2.5-pro\", \"google/gemini-2.5-flash\",\n 100: ],\n 101: \"zai\": [\"glm-5.2\", \"glm-5.1\", \"glm-5\", \"glm-4.7\", \"glm-4.5\", \"glm-4.5-flash\"],\n 102: \"kimi-coding\": [\"kimi-k2.6\", \"kimi-k2.5\", \"kimi-k2-thinking\", \"kimi-k2-turbo-preview\"],\n 103: \"kimi-coding-cn\": [\"kimi-k2.6\", \"kimi-k2.5\", \"kimi-k2-thinking\", \"kimi-k2-turbo-preview\"],\n 104: \"stepfun\": [\"step-3.5-flash\", \"step-3.5-flash-2603\"],\n 105: \"arcee\": [\"trinity-large-thinking\", \"trinity-large-preview\", \"trinity-mini\"],\n 106: \"minimax\": [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-M2\"],\n 107: \"minimax-cn\": [\"MiniMax-M2.7\", \"MiniMax-M2.5\", \"MiniMax-M2.1\", \"MiniMax-M2\"],\n/home/ubuntu/.hermes/hermes-agent/hermes_cli/setup.py-108- \"kilocode\": [\"anthropic/claude-opus-4.6\", \"anthropic/claude-sonnet-4.6\", \"openai/gpt-5.4\", \"google/gemini-3-pro-preview\", \"google/gemini\n 3: flash-preview\"],\n/home/ubuntu/.hermes/hermes-agent/hermes_cli/model_normalize.py\n 89: \n 90: # Direct providers that accept bare native names but should repair a matching\n 91: # provider/ prefix when users copy the aggregator form into config.yaml.\n 92: _MATCHING_PREFIX_STRIP_PROVIDERS: frozenset[str] = frozenset({", "truncated": true}
[Hint: Results truncated. Use offset=30 to see more, or narrow with a more specific pattern or file_glob.]
2026-07-22 22:15
ASSISTANT (hermes, glm-5.2)
The built-in Kimi provider is `kimi-coding` using `api.kimi.com`. But the model list doesn't include `kimi-k2.7-code` — let me check what models the Kimi API actually serves.
2026-07-22 22:15
TOOL (hermes, glm-5.2)
[Tool: terminal]
{"output": "Traceback (most recent call last):\n File \"<string>\", line 3, in <module>\n data=json.load(sys.stdin)\n File \"/usr/lib/python3.13/json/__init__.py\", line 293, in load\n return loads(fp.read(),\n cls=cls, object_hook=object_hook,\n parse_float=parse_float, parse_int=parse_int,\n parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw)\n File \"/usr/lib/python3.13/json/__init__.py\", line 346, in loads\n return _default_decoder.decode(s)\n ~~~~~~~~~~~~~~~~~~~~~~~^^^\n File \"/usr/lib/python3.13/json/decoder.py\", line 345, in decode\n obj, end = self.raw_decode(s, idx=_w(s, 0).end())\n ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/lib/python3.13/json/decoder.py\", line 363, in raw_decode\n raise JSONDecodeError(\"Expecting value\", s, err.value) from None\njson.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)", "exit_code": 1, "error": null, "approval": "Command was flagged (Security scan — [HIGH] Pipe to interpreter: curl | python3: Command pipes output from 'curl' directly to interpreter 'python3'. Downloaded content will be executed without inspection.\n Safer: tirith run https://api.kimi.com/v1/models — or: vet https://api.kimi.com/v1/models (https://getvet.sh); script execution via -e/-c flag) and auto-approved by smart approval."}
[Tool: terminal]
{"output": "50:# Legacy keys from platform.moonshot.ai need KIMI_BASE_URL override below.\n52:# KIMI_BASE_URL=https://api.kimi.com/coding/v1 # Default for sk-kimi- keys\n53:# KIMI_BASE_URL=https://api.moonshot.ai/v1 # For legacy Moonshot keys\n54:# KIMI_BASE_URL=https://api.moonshot.cn/v1 # For Moonshot China keys", "exit_code": 0, "error": null}
2026-07-22 22:15
TOOL (hermes, glm-5.2)
[Tool: search_files]
{"total_count": 195, "matches_format": "path-grouped: each file path on its own line, followed by indented '<line>: <content>' rows for matches in that file", "matches_text": "/home/ubuntu/.hermes/hermes-agent/hermes_cli/models.py\n 69: (\"qwen/qwen3.7-plus\", \"\"),\n 70: (\"qwen/qwen3.6-35b-a3b\", \"\"),\n 71: # MoonshotAI\n 72: (\"moonshotai/kimi-k3\", \"recommended\"),\n 73: # MiniMax\n 74: (\"minimax/minimax-m3\", \"\"),\n 75: # Z-AI\n 219: \"qwen/qwen3.7-plus\",\n 220: \"qwen/qwen3.6-35b-a3b\",\n 221: # MoonshotAI\n 222: \"moonshotai/kimi-k3\",\n 223: # MiniMax\n 224: \"minimax/minimax-m3\",\n 225: # Z-AI\n 314: # Third-party agentic models hosted on build.nvidia.com\n 315: # (map to OpenRouter defaults — users get familiar picks on NIM)\n 316: \"z-ai/glm-5.2\",\n 317: \"moonshotai/kimi-k2.6\",\n 318: \"minimaxai/minimax-m3\",\n 319: ],", "truncated": true}
[Hint: Results truncated. Use offset=20 to see more, or narrow with a more specific pattern or file_glob.]
2026-07-22 22:15
ASSISTANT (hermes, glm-5.2)
2026-07-22 22:15
TOOL (hermes, glm-5.2)
[Tool: search_files]
{"total_count": 213, "matches_format": "path-grouped: each file path on its own line, followed by indented '<line>: <content>' rows for matches in that file", "matches_text": "/home/ubuntu/.hermes/hermes-agent/run_agent.py\n 4669: self._client_kwargs[\"default_headers\"] = _routermint_headers()\n 4670: elif base_url_host_matches(base_url, \"githubcopilot.com\"):\n 4671: from hermes_cli.models import copilot_default_headers\n 4672: \n 4673: self._client_kwargs[\"default_headers\"] = copilot_default_headers()\n 4674: elif base_url_host_matches(base_url, \"api.kimi.com\"):\n 4675: self._client_kwargs[\"default_headers\"] = {\"User-Agent\": \"claude-code/0.1.0\"}\n 4676: elif base_url_host_matches(base_url, \"portal.qwen.ai\"):\n 4677: self._client_kwargs[\"default_headers\"] = _qwen_portal_headers()\n 4678: elif base_url_host_matches(base_url, \"chatgpt.com\"):\n 4679: from agent.auxiliary_client import _codex_cloudflare_headers\n 6000: kimi-reasoning replay when the request actually targets a\n 6001: kimi/moonshot endpoint or the dedicated kimi-coding provider.\n 6002: \"\"\"\n 6003: return (\n 6004: self.provider in {\"kimi-coding\", \"kimi-coding-cn\"}\n 6005: or base_url_host_matches(self.base_url, \"api.kimi.com\")\n 6006: or base_url_host_matches(self.base_url, \"moonshot.ai\")\n 6007: or base_url_host_matches(self.base_url, \"moonshot.cn\")\n 6008: )\n 6009: \n 6010: def _needs_deepseek_tool_reasoning(self) -> bool:\n/home/ubuntu/.hermes/hermes-agent/tests/test_base_url_hostname.py\n 67: def test_subdomain_matches(self):\n 68: # A subdomain of the registered domain should match — needed for\n 69: # api.moonshot.ai / api.kimi.com / portal.qwen.ai lookups that\n 70: # accept both the bare registrable domain and any subdomain under it.\n 71: assert base_url_host_matches(\"https://api.moonshot.ai/v1\", \"moonshot.ai\") is True\n 72: assert base_url_host_matches(\"https://api.kimi.com/v1\", \"api.kimi.com\") is True\n 73: assert base_url_host_matches(\"https://portal.qwen.ai/v1\", \"portal.qwen.ai\") is True\n 74: ", "truncated": true}
[Hint: Results truncated. Use offset=30 to see more, or narrow with a more specific pattern or file_glob.]
[Tool: search_files]
{"total_count": 95, "matches_format": "path-grouped: each file path on its own line, followed by indented '<line>: <content>' rows for matches in that file", "matches_text": "/home/ubuntu/.hermes/hermes-agent/hermes_cli/auth.py\n 241: base_url_env_var=\"GEMINI_BASE_URL\",\n 242: ),\n 243: \"zai\": ProviderConfig(\n 244: id=\"zai\",\n 245: name=\"Z.AI / GLM\",\n 246: auth_type=\"api_key\",\n 247: inference_base_url=\"https://api.z.ai/api/paas/v4\",\n 248: api_key_env_vars=(\"GLM_API_KEY\", \"ZAI_API_KEY\", \"Z_AI_API_KEY\"),\n 249: base_url_env_var=\"GLM_BASE_URL\",\n 250: ),\n 251: \"kimi-coding\": ProviderConfig(\n 252: id=\"kimi-coding\",\n 253: name=\"Kimi / Moonshot\",\n 254: auth_type=\"api_key\",\n 255: # Legacy platform.moonshot.ai keys use this endpoint (OpenAI-compat).\n 256: # sk-kimi- (Kimi Code) keys are auto-redirected to api.kimi.com/coding\n 257: # by _resolve_kimi_base_url() below.\n 258: inference_base_url=\"https://api.moonshot.ai/v1\",\n 259: api_key_env_vars=(\"KIMI_API_KEY\", \"KIMI_CODING_API_KEY\"),\n 260: base_url_env_var=\"KIMI_BASE_URL\",", "truncated": true}
[Hint: Results truncated. Use offset=20 to see more, or narrow with a more specific pattern or file_glob.]
2026-07-22 22:15
ASSISTANT (hermes, glm-5.2)
2026-07-22 22:15
TOOL (hermes, glm-5.2)
[Tool: search_files]
{"total_count": 164, "matches_format": "path-grouped: each file path on its own line, followed by indented '<line>: <content>' rows for matches in that file", "matches_text": "/home/ubuntu/.hermes/hermes-agent/hermes_cli/auth.py\n 237: name=\"Google AI Studio\",\n 238: auth_type=\"api_key\",\n 239: inference_base_url=\"https://generativelanguage.googleapis.com/v1beta\",\n 240: api_key_env_vars=(\"GOOGLE_API_KEY\", \"GEMINI_API_KEY\"),\n 241: base_url_env_var=\"GEMINI_BASE_URL\",\n 242: ),\n 243: \"zai\": ProviderConfig(\n 244: id=\"zai\",\n 245: name=\"Z.AI / GLM\",\n 246: auth_type=\"api_key\",\n 247: inference_base_url=\"https://api.z.ai/api/paas/v4\",\n 248: api_key_env_vars=(\"GLM_API_KEY\", \"ZAI_API_KEY\", \"Z_AI_API_KEY\"),\n 249: base_url_env_var=\"GLM_BASE_URL\",\n 250: ),\n 251: \"kimi-coding\": ProviderConfig(\n 252: id=\"kimi-coding\",\n 253: name=\"Kimi / Moonshot\",\n 254: auth_type=\"api_key\",\n 255: # Legacy platform.moonshot.ai keys use this endpoint (OpenAI-compat).\n 256: # sk-kimi- (Kimi Code) keys are auto-redirected to api.kimi.com/coding\n 257: # by _resolve_kimi_base_url() below.\n 258: inference_base_url=\"https://api.moonshot.ai/v1\",\n 259: api_key_env_vars=(\"KIMI_API_KEY\", \"KIMI_CODING_API_KEY\"),\n 260: base_url_env_var=\"KIMI_BASE_URL\",\n 261: ),\n 262: \"kimi-coding-cn\": ProviderConfig(\n 263: id=\"kimi-coding-cn\",\n 264: name=\"Kimi / Moonshot (China)\",\n 265: auth_type=\"api_key\",\n 266: inference_base_url=\"https://api.moonshot.cn/v1\",", "truncated": true}
[Hint: Results truncated. Use offset=30 to see more, or narrow with a more specific pattern or file_glob.]
2026-07-22 22:15
ASSISTANT (hermes, glm-5.2)
2026-07-22 22:16
TOOL (hermes, glm-5.2)
[Tool: search_files]
{"total_count": 41, "matches_format": "path-grouped: each file path on its own line, followed by indented '<line>: <content>' rows for matches in that file", "matches_text": "/home/ubuntu/.hermes/hermes-agent/hermes_cli/auth.py\n 503: return \"\"\n 504: \n 505: \n 506: # =============================================================================\n 507: # Kimi Code Endpoint Detection\n 508: # =============================================================================\n 509: \n 510: # Kimi Code (kimi.com/code) issues keys prefixed \"sk-kimi-\" that only work\n 511: # on api.kimi.com/coding. Legacy keys from platform.moonshot.ai work on\n 512: # api.moonshot.ai/v1 (the old default). Auto-detect when user hasn't set", "truncated": true}
[Hint: Results truncated. Use offset=10 to see more, or narrow with a more specific pattern or file_glob.]
2026-07-22 22:16
ASSISTANT (hermes, glm-5.2)
2026-07-22 22:16
TOOL (hermes, glm-5.2)
[Tool: read_file]
{"content": "510|# Kimi Code (kimi.com/code) issues keys prefixed \"sk-kimi-\" that only work\n511|# on api.kimi.com/coding. Legacy keys from platform.moonshot.ai work on\n512|# api.moonshot.ai/v1 (the old default). Auto-detect when user hasn't set\n513|# KIMI_BASE_URL explicitly.\n514|#\n515|# Note: the base URL intentionally has NO /v1 suffix. The /coding endpoint\n516|# speaks the Anthropic Messages protocol, and the anthropic SDK appends\n517|# \"/v1/messages\" internally — so \"/coding\" + SDK suffix → \"/coding/v1/messages\"\n518|# (the correct target). Using \"/coding/v1\" here would produce\n519|# \"/coding/v1/v1/messages\" (a 404).\n520|KIMI_CODE_BASE_URL = \"https://api.kimi.com/coding\"\n521|\n522|\n523|def _resolve_kimi_base_url(api_key: str, default_url: str, env_override: str) -> str:\n524| \"\"\"Return the correct Kimi base URL based on the API key prefix.\n525|\n526| If the user has explicitly set KIMI_BASE_URL, that always wins.\n527| Otherwise, sk-kimi- prefixed keys route to api.kimi.com/coding/v1.\n528| \"\"\"\n529| if env_override:\n530| return env_override\n531| # No key → nothing to infer from. Return default without inspecting.\n532| if not api_key:\n533| return default_url\n534| if api_key.startswith(\"sk-kimi-\"):\n535| return KIMI_CODE_BASE_URL\n536| return default_url\n537|\n538|\n539|\n540|_PLACEHOLDER_SECRET_VALUES = {\n541| \"*\",\n542| \"**\",\n543| \"***\",\n544| \"changeme\",\n545| \"your_api_key\",\n546| \"your_api_key_here\",\n547| \"your-api-key\",\n548| \"placeholder\",\n549| \"example\",\n550| \"dummy\",\n551| \"null\",\n552| \"none\",\n553|}\n554|\n555|\n556|def has_usable_secret(value: Any, *, min_length: int = 4) -> bool:\n557| \"\"\"Return True when a configured secret looks usable, not empty/placeholder.\"\"\"\n558| if not isinstance(value, str):\n559| return False\n560|", "total_lines": 8446, "file_size": 340761, "truncated": true, "hint": "Use offset=560 to continue reading (showing 510-559 of 8446 lines)", "is_binary": false, "is_image": false}
2026-07-22 22:16
ASSISTANT (hermes, glm-5.2)
Now I understand the full picture. Your key starts with `sk-kimi-`, so Hermes will auto-route it to `https://api.kimi.com/coding`. But there's a catch — the Kimi Code API uses the Anthropic Messages protocol, not OpenAI chat completions. The built-in `kimi-coding` provider handles this. However, the model list in the setup wizard only shows up to `kimi-k2.6` — `kimi-k2.7-code` isn't listed there yet.
Let me check if Kimi's API actually serves `kimi-k2.7-code`:
2026-07-22 22:16
TOOL (hermes, glm-5.2)
[Tool: terminal]
{"output": "{\"error\":{\"message\":\"The API Key appears to be invalid or may have expired. Please verify your credentials and try again.\",\"type\":\"invalid_authentication_error\"}}", "exit_code": 0, "error": null}
2026-07-22 22:16
ASSISTANT (hermes, glm-5.2)
2026-07-22 22:16
TOOL (hermes, glm-5.2)
[Tool: terminal]
{"output": "{\"error\":{\"message\":\"The API Key appears to be invalid or may have expired. Please verify your credentials and try again.\",\"type\":\"invalid_authentication_error\"}}", "exit_code": 0, "error": null}
2026-07-22 22:16
ASSISTANT (hermes, glm-5.2)
2026-07-22 22:16
TOOL (hermes, glm-5.2)
[Tool: terminal]
{"output": "Key prefix: sk-kim...Y4Wx\nFull key length: 72\n{\"error\":{\"type\":\"authentication_error\",\"message\":\"The API Key appears to be invalid or may have expired. Please verify your credentials and try again.\"},\"type\":\"error\"}", "exit_code": 0, "error": null}
2026-07-22 22:16
ASSISTANT (hermes, glm-5.2)
2026-07-22 22:16
TOOL (hermes, glm-5.2)
[Tool: terminal]
{"output": "{\"error\":{\"type\":\"authentication_error\",\"message\":\"The API Key appears to be invalid or may have expired. Please verify your credentials and try again.\"},\"type\":\"error\"}", "exit_code": 0, "error": null}
2026-07-22 22:16
ASSISTANT (hermes, glm-5.2)
2026-07-22 22:16
TOOL (hermes, glm-5.2)
[Tool: terminal]
{"output": "<html>\r\n<head><title>404 Not Found</title></head>\r\n<body>\r\n<center><h1>404 Not Found</h1></center>\r\n<hr><center>nginx</center>\r\n</body>\r\n</html>", "exit_code": 0, "error": null}
[Tool: terminal]
{"output": "{\"error\":{\"message\":\"The API Key appears to be invalid or may have expired. Please verify your credentials and try again.\",\"type\":\"invalid_authentication_error\"}}", "exit_code": 0, "error": null}
2026-07-22 22:16
ASSISTANT (hermes, glm-5.2)
Here's what I found:
1. Your KIMI_API_KEY is saved (starts with `sk-kimi-`, 72 chars)
2. The key is being **rejected by Kimi's API** — I tried both the Anthropic-style endpoint (`api.kimi.com/coding/v1/messages`) and the OpenAI-compatible endpoint, with both `x-api-key` and `Bearer` auth. All return "The API Key appears to be invalid or may have expired."
3. The same key also fails against `api.moonshot.ai/v1`.
Your Kimi API key appears to be **expired or invalid**. You'll need to get a fresh key from https://platform.kimi.ai (Kimi Code console).
Once you have a new key, the switch is simple:
```
hermes config set model.provider kimi-coding
hermes config set model.default kimi-k2.7-code
```
Then update the key in `~/.hermes/.env`:
```
KIMI_API_KEY=***
```
Since your key starts with `sk-kimi-`, Hermes auto-routes it to `https://api.kimi.com/coding` (Anthropic Messages protocol) — no need to set `KIMI_BASE_URL` manually.
Do you want to get a fresh key from Kimi, or would you like me to keep you on Ollama Cloud's `kimi-k2.7-code` in the meantime?
[Tool: read_file]
{"error": "Access denied: /home/ubuntu/.hermes/.env is a Hermes credential store and cannot be read directly. Provider tools consume these credentials through internal channels. (Defense-in-depth \u2014 not a security boundary; the terminal tool can still bypass.)"}
2026-07-22 22:18
ASSISTANT (hermes, glm-5.2)
2026-07-22 22:18
TOOL (hermes, glm-5.2)
[Tool: terminal]
{"output": "Updated line 411:\nKIMI_API_KEY=sk-kimi-***", "exit_code": 0, "error": null, "approval": "Command was flagged (in-place edit of Hermes config/env) and auto-approved by smart approval."}
2026-07-22 22:18
ASSISTANT (hermes, glm-5.2)
Now let me verify this key actually works against Kimi's API before switching the config:
2026-07-22 22:19
TOOL (hermes, glm-5.2)
[Tool: terminal]
{"output": "{\"id\":\"msg_uRjaG6SUibBZ9XnNW2AjXD5W\",\"type\":\"message\",\"role\":\"assistant\",\"content\":[{\"type\":\"thinking\",\"thinking\":\"The user said \\\"say hi\\\". I should respond\",\"signature\":\"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
... [13530 chars total, truncated]
2026-07-22 22:19
ASSISTANT (hermes, glm-5.2)
The new key works — Kimi's API responded with `kimi-k2.7-code`. Now let me switch the config:
2026-07-22 22:19
TOOL (hermes, glm-5.2)
[Tool: terminal]
{"output": "✓ Set model.provider = kimi-coding in /home/ubuntu/.hermes/config.yaml\n✓ Set model.default = kimi-k2.7-code in /home/ubuntu/.hermes/config.yaml", "exit_code": 0, "error": null}
2026-07-22 22:19
ASSISTANT (hermes, glm-5.2)
Now let me clean up the old ollama-cloud settings from the model block (base_url and api_key are stale and would override the Kimi provider auto-detection):
The old `base_url` and `api_key` from Ollama Cloud are still in the model block — those would override the Kimi provider's auto-detection. Let me remove them:
2026-07-22 22:19
TOOL (hermes, glm-5.2)
[Tool: terminal]
{"output": "✓ Set model.base_url = in /home/ubuntu/.hermes/config.yaml\n✓ Set model.api_key = in /home/ubuntu/.hermes/config.yaml", "exit_code": 0, "error": null}
Done. Here's what changed:
- Updated KIMI_API_KEY in ~/.hermes/.env with your new key
- Set model.provider to kimi-coding (Kimi's own API, not Ollama Cloud)
- Set model.default to kimi-k2.7-code
- Removed stale base_url, api_key, and api_mode (were pointing to Ollama Cloud)
Since your key starts with sk-kimi-, Hermes auto-routes to https://api.kimi.com/coding (Anthropic Messages protocol). I verified the key works with a test request — got a valid response.
Start a new session (/new or relaunch hermes) to use kimi-k2.7-code directly through Kimi's API.