diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+2.1.0:
+
+- Add `Item_Input_Reasoning` constructor and JSON round-trip test so reasoning traces from tool calls can be echoed back via the Responses API.
+
 2.0.0:
 
 - **BREAKING CHANGE**: Renamed `Item_InputMessage` to `Item_Input_Message` in `OpenAI.V1.Responses` for consistency with new constructors
diff --git a/openai.cabal b/openai.cabal
--- a/openai.cabal
+++ b/openai.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.4
 name:               openai
-version:            2.0.0
+version:            2.1.0
 synopsis:           Servant bindings to OpenAI
 description:        This package provides comprehensive and type-safe bindings
                     to OpenAI, providing both a Servant interface and
diff --git a/src/OpenAI/V1/Responses.hs b/src/OpenAI/V1/Responses.hs
--- a/src/OpenAI/V1/Responses.hs
+++ b/src/OpenAI/V1/Responses.hs
@@ -74,7 +74,7 @@
 
 -- | Role of an input message
 data InputRole = User | System | Developer
-    deriving stock (Generic, Show)
+    deriving stock (Eq, Generic, Show)
 
 instance FromJSON InputRole where
     parseJSON = genericParseJSON aesonOptions
@@ -88,7 +88,7 @@
     | Input_Image { image_url :: Maybe Text, file_id :: Maybe Text, detail :: Maybe Text }
     | Input_File { file_id :: Maybe Text, filename :: Maybe Text, file_url :: Maybe Text, file_data :: Maybe Text }
     | Input_Audio { input_audio :: Object }
-    deriving stock (Generic, Show)
+    deriving stock (Eq, Generic, Show)
 
 inputContentOptions :: Options
 inputContentOptions =
@@ -125,10 +125,17 @@
         , output :: Text
         , status :: Maybe Text
         }
+    | Item_Input_Reasoning
+        { reasoning_id :: Text
+        , reasoning_encrypted_content :: Maybe Text
+        , reasoning_summary :: Maybe (Vector SummaryPart)
+        , reasoning_content :: Maybe (Vector ReasoningText)
+        , reasoning_status :: Maybe Text
+        }
     | Item_Input_Item_Reference
         { id :: Maybe Text
         }
-    deriving stock (Generic, Show)
+    deriving stock (Eq, Generic, Show)
 
 inputItemOptions :: Options
 inputItemOptions =
@@ -136,6 +143,7 @@
         { sumEncoding = TaggedObject{ tagFieldName = "type", contentsFieldName = "" }
         , tagSingleConstructors = True
         , constructorTagModifier = stripPrefix "Item_Input_"
+        , fieldLabelModifier = stripPrefix "reasoning_"
         }
 
 instance FromJSON InputItem where
@@ -491,7 +499,7 @@
 
 -- | Reasoning summary part
 data SummaryPart = Summary_Text{ text :: Text }
-    deriving stock (Generic, Show)
+    deriving stock (Eq, Generic, Show)
 
 summaryPartOptions :: Options
 summaryPartOptions = aesonOptions
@@ -507,7 +515,7 @@
 
 -- | Reasoning text part
 data ReasoningText = Reasoning_Text{ text :: Text }
-    deriving stock (Generic, Show)
+    deriving stock (Eq, Generic, Show)
 
 reasoningTextOptions :: Options
 reasoningTextOptions = aesonOptions
@@ -528,7 +536,7 @@
     , summary :: Maybe (Vector SummaryPart)
     , content :: Maybe (Vector ReasoningText)
     , status :: Maybe Text
-    } deriving stock (Generic, Show)
+    } deriving stock (Eq, Generic, Show)
 
 instance FromJSON ReasoningItem where
     parseJSON = genericParseJSON aesonOptions
diff --git a/tasty/Main.hs b/tasty/Main.hs
--- a/tasty/Main.hs
+++ b/tasty/Main.hs
@@ -5,6 +5,8 @@
 
 module Main where
 
+import Data.Aeson ((.=))
+import qualified Data.Aeson as Aeson
 import Control.Exception (SomeException, catch)
 import OpenAI.V1 (Methods(..))
 import OpenAI.V1.Audio.Speech (CreateSpeech(..), Voice(..), _CreateSpeech)
@@ -975,6 +977,61 @@
 
           return ()
 
+  let responsesReasoningInputSerializationTest =
+        HUnit.testCase "Responses - reasoning input serialization" do
+          let reasoningItem =
+                Responses.Item_Input_Reasoning
+                  { Responses.reasoning_id = "reasoning_123"
+                  , Responses.reasoning_encrypted_content = Just "ciphertext"
+                  , Responses.reasoning_summary =
+                      Just
+                        [ Responses.Summary_Text
+                            { Responses.text = "High-level plan" }
+                        ]
+                  , Responses.reasoning_content =
+                      Just
+                        [ Responses.Reasoning_Text
+                            { Responses.text = "Step 1: inspect tool output." }
+                        ]
+                  , Responses.reasoning_status = Just Responses.statusCompleted
+                  }
+              encoded = Aeson.encode reasoningItem
+              expected :: Aeson.Value
+              expected =
+                Aeson.object
+                  [ "type" .= ("reasoning" :: Text.Text)
+                  , "id" .= ("reasoning_123" :: Text.Text)
+                  , "encrypted_content" .= ("ciphertext" :: Text.Text)
+                  , "summary"
+                      .= ( [ Aeson.object
+                                [ "type" .= ("summary_text" :: Text.Text)
+                                , "text" .= ("High-level plan" :: Text.Text)
+                                ]
+                            ]
+                         :: [Aeson.Value]
+                         )
+                  , "content"
+                      .= ( [ Aeson.object
+                                [ "type" .= ("reasoning_text" :: Text.Text)
+                                , "text" .= ("Step 1: inspect tool output." :: Text.Text)
+                                ]
+                            ]
+                         :: [Aeson.Value]
+                         )
+                  , "status" .= (Responses.statusCompleted :: Text.Text)
+                  ]
+          case Aeson.decode encoded of
+            Nothing ->
+              HUnit.assertFailure "Failed to decode encoded reasoning input item"
+            Just decodedValue ->
+              HUnit.assertEqual "Encoded JSON mismatch" expected decodedValue
+
+          case Aeson.fromJSON expected of
+            Aeson.Error err ->
+              HUnit.assertFailure ("Round-trip decode failed: " <> err)
+            Aeson.Success decoded ->
+              HUnit.assertEqual "Round-trip mismatch" reasoningItem decoded
+
   let tests =
           speechTests
             <> [ transcriptionTest,
@@ -994,6 +1051,7 @@
                createImageVariationMaximalTest,
                createModerationTest,
                responsesMinimalTest,
+               responsesReasoningInputSerializationTest,
                responsesStreamingHaikuTest,
                responsesCodeInterpreterStreamingTest,
                assistantsTest,
