Skip to content

fix(kimi): send max_tokens, reasoning_effort, and thinking for Kimi/Moonshot - #13503

Merged
teknium1 merged 2 commits into
mainfrom
hermes/hermes-5763f4db
Apr 21, 2026
Merged

fix(kimi): send max_tokens, reasoning_effort, and thinking for Kimi/Moonshot#13503
teknium1 merged 2 commits into
mainfrom
hermes/hermes-5763f4db

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Salvages #13168 (@mengjian-github) onto current main with hostname-safe URL checks and upstream-faithful disabled-reasoning semantics.

Summary

Kimi/Moonshot endpoints stop returning "Response truncated due to output length limit" — we now send max_tokens=32000, top-level reasoning_effort, and extra_body.thinking={"type":"enabled"}, matching Kimi CLI's generate() + with_thinking() defaults.

Changes

  • run_agent.py _build_api_kwargs():
    • New branch in the max_tokens chain for Kimi/Moonshot hosts → sends max_tokens=32000 + reasoning_effort.
    • New block injecting extra_body.thinking for Kimi/Moonshot hosts, independent of _supports_reasoning_extra_body().
  • tests/run_agent/test_run_agent.py: 6 targeted tests covering kimi.com / moonshot.ai / moonshot.cn, custom effort, and disabled reasoning.

Salvage adjustments on top of #13168

  • Replaced substring checks ("api.kimi.com" in ..., "api.moonshot" in ...) with base_url_host_matches(...) — matches the hostname-hardening sweep (dbb7e00, 5356797) already on main. Incidentally closes https://moonshot.ai.evil.com/v1 and https://evil.com/api.moonshot.ai/v1 false-positive paths (E2E verified).
  • Explicitly cover api.moonshot.cn (China endpoint) — same kimi-coding-cn route already recognized in model_metadata.py.
  • When reasoning_config.enabled=False, omit reasoning_effort entirely (not "medium") — mirrors upstream Kimi CLI's with_thinking("off") mapping reasoning_effort=None. Test updated to assert reasoning_effort is not present in that case.

Note on max_tokens value

Upstream Kimi CLI default is 32000. Official Kimi docs list 32768 as the model default for K2.5/K2.6 and recommend 128k for reasoning / 256k for coding benchmarks. Starting conservative at 32000 to match CLI parity; we can bump this in a follow-up if coding tool-call workloads still truncate.

Validation

  • 29/29 TestBuildApiKwargs tests pass (incl. 6 new).
  • E2E with real AIAgent on isolated HERMES_HOME: all three legit hostnames send the expected params; two attack-shape URLs (evil.com/api.moonshot.ai/v1, moonshot.ai.evil.com/v1) correctly receive nothing.

Closes #13168.

Kian Meng and others added 2 commits April 21, 2026 05:23
…oonshot

Kimi/Moonshot endpoints require explicit parameters that Hermes was not
sending, causing 'Response truncated due to output length limit' errors
and inconsistent reasoning behavior.

Root cause analysis against Kimi CLI source (MoonshotAI/kimi-cli,
packages/kosong/src/kosong/chat_provider/kimi.py):

1. max_tokens: Kimi's API defaults to a very low value when omitted.
   Reasoning tokens share the output budget — the model exhausts it on
   thinking alone.  Send 32000, matching Kimi CLI's generate() default.

2. reasoning_effort: Kimi CLI sends this as a top-level parameter (not
   inside extra_body).  Hermes was not sending it at all because
   _supports_reasoning_extra_body() returns False for non-OpenRouter
   endpoints.

3. extra_body.thinking: Kimi CLI uses with_thinking() which sets
   extra_body.thinking={"type":"enabled"} alongside reasoning_effort.
   This is a separate control from the OpenAI-style reasoning extra_body
   that Hermes sends for OpenRouter/GitHub.  Without it, the Kimi gateway
   may not activate reasoning mode correctly.

Covers api.kimi.com (Kimi Code) and api.moonshot.ai/cn (Moonshot).

Tests: 6 new test cases for max_tokens, reasoning_effort, and
extra_body.thinking under various configs.
@teknium1
teknium1 merged commit 793199a into main Apr 21, 2026
11 of 12 checks passed
@teknium1
teknium1 deleted the hermes/hermes-5763f4db branch April 21, 2026 12:32
teknium1 added a commit that referenced this pull request Apr 22, 2026
Kimi's /coding endpoint speaks the Anthropic Messages protocol but has
its own thinking semantics: when thinking.enabled is sent, Kimi validates
the history and requires every prior assistant tool-call message to carry
OpenAI-style reasoning_content. The Anthropic path never populates that
field, and convert_messages_to_anthropic strips Anthropic thinking blocks
on third-party endpoints — so after one tool-calling turn the next request
fails with:

  HTTP 400: thinking is enabled but reasoning_content is missing in
  assistant tool call message at index N

Kimi on chat_completions handles thinking via extra_body in
ChatCompletionsTransport (#13503). On the Anthropic route, drop the
parameter entirely and let Kimi drive reasoning server-side.

build_anthropic_kwargs now gates the reasoning_config -> thinking block
on not _is_kimi_coding_endpoint(base_url).

Tests: 8 new parametric tests cover /coding, /coding/v1, /coding/anthropic,
/coding/ (trailing slash), explicit disabled, other third-party endpoints
still getting thinking (MiniMax), native Anthropic unaffected, and the
non-/coding Kimi root route.
aj-nt pushed a commit to aj-nt/hermes-agent that referenced this pull request May 1, 2026
…Research#13826)

Kimi's /coding endpoint speaks the Anthropic Messages protocol but has
its own thinking semantics: when thinking.enabled is sent, Kimi validates
the history and requires every prior assistant tool-call message to carry
OpenAI-style reasoning_content. The Anthropic path never populates that
field, and convert_messages_to_anthropic strips Anthropic thinking blocks
on third-party endpoints — so after one tool-calling turn the next request
fails with:

  HTTP 400: thinking is enabled but reasoning_content is missing in
  assistant tool call message at index N

Kimi on chat_completions handles thinking via extra_body in
ChatCompletionsTransport (NousResearch#13503). On the Anthropic route, drop the
parameter entirely and let Kimi drive reasoning server-side.

build_anthropic_kwargs now gates the reasoning_config -> thinking block
on not _is_kimi_coding_endpoint(base_url).

Tests: 8 new parametric tests cover /coding, /coding/v1, /coding/anthropic,
/coding/ (trailing slash), explicit disabled, other third-party endpoints
still getting thinking (MiniMax), native Anthropic unaffected, and the
non-/coding Kimi root route.
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
…Research#13826)

Kimi's /coding endpoint speaks the Anthropic Messages protocol but has
its own thinking semantics: when thinking.enabled is sent, Kimi validates
the history and requires every prior assistant tool-call message to carry
OpenAI-style reasoning_content. The Anthropic path never populates that
field, and convert_messages_to_anthropic strips Anthropic thinking blocks
on third-party endpoints — so after one tool-calling turn the next request
fails with:

  HTTP 400: thinking is enabled but reasoning_content is missing in
  assistant tool call message at index N

Kimi on chat_completions handles thinking via extra_body in
ChatCompletionsTransport (NousResearch#13503). On the Anthropic route, drop the
parameter entirely and let Kimi drive reasoning server-side.

build_anthropic_kwargs now gates the reasoning_config -> thinking block
on not _is_kimi_coding_endpoint(base_url).

Tests: 8 new parametric tests cover /coding, /coding/v1, /coding/anthropic,
/coding/ (trailing slash), explicit disabled, other third-party endpoints
still getting thinking (MiniMax), native Anthropic unaffected, and the
non-/coding Kimi root route.
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
…Research#13826)

Kimi's /coding endpoint speaks the Anthropic Messages protocol but has
its own thinking semantics: when thinking.enabled is sent, Kimi validates
the history and requires every prior assistant tool-call message to carry
OpenAI-style reasoning_content. The Anthropic path never populates that
field, and convert_messages_to_anthropic strips Anthropic thinking blocks
on third-party endpoints — so after one tool-calling turn the next request
fails with:

  HTTP 400: thinking is enabled but reasoning_content is missing in
  assistant tool call message at index N

Kimi on chat_completions handles thinking via extra_body in
ChatCompletionsTransport (NousResearch#13503). On the Anthropic route, drop the
parameter entirely and let Kimi drive reasoning server-side.

build_anthropic_kwargs now gates the reasoning_config -> thinking block
on not _is_kimi_coding_endpoint(base_url).

Tests: 8 new parametric tests cover /coding, /coding/v1, /coding/anthropic,
/coding/ (trailing slash), explicit disabled, other third-party endpoints
still getting thinking (MiniMax), native Anthropic unaffected, and the
non-/coding Kimi root route.
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
…Research#13826)

Kimi's /coding endpoint speaks the Anthropic Messages protocol but has
its own thinking semantics: when thinking.enabled is sent, Kimi validates
the history and requires every prior assistant tool-call message to carry
OpenAI-style reasoning_content. The Anthropic path never populates that
field, and convert_messages_to_anthropic strips Anthropic thinking blocks
on third-party endpoints — so after one tool-calling turn the next request
fails with:

  HTTP 400: thinking is enabled but reasoning_content is missing in
  assistant tool call message at index N

Kimi on chat_completions handles thinking via extra_body in
ChatCompletionsTransport (NousResearch#13503). On the Anthropic route, drop the
parameter entirely and let Kimi drive reasoning server-side.

build_anthropic_kwargs now gates the reasoning_config -> thinking block
on not _is_kimi_coding_endpoint(base_url).

Tests: 8 new parametric tests cover /coding, /coding/v1, /coding/anthropic,
/coding/ (trailing slash), explicit disabled, other third-party endpoints
still getting thinking (MiniMax), native Anthropic unaffected, and the
non-/coding Kimi root route.
smasoftware pushed a commit to smasoftware/hermes-agent that referenced this pull request Jul 18, 2026
…Research#13826)

Kimi's /coding endpoint speaks the Anthropic Messages protocol but has
its own thinking semantics: when thinking.enabled is sent, Kimi validates
the history and requires every prior assistant tool-call message to carry
OpenAI-style reasoning_content. The Anthropic path never populates that
field, and convert_messages_to_anthropic strips Anthropic thinking blocks
on third-party endpoints — so after one tool-calling turn the next request
fails with:

  HTTP 400: thinking is enabled but reasoning_content is missing in
  assistant tool call message at index N

Kimi on chat_completions handles thinking via extra_body in
ChatCompletionsTransport (NousResearch#13503). On the Anthropic route, drop the
parameter entirely and let Kimi drive reasoning server-side.

build_anthropic_kwargs now gates the reasoning_config -> thinking block
on not _is_kimi_coding_endpoint(base_url).

Tests: 8 new parametric tests cover /coding, /coding/v1, /coding/anthropic,
/coding/ (trailing slash), explicit disabled, other third-party endpoints
still getting thinking (MiniMax), native Anthropic unaffected, and the
non-/coding Kimi root route.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant