Skip to content

feat(llm): add Reasoning field support for additional provider compatibility#1077

Merged
looplj merged 5 commits intolooplj:release/v0.9.xfrom
djdembeck:feature/reasoning-field-support
Mar 16, 2026
Merged

feat(llm): add Reasoning field support for additional provider compatibility#1077
looplj merged 5 commits intolooplj:release/v0.9.xfrom
djdembeck:feature/reasoning-field-support

Conversation

@djdembeck
Copy link
Copy Markdown
Contributor

@djdembeck djdembeck commented Mar 16, 2026

Problem

AxonHub only supports the reasoning_content field, but some providers return a reasoning field instead, causing reasoning content to be lost when proxying through AxonHub.

Competing Standards in OpenAI-compatible Ecosystem

There are two conventions for reasoning content:

  1. message.reasoning_content - Used by DeepSeek, OpenAI o1/o3
  2. message.reasoning - Used by some providers (e.g., models returning reasoning as a separate field)

Example

Direct API call to a provider using reasoning field returns:

{
  "content": "The equation 1+1=2 is true...",
  "reasoning_content": null,
  "reasoning": "The user is asking Why does 1+1=2?..."
}

Through AxonHub (before fix):

{
  "content": "The equation 1+1=2 is true...",
  "reasoning_content": null,
  "reasoning": null
}

The reasoning field was being lost because the OpenAI Message struct only defined ReasoningContent, missing Reasoning entirely.

Solution

Add native support for the reasoning field alongside reasoning_content in the OpenAI transformer layer with bidirectional fallback logic:

  1. Inbound: If ReasoningContent is nil but Reasoning has value, copy ReasoningReasoningContent
  2. Outbound: Sync both fields - if one is set, populate the other

This ensures compatibility with both conventions without breaking existing DeepSeek functionality.

Changes

  • Added Reasoning *string field to OpenAI Message struct (model.go)
  • Added Reasoning *string field to unified llm.Message struct (llm/model.go)
  • Implemented inbound conversion with fallback (inbound_convert.go)
  • Implemented outbound conversion with bidirectional sync (outbound_convert.go)
  • Added comprehensive unit tests (19 test cases)

Testing

  • ✅ All 19 new unit tests pass
  • ✅ Full LLM test suite passes (35 packages)
  • ✅ Reasoning tests pass on models using reasoning field (14/14)
  • ✅ Reasoning tests pass on models using reasoning_content field (14/14)
  • ✅ DeepSeek backward compatibility maintained

Impact

Fixes reasoning field support for providers using the reasoning field convention.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the LLM transformer by introducing robust support for a new 'Reasoning' field. This change ensures that the system can correctly process and convert reasoning information from various LLM providers, particularly those that utilize a 'Reasoning' field instead of or in addition to 'ReasoningContent'. The modifications span across core message structures and conversion logic, providing a more flexible and compatible integration with diverse LLM services.

Highlights

  • Reasoning Field Support: Added support for handling the 'Reasoning' field in OpenAI API conversions, accommodating providers that use this alternative field.
  • Bidirectional Transformation: Implemented bidirectional transformation logic for the 'Reasoning' field during both inbound and outbound conversions to ensure data consistency.
  • Comprehensive Unit Tests: Included extensive unit tests to validate the correct behavior and various scenarios for the new 'Reasoning' field support.
Changelog
  • llm/model.go
    • Added a new 'Reasoning' field to the core 'llm.Message' struct to support alternative reasoning representations.
  • llm/transformer/openai/inbound_convert.go
    • Updated the 'ToLLMMessage' function to correctly map the new 'Reasoning' field and implemented fallback logic to populate 'ReasoningContent' if 'Reasoning' is present and 'ReasoningContent' is empty.
  • llm/transformer/openai/inbound_convert_test.go
    • Added a new test file containing comprehensive unit tests for the inbound conversion of the 'Reasoning' field, covering various scenarios including fallback and synchronization.
  • llm/transformer/openai/model.go
    • Included the 'Reasoning' field in the OpenAI transformer's 'Message' struct to align with the new core message structure.
  • llm/transformer/openai/outbound_convert.go
    • Modified the 'MessageFromLLM' function to handle bidirectional conversion and fallback logic between the 'Reasoning' and 'ReasoningContent' fields for outbound messages.
Activity
  • No specific activity (comments, reviews, progress) has been recorded for this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@djdembeck djdembeck changed the title feat: add Reasoning field support to LLM transformer feat(llm): add Reasoning field support for Synthetic API compatibility Mar 16, 2026
@djdembeck djdembeck changed the title feat(llm): add Reasoning field support for Synthetic API compatibility feat(llm): add Reasoning field support for additional provider compatibility Mar 16, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request adds support for a Reasoning field in the LLM transformer, which is a good enhancement for compatibility with various providers. The changes are mostly well-implemented, with comprehensive unit tests. However, I've identified a critical bug in the outbound conversion logic when handling foreign reasoning signatures, which could lead to incorrect data being sent to the upstream service. The corresponding unit test also asserts this buggy behavior. I've provided suggestions to correct both the implementation and the test.

Refines the reasoning field handling in MessageFromLLM to properly clear
both reasoning and reasoningContent fields when a foreign signature is
detected, preventing provider-specific data from being sent to OpenAI.
@looplj looplj merged commit f37da22 into looplj:release/v0.9.x Mar 16, 2026
2 checks passed
@djdembeck djdembeck deleted the feature/reasoning-field-support branch April 3, 2026 03:58
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.

2 participants