Skip to content

feat: support custom request headers and preserve reasoning_content#889

Open
chanchann wants to merge 6 commits intosipeed:mainfrom
chanchann:main
Open

feat: support custom request headers and preserve reasoning_content#889
chanchann wants to merge 6 commits intosipeed:mainfrom
chanchann:main

Conversation

@chanchann
Copy link

@chanchann chanchann commented Feb 28, 2026

📝 Description

Add support for custom HTTP request headers in HTTP-based providers. Users can now specify arbitrary headers (e.g., User-Agent, vendor-specific tokens) per model entry in config.json. This is particularly useful for providers like Kimi for Coding that require a custom User-Agent header for API access.

Additionally, preserve reasoning_content across multi-turn conversations so that models which return chain-of-thought reasoning (e.g., DeepSeek-R1, Kimi) correctly echo it back in subsequent requests.

🗣️ Type of Change

  • 🐞 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 📝 Documentation update
  • ⚡ Code refactoring (no functional changes, no api changes)

🤖 AI Code Generation

  • 🤖 Fully AI-generated (100% AI, 0% Human)
  • 🛠️ Mostly AI-generated (AI draft, Human verified/modified)
  • 👨‍💻 Mostly Human-written (Human lead, AI assisted or none)

🔗 Related Issue

📚 Technical Context

  • Reference URL: N/A

  • Reasoning:

    Some HTTP-based LLM providers require non-standard headers beyond Authorization — for example, Kimi's coding endpoint expects a specific User-Agent to identify the client. Previously there was no way to inject arbitrary headers without modifying source code. This change threads a headers map from the config file all the way through to the HTTP request layer.

    Models that perform chain-of-thought reasoning (e.g., DeepSeek-R1, Kimi) return a reasoning_content field alongside the main content. Without preserving it across turns, the model loses its reasoning context on every follow-up message, degrading response quality.

    Changed files

    File Change Purpose
    pkg/config/config.go Add Headers map[string]string field to ModelConfig Expose headers key in config.json model entries
    pkg/providers/openai_compat/provider.go Add customHeaders field to Provider; add WithCustomHeaders() option; apply headers on every request; add reasoning_content to openaiMessage and populate it in stripSystemParts Core header injection logic + reasoning preservation
    pkg/providers/http_provider.go Add NewHTTPProviderWithOptions() (supersedes NewHTTPProviderWithMaxTokensFieldAndRequestTimeout); old function becomes a thin wrapper Unified constructor that accepts optional headers
    pkg/providers/factory_provider.go Switch all HTTP provider construction to NewHTTPProviderWithOptions() and pass cfg.Headers Wire config → provider
    pkg/tools/toolloop.go Copy ReasoningContent from response into the assistant message appended to history Preserve reasoning across tool-loop turns

    Config example

    {
      "agents": {
        "defaults": {
          "model": "kimi-for-coding"
        }
      },
      "model_list": [
        {
          "model_name": "kimi-for-coding",
          "model": "openai/kimi-for-coding",
          "api_base": "https://api.kimi.com/coding/v1",
          "api_key": "sk-kimi-xxx",
          "headers": {
            "User-Agent": "claude-code/1.0.0"
          }
        }
      ]
    }

    The headers field is optional and omitted by default (omitempty), so existing configurations are unaffected.

🧪 Test Environment

  • Hardware: PC
  • OS: Ubuntu 22.04
  • Model/Provider: Kimi for Coding (openai/kimi-for-coding)
  • Channels: CLI

📸 Evidence (Optional)

Click to view Logs/Screenshots

☑️ Checklist

  • My code/docs follow the style of this project.
  • I have performed a self-review of my own changes.
  • I have updated the documentation accordingly.

@chanchann chanchann changed the title feat(providers): support custom request headers in HTTP providers feat: support kimi-for-coding Feb 28, 2026
Copy link

@nikolasdehor nikolasdehor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good feature overall — custom headers and reasoning_content preservation are both valuable. A few concerns: (1) Security: header override — Custom headers are applied after Authorization via Header.Set, which means a config entry like headers: {Authorization: ...} would silently override the API key. Consider skipping reserved headers (Authorization, Content-Type) or documenting this behavior. (2) Conflict with #876 — This PR and #876 both add reasoning_content to openaiMessage with different field names (Reasoning vs ReasoningContent). These need to be coordinated. (3) Title — The title suggests Kimi-specific support but the changes are generic. Consider renaming. (4) Tests — Please add tests for custom headers, reserved header override behavior, and reasoning_content round-tripping.

@chanchann
Copy link
Author

chanchann commented Feb 28, 2026

Thanks for the detailed review! Here's how I'm addressing each point:

(1) Reserved header protection

Good catch. I'll skip Authorization and Content-Type in the custom headers loop rather than letting them silently override — that's the safer default. I'll add a note in the config docs explaining that these headers are managed internally.

(2) Conflict with #876

I'll rename the Go struct field from Reasoning to ReasoningContent to align the field name with the JSON tag (reasoning_content). I'll also check #876's approach and coordinate — happy to rebase on top of it or split this out if needed.

(3) Title

Will rename to: feat(providers): support custom request headers and preserve reasoning_content

(4) Tests

Will add:

  • TestProviderChat_SendsCustomHeaders — verifies custom header reaches the server
  • TestProviderChat_SkipsReservedHeaders — verifies Authorization/Content-Type are not overridden
  • TestProviderChat_RoundTripsReasoningContent — verifies reasoning_content is serialized in outgoing messages

Will push an updated commit shortly.

@chanchann chanchann changed the title feat: support kimi-for-coding feat: support custom request headers and preserve reasoning_content Feb 28, 2026
@CLAassistant
Copy link

CLAassistant commented Mar 5, 2026

CLA assistant check
All committers have signed the CLA.

@yinwm
Copy link
Collaborator

yinwm commented Mar 6, 2026

@chanchann please fix Linter and tests

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants