diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,28 @@
+2.0.0:
+
+- **BREAKING CHANGE**: Renamed `Item_InputMessage` to `Item_Input_Message` in `OpenAI.V1.Responses` for consistency with new constructors
+
+  The `InputItem` data type in the Responses API has been updated to use a consistent naming scheme. If you are using the Responses API, you will need to update your code:
+
+  ```haskell
+  -- Before (v1.2.0):
+  Item_InputMessage { role = ..., content = ..., status = ... }
+
+  -- After (v2.0.0):
+  Item_Input_Message { role = ..., content = ..., status = ... }
+  ```
+
+- Add support for function tool calls in Responses API
+  - New `InputItem` constructors: `Item_Input_Function_Call`, `Item_Input_Function_Call_Output`, `Item_Input_Item_Reference`
+  - Add flattened tool JSON representation for Responses API compatibility
+  - Export status constants: `statusIncomplete`, `statusCompleted`
+  - Export tool choice constants: `toolChoiceNoneText`, `toolChoiceAutoText`, `toolChoiceRequiredText`
+
+- Code quality improvements:
+  - Optimize `isFunctionField` using `HashSet` for O(1) lookups
+  - Simplify `unflattenChoice` with guards
+  - Extract magic strings as named constants
+
 1.2.0:
 
 - [`/v1/responses`: Add support for Responses API](https://platform.openai.com/docs/api-reference/responses)
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -61,7 +61,7 @@
     let req = Responses._CreateResponse
             { Responses.model = "gpt-5"
             , Responses.input = Just (Responses.Input
-                [ Responses.Item_InputMessage
+                [ Responses.Item_Input_Message
                     { Responses.role = Responses.User
                     , Responses.content = [ Responses.Input_Text{ Responses.text = "Say hello in one sentence." } ]
                     , Responses.status = Nothing
diff --git a/examples/openai-example/Main.hs b/examples/openai-example/Main.hs
--- a/examples/openai-example/Main.hs
+++ b/examples/openai-example/Main.hs
@@ -1,7 +1,7 @@
 {-# LANGUAGE DuplicateRecordFields #-}
 {-# LANGUAGE NamedFieldPuns        #-}
-{-# LANGUAGE OverloadedStrings     #-}
 {-# LANGUAGE OverloadedLists       #-}
+{-# LANGUAGE OverloadedStrings     #-}
 
 module Main where
 
diff --git a/examples/responses-example/Main.hs b/examples/responses-example/Main.hs
--- a/examples/responses-example/Main.hs
+++ b/examples/responses-example/Main.hs
@@ -1,16 +1,17 @@
-{-# LANGUAGE OverloadedLists #-}
-{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE DuplicateRecordFields #-}
-{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE OverloadedLists       #-}
+{-# LANGUAGE OverloadedStrings     #-}
 
 module Main where
 
 import Data.Foldable (toList)
+import System.Environment (getEnv)
+
 import qualified Data.Text as Text
 import qualified Data.Text.IO as TextIO
 import qualified OpenAI.V1 as V1
 import qualified OpenAI.V1.Responses as Responses
-import System.Environment (getEnv)
 
 main :: IO ()
 main = do
@@ -22,7 +23,7 @@
     let req = Responses._CreateResponse
             { Responses.model = "gpt-5"
             , Responses.input = Just (Responses.Input
-                [ Responses.Item_InputMessage
+                [ Responses.Item_Input_Message
                     { Responses.role = Responses.User
                     , Responses.content = [ Responses.Input_Text{ Responses.text = "Tell me a three sentence bedtime story about a unicorn." } ]
                     , Responses.status = Nothing
diff --git a/examples/responses-stream-example/Main.hs b/examples/responses-stream-example/Main.hs
--- a/examples/responses-stream-example/Main.hs
+++ b/examples/responses-stream-example/Main.hs
@@ -1,17 +1,18 @@
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE OverloadedLists #-}
 {-# LANGUAGE DuplicateRecordFields #-}
-{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE OverloadedLists       #-}
+{-# LANGUAGE OverloadedStrings     #-}
 
 module Main where
 
+import System.Environment (getEnv)
+import System.IO (hFlush, hPutStrLn, stderr, stdout)
+
 import qualified Data.Text as T
 import qualified Data.Text.IO as TIO
 import qualified OpenAI.V1 as V1
 import qualified OpenAI.V1.Responses as Responses
 import qualified OpenAI.V1.Tool as Tool
-import System.Environment (getEnv)
-import System.IO (hFlush, hPutStrLn, stderr, stdout)
 
 main :: IO ()
 main = do
@@ -33,7 +34,7 @@
     let reqHaiku = Responses._CreateResponse
             { Responses.model = "gpt-5-mini"
             , Responses.input = Just (Responses.Input
-                [ Responses.Item_InputMessage
+                [ Responses.Item_Input_Message
                     { Responses.role = Responses.User
                     , Responses.content = [ Responses.Input_Text{ Responses.text = "Write a short haiku about the sea." } ]
                     , Responses.status = Nothing
@@ -42,14 +43,14 @@
             }
 
     createResponseStreamTyped reqHaiku onEvent
-    
+
     putStrLn "--------------------------------"
 
     -- 2) Web search example
     let reqSearch = Responses._CreateResponse
             { Responses.model = "gpt-5-mini"
             , Responses.input = Just (Responses.Input
-                [ Responses.Item_InputMessage
+                [ Responses.Item_Input_Message
                     { Responses.role = Responses.User
                     , Responses.content = [ Responses.Input_Text{ Responses.text = "Use web_search to find current news about France and display a concise summary. Do not include citations, references, or URLs in the output; provide only the summary text." } ]
                     , Responses.status = Nothing
@@ -67,7 +68,7 @@
             { Responses.model = "gpt-5-mini"
             , Responses.instructions = Just "You are a personal math tutor. When asked a math question, write and run code using the python tool to answer the question."
             , Responses.input = Just (Responses.Input
-                [ Responses.Item_InputMessage
+                [ Responses.Item_Input_Message
                     { Responses.role = Responses.User
                     , Responses.content = [ Responses.Input_Text{ Responses.text = "I need to solve the equation 3x + 11 = 14. Can you help me?" } ]
                     , Responses.status = Nothing
diff --git a/examples/responses-tool-call-example/Main.hs b/examples/responses-tool-call-example/Main.hs
new file mode 100644
--- /dev/null
+++ b/examples/responses-tool-call-example/Main.hs
@@ -0,0 +1,168 @@
+{-# LANGUAGE DuplicateRecordFields #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedLists #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module Main where
+
+import Data.Aeson (FromJSON (..), (.:), (.=), withObject)
+import qualified Data.Aeson as Aeson
+import qualified Data.ByteString.Lazy as LBS
+import Data.Foldable (toList)
+import Data.Text (Text)
+import qualified Data.Text as Text
+import qualified Data.Text.Encoding as Text.Encoding
+import qualified Data.Text.IO as TextIO
+import qualified Data.Vector as Vector
+import OpenAI.V1 (Methods (..))
+import qualified OpenAI.V1 as V1
+import qualified OpenAI.V1.Responses as Responses
+import OpenAI.V1.Tool (Function (..), Tool (..))
+import System.Environment (getEnv)
+
+-- | Simple JSON payload for parsing function arguments
+newtype HoroscopeArgs = HoroscopeArgs { sign :: Text }
+
+instance FromJSON HoroscopeArgs where
+    parseJSON = withObject "HoroscopeArgs" $ \obj -> do
+        sign <- obj .: "sign"
+        pure HoroscopeArgs{ sign }
+
+getHoroscope :: Text -> Text
+getHoroscope sign = sign <> ": Next Tuesday you will befriend a baby otter."
+
+horoscopeTool :: Tool
+horoscopeTool =
+    Tool_Function
+        Function
+            { description = Just "Get today's horoscope for an astrological sign."
+            , name = "get_horoscope"
+            , parameters =
+                Just . Aeson.object $
+                    [ "type" .= ("object" :: Text)
+                    , "properties"
+                        .= Aeson.object
+                            [ "sign"
+                                .= Aeson.object
+                                    [ "type" .= ("string" :: Text)
+                                    , "description" .= ("An astrological sign like Taurus or Aquarius" :: Text)
+                                    ]
+                            ]
+                    , "required" .= (["sign"] :: [Text])
+                    , "additionalProperties" .= False
+                    ]
+            , strict = Just True
+            }
+
+main :: IO ()
+main = do
+    key <- Text.pack <$> getEnv "OPENAI_KEY"
+    env <- V1.getClientEnv "https://api.openai.com"
+
+    let Methods{ createResponse } = V1.makeMethods env key Nothing Nothing
+        userMessage =
+            Responses.Item_Input_Message
+                { Responses.role = Responses.User
+                , Responses.content = Vector.singleton Responses.Input_Text{ Responses.text = "What is my horoscope? I am an Aquarius." }
+                , Responses.status = Nothing
+                }
+        initialItems = [userMessage]
+        initialInput = Responses.Input (Vector.fromList initialItems)
+        firstRequest =
+            Responses._CreateResponse
+                { Responses.model = "gpt-5"
+                , Responses.input = Just initialInput
+                , Responses.tools = Just [horoscopeTool]
+                }
+
+    firstResponse <- createResponse firstRequest
+
+    let Responses.ResponseObject{ Responses.output = outputItems } = firstResponse
+        outputList = toList outputItems
+        hasFunctionCall = Prelude.any isFunctionCall outputList
+
+    if not hasFunctionCall
+        then mapM_ TextIO.putStrLn (collectText firstResponse)
+        else do
+            additionalInputs <- gatherInputs outputList
+
+            let finalItems = initialItems <> additionalInputs
+                finalInput = Responses.Input (Vector.fromList finalItems)
+                secondRequest =
+                    Responses._CreateResponse
+                        { Responses.model = "gpt-5"
+                        , Responses.instructions = Just "Respond only with a horoscope generated by a tool."
+                        , Responses.input = Just finalInput
+                        , Responses.tools = Just [horoscopeTool]
+                        }
+
+            finalResponse <- createResponse secondRequest
+
+            mapM_ TextIO.putStrLn (collectText finalResponse)
+
+isFunctionCall :: Responses.OutputItem -> Bool
+isFunctionCall Responses.Item_FunctionToolCall{} = True
+isFunctionCall _ = False
+
+gatherInputs :: [Responses.OutputItem] -> IO [Responses.InputItem]
+gatherInputs [] = pure []
+gatherInputs (item : rest) =
+    case item of
+        Responses.Item_Reasoning{ Responses.reasoning_id } -> do
+            restInputs <- gatherInputs rest
+            let reference = Responses.Item_Input_Item_Reference{ Responses.id = Just reasoning_id }
+            pure (reference : restInputs)
+        call@Responses.Item_FunctionToolCall{} -> do
+            (callInput, callOutput) <- processFunctionCall call
+            restInputs <- gatherInputs rest
+            pure (callInput : callOutput : restInputs)
+        _ -> gatherInputs rest
+
+processFunctionCall
+    :: Responses.OutputItem
+    -> IO (Responses.InputItem, Responses.InputItem)
+processFunctionCall
+    Responses.Item_FunctionToolCall
+        { Responses.function_id = functionId
+        , Responses.function_call_id = callId
+        , Responses.function_name = functionName
+        , Responses.function_arguments = argumentsText
+        , Responses.function_status = statusText
+        } = do
+    let callInput =
+            Responses.Item_Input_Function_Call
+                { Responses.id = functionId
+                , Responses.call_id = callId
+                , Responses.name = functionName
+                , Responses.arguments = argumentsText
+                , Responses.status = statusText
+                }
+        argumentsBytes = Text.Encoding.encodeUtf8 argumentsText
+
+        makeOutput status payload =
+            Responses.Item_Input_Function_Call_Output
+                { Responses.id = Nothing
+                , Responses.call_id = callId
+                , Responses.output = encodePayload payload
+                , Responses.status = Just status
+                }
+
+        encodePayload = Text.Encoding.decodeUtf8 . LBS.toStrict . Aeson.encode
+
+    result <- case Aeson.eitherDecodeStrict' argumentsBytes of
+        Left err ->
+            pure $ makeOutput Responses.statusIncomplete (Aeson.object ["error" .= Text.pack err])
+        Right HoroscopeArgs{ sign } -> do
+            let horoscope = getHoroscope sign
+            pure $ makeOutput Responses.statusCompleted (Aeson.object ["horoscope" .= horoscope])
+
+    pure (callInput, result)
+processFunctionCall other =
+    error $ "Unexpected output item: " <> show other
+
+collectText :: Responses.ResponseObject -> [Text]
+collectText Responses.ResponseObject{ Responses.output } =
+    [ text
+    | Responses.Item_OutputMessage{ Responses.message_content } <- toList output
+    , Responses.Output_Text{ Responses.text } <- toList message_content
+    ]
diff --git a/examples/weather-chatbot-example/Main.hs b/examples/weather-chatbot-example/Main.hs
--- a/examples/weather-chatbot-example/Main.hs
+++ b/examples/weather-chatbot-example/Main.hs
@@ -1,12 +1,12 @@
 {-# LANGUAGE DuplicateRecordFields #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE OverloadedLists #-}
-{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE OverloadedLists       #-}
+{-# LANGUAGE OverloadedStrings     #-}
 
 module Main where
 
 import Control.Monad (foldM, when)
-import Data.Aeson (Value (..), (.=))
+import Data.Aeson (Value(..), (.=))
 import Data.Text (Text)
 import Data.Vector (Vector)
 import GHC.Exts (toList)
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:            1.2.0
+version:            2.0.0
 synopsis:           Servant bindings to OpenAI
 description:        This package provides comprehensive and type-safe bindings
                     to OpenAI, providing both a Servant interface and
@@ -42,6 +42,7 @@
                       , servant-multipart-client
                       , text
                       , time
+                      , unordered-containers
                       , vector
     exposed-modules:    OpenAI.V1
                         OpenAI.V1.Assistants
@@ -145,6 +146,18 @@
     hs-source-dirs:   examples/responses-example
     main-is:          Main.hs
     build-depends:    base
+                    , openai
+                    , text
+                    , vector
+    ghc-options:      -Wall
+
+executable responses-tool-call-example
+    default-language: Haskell2010
+    hs-source-dirs:   examples/responses-tool-call-example
+    main-is:          Main.hs
+    build-depends:    base
+                    , aeson
+                    , bytestring
                     , openai
                     , text
                     , vector
diff --git a/src/OpenAI/Prelude.hs b/src/OpenAI/Prelude.hs
--- a/src/OpenAI/Prelude.hs
+++ b/src/OpenAI/Prelude.hs
@@ -3,13 +3,11 @@
       aesonOptions
     , stripPrefix
     , labelModifier
-
       -- * Multipart Form Data
     , input
     , renderIntegral
     , renderRealFloat
     , getExtension
-
       -- * Re-exports
     , module Data.Aeson
     , module Data.ByteString.Lazy
@@ -43,9 +41,9 @@
 
 import Data.Aeson
     ( FromJSON(..)
-    , ToJSON(..)
     , Options(..)
     , SumEncoding(..)
+    , ToJSON(..)
     , Value(..)
     , genericParseJSON
     , genericToJSON
@@ -73,8 +71,8 @@
     , Input(..)
     , MultipartData(..)
     , MultipartForm
-    , ToMultipart(..)
     , Tmp
+    , ToMultipart(..)
     )
 
 import qualified Data.Aeson as Aeson
@@ -83,8 +81,8 @@
 import qualified Data.Text as Text
 import qualified Data.Text.Lazy as Text.Lazy
 import qualified Data.Text.Lazy.Builder as Builder
-import qualified Data.Text.Lazy.Builder.RealFloat as RealFloat
 import qualified Data.Text.Lazy.Builder.Int as Int
+import qualified Data.Text.Lazy.Builder.RealFloat as RealFloat
 import qualified System.FilePath as FilePath
 
 dropTrailingUnderscore :: String -> String
diff --git a/src/OpenAI/V1.hs b/src/OpenAI/V1.hs
--- a/src/OpenAI/V1.hs
+++ b/src/OpenAI/V1.hs
@@ -40,50 +40,43 @@
 
 module OpenAI.V1
     ( -- * Methods
-      getClientEnv
+      Methods(..)
+    , getClientEnv
     , makeMethods
-    , Methods(..)
-
       -- * Servant
     , API
     ) where
 
+import Control.Monad (foldM)
 import Data.ByteString.Char8 ()
 import Data.Proxy (Proxy(..))
 import OpenAI.Prelude
 import OpenAI.V1.Audio.Speech (CreateSpeech)
-import OpenAI.V1.Embeddings (CreateEmbeddings, EmbeddingObject)
+import OpenAI.V1.Audio.Transcriptions (CreateTranscription, TranscriptionObject)
+import OpenAI.V1.Audio.Translations (CreateTranslation, TranslationObject)
 import OpenAI.V1.Batches (BatchID, BatchObject, CreateBatch)
+import OpenAI.V1.Chat.Completions (ChatCompletionObject, CreateChatCompletion)
 import OpenAI.V1.DeletionStatus (DeletionStatus)
+import OpenAI.V1.Embeddings (CreateEmbeddings, EmbeddingObject)
 import OpenAI.V1.Files (FileID, FileObject, UploadFile)
-import OpenAI.V1.Images.Image (ImageObject)
-import OpenAI.V1.Images.Generations (CreateImage)
 import OpenAI.V1.Images.Edits (CreateImageEdit)
+import OpenAI.V1.Images.Generations (CreateImage)
+import OpenAI.V1.Images.Image (ImageObject)
 import OpenAI.V1.Images.Variations (CreateImageVariation)
 import OpenAI.V1.ListOf (ListOf(..))
 import OpenAI.V1.Message (Message)
 import OpenAI.V1.Models (Model, ModelObject)
 import OpenAI.V1.Moderations (CreateModeration, Moderation)
 import OpenAI.V1.Order (Order)
-import OpenAI.V1.Threads (Thread, ThreadID, ModifyThread, ThreadObject)
+import OpenAI.V1.Responses (CreateResponse, InputItem, ResponseObject)
+import OpenAI.V1.Threads (ModifyThread, Thread, ThreadID, ThreadObject)
+import OpenAI.V1.Threads.Messages (MessageID, MessageObject, ModifyMessage)
 import OpenAI.V1.Threads.Runs.Steps (RunStepObject(..), StepID)
 import Servant.Client (ClientEnv)
 import Servant.Multipart.Client ()
 
 import OpenAI.V1.Assistants
     (AssistantID, AssistantObject, CreateAssistant, ModifyAssistant)
-import OpenAI.V1.Audio.Transcriptions
-    (CreateTranscription, TranscriptionObject)
-import OpenAI.V1.Audio.Translations
-    (CreateTranslation, TranslationObject)
-import OpenAI.V1.Chat.Completions
-    (ChatCompletionObject, CreateChatCompletion)
-import OpenAI.V1.Responses
-    ( CreateResponse
-    , ResponseObject
-    , InputItem
-    )
-import qualified OpenAI.V1.Responses as Responses
 import OpenAI.V1.FineTuning.Jobs
     ( CheckpointObject
     , CreateFineTuningJob
@@ -91,8 +84,6 @@
     , FineTuningJobID
     , JobObject
     )
-import OpenAI.V1.Threads.Messages
-    (MessageID, MessageObject, ModifyMessage)
 import OpenAI.V1.Threads.Runs
     ( CreateRun
     , CreateThreadAndRun
@@ -115,45 +106,42 @@
     , VectorStoreID
     , VectorStoreObject(..)
     )
-import OpenAI.V1.VectorStores.Files
-    ( CreateVectorStoreFile(..)
-    , VectorStoreFileID
-    , VectorStoreFileObject(..)
-    )
 import OpenAI.V1.VectorStores.FileBatches
     ( CreateVectorStoreFileBatch(..)
-    , VectorStoreFilesBatchObject(..)
     , VectorStoreFileBatchID
+    , VectorStoreFilesBatchObject(..)
     )
+import OpenAI.V1.VectorStores.Files
+    (CreateVectorStoreFile(..), VectorStoreFileID, VectorStoreFileObject(..))
 
 import qualified Control.Exception as Exception
-import qualified Data.Text as Text
-import qualified Network.HTTP.Client as HTTP.Client
-import qualified Network.HTTP.Client.TLS as TLS
-import qualified Network.HTTP.Types.Status as Status
 import qualified Data.Aeson as Aeson
 import qualified Data.ByteString as SBS
 import qualified Data.ByteString.Char8 as S8
-import Control.Monad (foldM)
 import qualified Data.IORef as IORef
+import qualified Data.Text as Text
+import qualified Network.HTTP.Client as HTTP.Client
+import qualified Network.HTTP.Client.TLS as TLS
+import qualified Network.HTTP.Types.Status as Status
 import qualified OpenAI.V1.Assistants as Assistants
 import qualified OpenAI.V1.Audio as Audio
 import qualified OpenAI.V1.Batches as Batches
 import qualified OpenAI.V1.Chat.Completions as Chat.Completions
 import qualified OpenAI.V1.Embeddings as Embeddings
-import qualified OpenAI.V1.FineTuning.Jobs as FineTuning.Jobs
 import qualified OpenAI.V1.Files as Files
+import qualified OpenAI.V1.FineTuning.Jobs as FineTuning.Jobs
 import qualified OpenAI.V1.Images as Images
 import qualified OpenAI.V1.Models as Models
 import qualified OpenAI.V1.Moderations as Moderations
-import qualified OpenAI.V1.Threads.Runs as Threads.Runs
-import qualified OpenAI.V1.Threads.Runs.Steps as Threads.Runs.Steps
+import qualified OpenAI.V1.Responses as Responses
 import qualified OpenAI.V1.Threads as Threads
 import qualified OpenAI.V1.Threads.Messages as Messages
+import qualified OpenAI.V1.Threads.Runs as Threads.Runs
+import qualified OpenAI.V1.Threads.Runs.Steps as Threads.Runs.Steps
 import qualified OpenAI.V1.Uploads as Uploads
 import qualified OpenAI.V1.VectorStores as VectorStores
-import qualified OpenAI.V1.VectorStores.Files as VectorStores.Files
 import qualified OpenAI.V1.VectorStores.FileBatches as VectorStores.FileBatches
+import qualified OpenAI.V1.VectorStores.Files as VectorStores.Files
 import qualified OpenAI.V1.VectorStores.Status as VectorStores.Status
 import qualified Servant.Client as Client
 
@@ -271,7 +259,7 @@
                 :<|>  retrieveRunStep
                 )
             )
-      
+
       :<|>  (   (\x -> x "assistants=v2")
             ->  (     createVectorStore
                 :<|>  listVectorStores_
diff --git a/src/OpenAI/V1/Assistants.hs b/src/OpenAI/V1/Assistants.hs
--- a/src/OpenAI/V1/Assistants.hs
+++ b/src/OpenAI/V1/Assistants.hs
@@ -7,7 +7,6 @@
     , ModifyAssistant(..)
     , _ModifyAssistant
     , AssistantObject(..)
-
       -- * Other types
     , RankingOptions
     , FileSearch(..)
@@ -16,7 +15,6 @@
     , CodeInterpreterResources(..)
     , FileSearchResources(..)
     , ToolResources(..)
-
       -- * Servant
     , API
     ) where
diff --git a/src/OpenAI/V1/Audio.hs b/src/OpenAI/V1/Audio.hs
--- a/src/OpenAI/V1/Audio.hs
+++ b/src/OpenAI/V1/Audio.hs
@@ -5,6 +5,7 @@
     ) where
 
 import OpenAI.Prelude
+
 import qualified OpenAI.V1.Audio.Speech as Speech
 import qualified OpenAI.V1.Audio.Transcriptions as Transcriptions
 import qualified OpenAI.V1.Audio.Translations as Translations
diff --git a/src/OpenAI/V1/Chat/Completions.hs b/src/OpenAI/V1/Chat/Completions.hs
--- a/src/OpenAI/V1/Chat/Completions.hs
+++ b/src/OpenAI/V1/Chat/Completions.hs
@@ -28,7 +28,7 @@
     , FinishReason(..)
     , Token(..)
     , LogProbs(..)
-    -- * Servant
+      -- * Servant
     , API
     ) where
 
diff --git a/src/OpenAI/V1/ChunkingStrategy.hs b/src/OpenAI/V1/ChunkingStrategy.hs
--- a/src/OpenAI/V1/ChunkingStrategy.hs
+++ b/src/OpenAI/V1/ChunkingStrategy.hs
@@ -2,7 +2,6 @@
 module OpenAI.V1.ChunkingStrategy
     ( -- * Main types
       ChunkingStrategy(..)
-
       -- * Other types
     , Static(..)
     ) where
diff --git a/src/OpenAI/V1/Files.hs b/src/OpenAI/V1/Files.hs
--- a/src/OpenAI/V1/Files.hs
+++ b/src/OpenAI/V1/Files.hs
@@ -5,11 +5,11 @@
     , UploadFile(..)
     , _UploadFile
     , FileObject(..)
-    -- * Other types
+      -- * Other types
     , Order(..)
     , Purpose(..)
     , DeletionStatus(..)
-    -- * Servant
+      -- * Servant
     , API
     ) where
 
diff --git a/src/OpenAI/V1/FineTuning/Jobs.hs b/src/OpenAI/V1/FineTuning/Jobs.hs
--- a/src/OpenAI/V1/FineTuning/Jobs.hs
+++ b/src/OpenAI/V1/FineTuning/Jobs.hs
@@ -7,7 +7,6 @@
     , JobObject(..)
     , EventObject(..)
     , CheckpointObject(..)
-
       -- * Other types
     , AutoOr(..)
     , Hyperparameters(..)
@@ -16,7 +15,6 @@
     , Status(..)
     , Level(..)
     , Metrics(..)
-
       -- * Servant
     , API
     ) where
@@ -25,8 +23,8 @@
 import OpenAI.V1.AutoOr
 import OpenAI.V1.Error
 import OpenAI.V1.Files (FileID)
-import OpenAI.V1.Models (Model)
 import OpenAI.V1.ListOf
+import OpenAI.V1.Models (Model)
 
 -- | Fine tuning job ID
 newtype FineTuningJobID = FineTuningJobID{ text :: Text }
diff --git a/src/OpenAI/V1/Images.hs b/src/OpenAI/V1/Images.hs
--- a/src/OpenAI/V1/Images.hs
+++ b/src/OpenAI/V1/Images.hs
@@ -6,8 +6,8 @@
 
 import OpenAI.Prelude
 
-import qualified OpenAI.V1.Images.Generations as Generations
 import qualified OpenAI.V1.Images.Edits as Edits
+import qualified OpenAI.V1.Images.Generations as Generations
 import qualified OpenAI.V1.Images.Variations as Variations
 
 -- | Servant API
diff --git a/src/OpenAI/V1/Message.hs b/src/OpenAI/V1/Message.hs
--- a/src/OpenAI/V1/Message.hs
+++ b/src/OpenAI/V1/Message.hs
@@ -2,7 +2,6 @@
 module OpenAI.V1.Message
     ( -- * Main types
       Message(..)
-
       -- * Other types
     , ImageFile(..)
     , ImageURL(..)
diff --git a/src/OpenAI/V1/Models.hs b/src/OpenAI/V1/Models.hs
--- a/src/OpenAI/V1/Models.hs
+++ b/src/OpenAI/V1/Models.hs
@@ -3,7 +3,6 @@
     ( -- * Main types
       Model(..)
     , ModelObject(..)
-
       -- * Servant
     , API
     ) where
diff --git a/src/OpenAI/V1/Moderations.hs b/src/OpenAI/V1/Moderations.hs
--- a/src/OpenAI/V1/Moderations.hs
+++ b/src/OpenAI/V1/Moderations.hs
@@ -4,11 +4,9 @@
       CreateModeration(..)
     , _CreateModeration
     , Moderation(..)
-
       -- * Other types
     , InputType(..)
     , Result(..)
-
       -- * Servant
     , API
     ) where
@@ -44,9 +42,10 @@
     { flagged :: Bool
     , categories :: Map Text Bool
     , category_scores :: Map Text Double
-    , category_applied_input_types :: Maybe (Map Text InputType)
+    , category_applied_input_types :: Maybe (Map Text [InputType])
     -- According to the OpenAPI spec the `category_applied_input_types`
     -- field is required but their actual implementation omits this field.
+    -- Note: Each category maps to a list of input types (e.g., ["text"], ["image"])
     } deriving stock (Generic, Show)
       deriving anyclass (FromJSON, ToJSON)
 
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
@@ -30,18 +30,38 @@
     , ResponseUsage(..)
     , InputTokensDetails(..)
     , OutputTokensDetails(..)
-
+      -- * Constants
+    , statusIncomplete
+    , statusCompleted
       -- * Servant
     , API
     ) where
 
-import OpenAI.Prelude hiding (Input(..))
 import Data.Aeson (Object)
+import qualified Data.Aeson as Aeson
+import OpenAI.Prelude hiding (Input(..))
 -- no TH; inline JSON instances for payloads
 import OpenAI.V1.ListOf (ListOf)
 import OpenAI.V1.Models (Model)
-import OpenAI.V1.Tool (Tool, ToolChoice)
+import qualified Data.Aeson.Key as Key
+import qualified Data.Aeson.KeyMap as KeyMap
+import qualified Data.Vector as Vector
+import OpenAI.V1.Tool
+    ( Tool
+    , ToolChoice
+    , toolChoiceAutoText
+    , toolChoiceNoneText
+    , toolChoiceRequiredText
+    , toolChoiceToResponsesValue
+    , toolToResponsesValue
+    , unflattenToolValue
+    )
 
+-- | Status constants for function call outputs
+statusIncomplete, statusCompleted :: Text
+statusIncomplete = "incomplete"
+statusCompleted = "completed"
+
 -- | Input for the Responses API: a list of input items
 newtype Input = Input (Vector InputItem)
     deriving stock (Generic, Show)
@@ -87,11 +107,27 @@
 
 -- | An input item
 data InputItem
-    = Item_InputMessage
+    = Item_Input_Message
         { role :: InputRole
         , content :: Vector InputContent
         , status :: Maybe Text
         }
+    | Item_Input_Function_Call
+        { id :: Maybe Text
+        , call_id :: Text
+        , name :: Text
+        , arguments :: Text
+        , status :: Maybe Text
+        }
+    | Item_Input_Function_Call_Output
+        { id :: Maybe Text
+        , call_id :: Text
+        , output :: Text
+        , status :: Maybe Text
+        }
+    | Item_Input_Item_Reference
+        { id :: Maybe Text
+        }
     deriving stock (Generic, Show)
 
 inputItemOptions :: Options
@@ -99,7 +135,7 @@
     aesonOptions
         { sumEncoding = TaggedObject{ tagFieldName = "type", contentsFieldName = "" }
         , tagSingleConstructors = True
-        , constructorTagModifier = stripPrefix "Item_Input"
+        , constructorTagModifier = stripPrefix "Item_Input_"
         }
 
 instance FromJSON InputItem where
@@ -108,6 +144,50 @@
 instance ToJSON InputItem where
     toJSON = genericToJSON inputItemOptions
 
+keyTools :: Key.Key
+keyTools = Key.fromText "tools"
+
+keyToolChoice :: Key.Key
+keyToolChoice = Key.fromText "tool_choice"
+
+flattenResponseToolFields
+    :: Maybe (Vector Tool)
+    -> Maybe ToolChoice
+    -> KeyMap.KeyMap Value
+    -> KeyMap.KeyMap Value
+flattenResponseToolFields mTools mChoice o =
+    let oWithTools = case mTools of
+            Nothing -> o
+            Just ts -> KeyMap.insert keyTools (Aeson.Array (Vector.map toolToResponsesValue ts)) o
+        oWithChoice = case mChoice of
+            Nothing -> oWithTools
+            Just choice -> KeyMap.insert keyToolChoice (toolChoiceToResponsesValue choice) oWithTools
+    in oWithChoice
+
+unflattenResponseToolFields :: KeyMap.KeyMap Value -> KeyMap.KeyMap Value
+unflattenResponseToolFields = adjustChoice . adjustTools
+  where
+    adjustTools = adjustKey keyTools (mapArrayValues unflattenToolValue)
+    adjustChoice = adjustKey keyToolChoice unflattenChoice
+
+    unflattenChoice (String s)
+        | s `elem` ([toolChoiceNoneText, toolChoiceAutoText, toolChoiceRequiredText] :: [Text]) = String s
+    unflattenChoice other = unflattenToolValue other
+
+mapArrayValues :: (Value -> Value) -> Value -> Value
+mapArrayValues f (Aeson.Array arr) = Aeson.Array (Vector.map f arr)
+mapArrayValues _ other = other
+
+adjustKey
+    :: Key.Key
+    -> (Value -> Value)
+    -> KeyMap.KeyMap Value
+    -> KeyMap.KeyMap Value
+adjustKey key f obj =
+    case KeyMap.lookup key obj of
+        Nothing -> obj
+        Just v -> KeyMap.insert key (f v) obj
+
 -- | Output content from the model
 data OutputContent
     = Output_Text
@@ -674,8 +754,20 @@
     , user :: Maybe Text
     , metadata :: Maybe (Map Text Text)
     } deriving stock (Generic, Show)
-      deriving anyclass (FromJSON, ToJSON)
 
+instance FromJSON ResponseObject where
+    parseJSON (Aeson.Object o) =
+        genericParseJSON aesonOptions (Aeson.Object (unflattenResponseToolFields o))
+    parseJSON other = genericParseJSON aesonOptions other
+
+instance ToJSON ResponseObject where
+    toJSON response@ResponseObject{ tools = mTools, tool_choice = mChoice } =
+        case genericToJSON aesonOptions response of
+            Aeson.Object o ->
+                Aeson.Object
+                    (flattenResponseToolFields mTools mChoice o)
+            other -> other
+
 -- | Request body for /v1/responses
 data CreateResponse = CreateResponse
     { model :: Model
@@ -694,10 +786,17 @@
     } deriving stock (Generic, Show)
 
 instance FromJSON CreateResponse where
-    parseJSON = genericParseJSON aesonOptions
+    parseJSON (Aeson.Object o) =
+        genericParseJSON aesonOptions (Aeson.Object (unflattenResponseToolFields o))
+    parseJSON other = genericParseJSON aesonOptions other
 
 instance ToJSON CreateResponse where
-    toJSON = genericToJSON aesonOptions
+    toJSON request@CreateResponse{ tools = mTools, tool_choice = mChoice } =
+        case genericToJSON aesonOptions request of
+            Aeson.Object o ->
+                Aeson.Object
+                    (flattenResponseToolFields mTools mChoice o)
+            other -> other
 
 -- | Default CreateResponse
 _CreateResponse :: CreateResponse
diff --git a/src/OpenAI/V1/Threads.hs b/src/OpenAI/V1/Threads.hs
--- a/src/OpenAI/V1/Threads.hs
+++ b/src/OpenAI/V1/Threads.hs
@@ -9,12 +9,10 @@
     , Message(..)
     , Content(..)
     , ThreadObject(..)
-
       -- * Other types
     , ImageURL(..)
     , ImageFile(..)
     , Attachment(..)
-
       -- * Servant
     , API
     ) where
diff --git a/src/OpenAI/V1/Threads/Messages.hs b/src/OpenAI/V1/Threads/Messages.hs
--- a/src/OpenAI/V1/Threads/Messages.hs
+++ b/src/OpenAI/V1/Threads/Messages.hs
@@ -1,21 +1,19 @@
 -- | @\/v1\/threads/:thread_id/messages@
 module OpenAI.V1.Threads.Messages
     ( -- * Main types
-        MessageID(..)
-      , Message(..)
-      , ModifyMessage(..)
-      , _ModifyMessage
-      , MessageObject(..)
-
+      MessageID(..)
+    , Message(..)
+    , ModifyMessage(..)
+    , _ModifyMessage
+    , MessageObject(..)
       -- * Other types
-      , Status(..)
-      , IncompleteDetails(..)
-      , File(..)
-      , Annotation(..)
-      , TextObject(..)
-
+    , Status(..)
+    , IncompleteDetails(..)
+    , File(..)
+    , Annotation(..)
+    , TextObject(..)
       -- * Servant
-      , API
+    , API
     ) where
 
 import OpenAI.Prelude
diff --git a/src/OpenAI/V1/Threads/Runs.hs b/src/OpenAI/V1/Threads/Runs.hs
--- a/src/OpenAI/V1/Threads/Runs.hs
+++ b/src/OpenAI/V1/Threads/Runs.hs
@@ -11,7 +11,6 @@
     , SubmitToolOutputsToRun(..)
     , _SubmitToolOutputsToRun
     , RunObject(..)
-
       -- * Other types
     , TruncationStrategy(..)
     , SubmitToolOutputs(..)
@@ -19,7 +18,6 @@
     , IncompleteDetails(..)
     , ToolOutput(..)
     , Status(..)
-
       -- * Servant
     , API
     ) where
@@ -33,11 +31,10 @@
 import OpenAI.V1.Models (Model)
 import OpenAI.V1.Order
 import OpenAI.V1.ResponseFormat
-import OpenAI.V1.Threads (Thread)
+import OpenAI.V1.Threads (Thread, ThreadID)
 import OpenAI.V1.Tool
 import OpenAI.V1.ToolCall
 import OpenAI.V1.ToolResources
-import OpenAI.V1.Threads (ThreadID)
 import OpenAI.V1.Usage
 
 -- | Run ID
diff --git a/src/OpenAI/V1/Threads/Runs/Steps.hs b/src/OpenAI/V1/Threads/Runs/Steps.hs
--- a/src/OpenAI/V1/Threads/Runs/Steps.hs
+++ b/src/OpenAI/V1/Threads/Runs/Steps.hs
@@ -3,7 +3,6 @@
     ( -- * Main types
       StepID(..)
     , RunStepObject(..)
-
       -- * Other types
     , Status(..)
     , Image(..)
@@ -16,7 +15,6 @@
     , Function(..)
     , ToolCall(..)
     , StepDetails(..)
-
       -- * Servant
     , API
     ) where
@@ -26,9 +24,9 @@
 import OpenAI.V1.Error
 import OpenAI.V1.Files (FileID)
 import OpenAI.V1.ListOf
-import OpenAI.V1.Threads.Messages (MessageID)
 import OpenAI.V1.Order
 import OpenAI.V1.Threads (ThreadID)
+import OpenAI.V1.Threads.Messages (MessageID)
 import OpenAI.V1.Threads.Runs (RunID)
 import OpenAI.V1.Usage
 
diff --git a/src/OpenAI/V1/Tool.hs b/src/OpenAI/V1/Tool.hs
--- a/src/OpenAI/V1/Tool.hs
+++ b/src/OpenAI/V1/Tool.hs
@@ -7,17 +7,39 @@
     , Function(..)
     , ToolChoice(..)
     , CodeInterpreterContainer(..)
-    -- * Helpers
+      -- * Constants
+    , toolChoiceNoneText
+    , toolChoiceAutoText
+    , toolChoiceRequiredText
+      -- * Helpers
     , codeInterpreter
     , codeInterpreterAuto
     , codeInterpreterWithFiles
+    , toolToResponsesValue
+    , parseResponsesToolValue
+    , toolChoiceToResponsesValue
+    , parseResponsesToolChoiceValue
+    , flattenToolValue
+    , unflattenToolValue
     ) where
 
-import OpenAI.Prelude
 import Data.Aeson ((.:), (.:?), (.=))
+import Data.Aeson.Types (Parser)
+import OpenAI.Prelude
 import qualified Data.Aeson as Aeson
+import qualified Data.Aeson.Key as Key
+import qualified Data.Aeson.KeyMap as KeyMap
+import qualified Data.HashSet as HashSet
+import Data.HashSet (HashSet)
+import Data.List (partition)
 import qualified Data.Vector as V
 
+-- | Tool choice string constants
+toolChoiceNoneText, toolChoiceAutoText, toolChoiceRequiredText :: Text
+toolChoiceNoneText = "none"
+toolChoiceAutoText = "auto"
+toolChoiceRequiredText = "required"
+
 -- | The ranking options for the file search
 data RankingOptions = RankingOptions
     { ranker :: Maybe Text
@@ -65,6 +87,60 @@
 instance ToJSON Tool where
     toJSON = genericToJSON toolOptions
 
+toolToResponsesValue :: Tool -> Value
+toolToResponsesValue = flattenToolValue . toJSON
+
+parseResponsesToolValue :: Value -> Parser Tool
+parseResponsesToolValue = parseJSON . unflattenToolValue
+
+toolChoiceToResponsesValue :: ToolChoice -> Value
+toolChoiceToResponsesValue ToolChoiceNone = String toolChoiceNoneText
+toolChoiceToResponsesValue ToolChoiceAuto = String toolChoiceAutoText
+toolChoiceToResponsesValue ToolChoiceRequired = String toolChoiceRequiredText
+toolChoiceToResponsesValue (ToolChoiceTool tool) = toolToResponsesValue tool
+
+parseResponsesToolChoiceValue :: Value -> Parser ToolChoice
+parseResponsesToolChoiceValue (String s)
+    | s == toolChoiceNoneText = pure ToolChoiceNone
+    | s == toolChoiceAutoText = pure ToolChoiceAuto
+    | s == toolChoiceRequiredText = pure ToolChoiceRequired
+parseResponsesToolChoiceValue other = ToolChoiceTool <$> parseResponsesToolValue other
+
+keyFunction, keyType :: Key.Key
+keyFunction = Key.fromText "function"
+keyType = Key.fromText "type"
+
+functionFieldKeys :: HashSet Key.Key
+functionFieldKeys = HashSet.fromList $ Key.fromText <$> ["description", "name", "parameters", "strict"]
+
+isFunctionField :: Key.Key -> Bool
+isFunctionField = (`HashSet.member` functionFieldKeys)
+
+partitionFunctionFields
+    :: KeyMap.KeyMap Value
+    -> (KeyMap.KeyMap Value, KeyMap.KeyMap Value)
+partitionFunctionFields obj =
+    let (fnPairs, restPairs) = partition (isFunctionField . fst) (KeyMap.toList obj)
+    in (KeyMap.fromList fnPairs, KeyMap.fromList restPairs)
+
+flattenToolValue :: Value -> Value
+flattenToolValue value@(Aeson.Object o) =
+    maybe value flattenFunction (KeyMap.lookup keyFunction o)
+  where
+    flattenFunction (Aeson.Object fnFields) =
+        Aeson.Object (KeyMap.delete keyFunction o <> fnFields)
+    flattenFunction _ = value
+flattenToolValue value = value
+
+unflattenToolValue :: Value -> Value
+unflattenToolValue value@(Aeson.Object o)
+    | KeyMap.lookup keyType o == Just (String "function")
+    , not (KeyMap.member keyFunction o) =
+        let (fnFields, rest) = partitionFunctionFields o
+        in Aeson.Object (KeyMap.insert keyFunction (Aeson.Object fnFields) rest)
+    | otherwise = value
+unflattenToolValue value = value
+
 -- | Controls which (if any) tool is called by the model
 data ToolChoice
     = ToolChoiceNone
@@ -94,7 +170,7 @@
 instance ToJSON CodeInterpreterContainer where
     toJSON (CodeInterpreterContainer_ID container_id) = toJSON container_id
     toJSON (CodeInterpreterContainer_Auto file_ids) =
-        Aeson.object $ "type" .= String "auto" : 
+        Aeson.object $ "type" .= String "auto" :
                       maybe [] (\ids -> ["file_ids" .= ids]) file_ids
 
 instance FromJSON CodeInterpreterContainer where
diff --git a/src/OpenAI/V1/ToolResources.hs b/src/OpenAI/V1/ToolResources.hs
--- a/src/OpenAI/V1/ToolResources.hs
+++ b/src/OpenAI/V1/ToolResources.hs
@@ -2,7 +2,6 @@
 module OpenAI.V1.ToolResources
     ( -- * Main types
       ToolResources(..)
-
       -- * Other types
     , CodeInterpreterResources(..)
     , Static(..)
diff --git a/src/OpenAI/V1/Usage.hs b/src/OpenAI/V1/Usage.hs
--- a/src/OpenAI/V1/Usage.hs
+++ b/src/OpenAI/V1/Usage.hs
@@ -2,7 +2,6 @@
 module OpenAI.V1.Usage
     ( -- * Main types
       Usage(..)
-
       -- * Other types
     , CompletionTokensDetails(..)
     , PromptTokensDetails(..)
diff --git a/src/OpenAI/V1/VectorStores.hs b/src/OpenAI/V1/VectorStores.hs
--- a/src/OpenAI/V1/VectorStores.hs
+++ b/src/OpenAI/V1/VectorStores.hs
@@ -7,11 +7,9 @@
     , ModifyVectorStore(..)
     , _ModifyVectorStore
     , VectorStoreObject(..)
-
       -- * Other types
     , ExpiresAfter(..)
     , Status(..)
-
       -- * Servant
     , API
     ) where
@@ -21,8 +19,8 @@
 import OpenAI.V1.ChunkingStrategy
 import OpenAI.V1.DeletionStatus
 import OpenAI.V1.Files (FileID)
-import OpenAI.V1.Order
 import OpenAI.V1.ListOf
+import OpenAI.V1.Order
 import OpenAI.V1.VectorStores.FileCounts
 
 -- | Vector store ID
diff --git a/src/OpenAI/V1/VectorStores/FileBatches.hs b/src/OpenAI/V1/VectorStores/FileBatches.hs
--- a/src/OpenAI/V1/VectorStores/FileBatches.hs
+++ b/src/OpenAI/V1/VectorStores/FileBatches.hs
@@ -5,7 +5,6 @@
     , CreateVectorStoreFileBatch(..)
     , _CreateVectorStoreFileBatch
     , VectorStoreFilesBatchObject(..)
-
       -- * Servant
     , API
     ) where
diff --git a/src/OpenAI/V1/VectorStores/Files.hs b/src/OpenAI/V1/VectorStores/Files.hs
--- a/src/OpenAI/V1/VectorStores/Files.hs
+++ b/src/OpenAI/V1/VectorStores/Files.hs
@@ -5,7 +5,6 @@
     , CreateVectorStoreFile(..)
     , _CreateVectorStoreFile
     , VectorStoreFileObject(..)
-
       -- * Servant
     , API
     ) where
@@ -13,8 +12,8 @@
 import OpenAI.Prelude
 import OpenAI.V1.ChunkingStrategy
 import OpenAI.V1.DeletionStatus
-import OpenAI.V1.Files (FileID)
 import OpenAI.V1.Error
+import OpenAI.V1.Files (FileID)
 import OpenAI.V1.ListOf
 import OpenAI.V1.Order
 import OpenAI.V1.VectorStores (VectorStoreID)
diff --git a/tasty/Main.hs b/tasty/Main.hs
--- a/tasty/Main.hs
+++ b/tasty/Main.hs
@@ -1,104 +1,69 @@
-{-# LANGUAGE BlockArguments #-}
-{-# LANGUAGE DuplicateRecordFields #-}
-{-# LANGUAGE NamedFieldPuns #-}
-{-# LANGUAGE OverloadedLists #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE BlockArguments, DuplicateRecordFields, NamedFieldPuns #-}
+{-# LANGUAGE OverloadedLists, OverloadedStrings, RecordWildCards   #-}
+{-# LANGUAGE ScopedTypeVariables                                   #-}
 {-# OPTIONS_GHC -Wno-orphans #-}
 
 module Main where
 
-import qualified Control.Concurrent as Concurrent
 import Control.Exception (SomeException, catch)
+import OpenAI.V1 (Methods(..))
+import OpenAI.V1.Audio.Speech (CreateSpeech(..), Voice(..), _CreateSpeech)
+import OpenAI.V1.Audio.Transcriptions (CreateTranscription(..))
+import OpenAI.V1.Audio.Translations (CreateTranslation(..))
+import OpenAI.V1.AutoOr (AutoOr(..))
+import OpenAI.V1.Batches (BatchObject(..), CreateBatch(..))
+import OpenAI.V1.Chat.Completions (CreateChatCompletion(..), Modality(..))
+import OpenAI.V1.Embeddings (CreateEmbeddings(..), EncodingFormat(..))
+import OpenAI.V1.Files (FileObject(..), Order(..), UploadFile(..))
+import OpenAI.V1.Images.Edits (CreateImageEdit(..))
+import OpenAI.V1.Images.Generations (CreateImage(..), Quality(..), Style(..))
+import OpenAI.V1.Images.Variations (CreateImageVariation(..))
+import OpenAI.V1.Message (Message(..))
+import OpenAI.V1.Moderations (CreateModeration(..))
+import OpenAI.V1.Threads.Messages (MessageObject(..), ModifyMessage(..))
+import OpenAI.V1.Tool (Tool(..), ToolChoice(..))
+import OpenAI.V1.ToolCall (ToolCall(..))
+import Prelude hiding (id)
+
+import OpenAI.V1.Assistants
+    (AssistantObject(..), CreateAssistant(..), ModifyAssistant(..))
+import OpenAI.V1.FineTuning.Jobs
+    (CreateFineTuningJob(..), Hyperparameters(..), JobObject(..))
+import OpenAI.V1.Threads
+    (ModifyThread(..), Thread(..), ThreadID(..), ThreadObject(..))
+import OpenAI.V1.Threads.Runs
+    (CreateRun(..), ModifyRun(..), RunID(..), RunObject(..), Status(..))
+import OpenAI.V1.Uploads
+    ( AddUploadPart(..)
+    , CompleteUpload(..)
+    , CreateUpload(..)
+    , PartObject(..)
+    , UploadObject(..)
+    )
+import OpenAI.V1.VectorStores
+    (CreateVectorStore(..), ModifyVectorStore(..), VectorStoreObject(..))
+import OpenAI.V1.VectorStores.FileBatches
+    (CreateVectorStoreFileBatch(..), VectorStoreFilesBatchObject(..))
+import OpenAI.V1.VectorStores.Files
+    (CreateVectorStoreFile(..), VectorStoreFileObject(..))
+
+import qualified Control.Concurrent as Concurrent
+import qualified Data.IORef as IORef
 import qualified Data.Text as Text
 import qualified Network.HTTP.Client as HTTP.Client
 import qualified Network.HTTP.Client.TLS as TLS
-import OpenAI.V1 (Methods (..))
 import qualified OpenAI.V1 as V1
-import qualified OpenAI.V1.Responses as Responses
-import OpenAI.V1.Assistants
-  ( AssistantObject (..),
-    CreateAssistant (..),
-    ModifyAssistant (..),
-  )
-import OpenAI.V1.Audio.Speech
-  ( CreateSpeech (..),
-    Voice (..),
-    _CreateSpeech,
-  )
-import OpenAI.V1.Audio.Transcriptions (CreateTranscription (..))
-import OpenAI.V1.Audio.Translations (CreateTranslation (..))
-import OpenAI.V1.AutoOr (AutoOr (..))
-import OpenAI.V1.Batches (BatchObject (..), CreateBatch (..))
-import OpenAI.V1.Chat.Completions
-  ( CreateChatCompletion (..),
-    Modality (..),
-  )
 import qualified OpenAI.V1.Chat.Completions as Completions
-import OpenAI.V1.Embeddings (CreateEmbeddings (..), EncodingFormat (..))
-import OpenAI.V1.Files (FileObject (..), Order (..), UploadFile (..))
 import qualified OpenAI.V1.Files as Files
-import OpenAI.V1.FineTuning.Jobs
-  ( CreateFineTuningJob (..),
-    Hyperparameters (..),
-    JobObject (..),
-  )
 import qualified OpenAI.V1.FineTuning.Jobs as Jobs
-import OpenAI.V1.Images.Edits (CreateImageEdit (..))
-import OpenAI.V1.Images.Generations
-  ( CreateImage (..),
-    Quality (..),
-    Style (..),
-  )
 import qualified OpenAI.V1.Images.ResponseFormat as ResponseFormat
-import OpenAI.V1.Images.Variations (CreateImageVariation (..))
-import OpenAI.V1.Message (Message (..))
-import OpenAI.V1.Moderations (CreateModeration (..))
-import OpenAI.V1.Threads
-  ( ModifyThread (..),
-    Thread (..),
-    ThreadID (..),
-    ThreadObject (..),
-  )
-import OpenAI.V1.Threads.Messages (MessageObject (..), ModifyMessage (..))
-import OpenAI.V1.Threads.Runs
-  ( CreateRun (..),
-    ModifyRun (..),
-    RunID (..),
-    RunObject (..),
-    Status (..),
-  )
-import OpenAI.V1.Tool (Tool (..), ToolChoice (..))
+import qualified OpenAI.V1.Responses as Responses
 import qualified OpenAI.V1.Tool as Tool
-import OpenAI.V1.ToolCall (ToolCall (..))
 import qualified OpenAI.V1.ToolCall as ToolCall
-import OpenAI.V1.Uploads
-  ( AddUploadPart (..),
-    CompleteUpload (..),
-    CreateUpload (..),
-    PartObject (..),
-    UploadObject (..),
-  )
-import OpenAI.V1.VectorStores
-  ( CreateVectorStore (..),
-    ModifyVectorStore (..),
-    VectorStoreObject (..),
-  )
-import OpenAI.V1.VectorStores.FileBatches
-  ( CreateVectorStoreFileBatch (..),
-    VectorStoreFilesBatchObject (..),
-  )
-import OpenAI.V1.VectorStores.Files
-  ( CreateVectorStoreFile (..),
-    VectorStoreFileObject (..),
-  )
 import qualified Servant.Client as Client
 import qualified System.Environment as Environment
 import qualified Test.Tasty as Tasty
 import qualified Test.Tasty.HUnit as HUnit
-import Prelude hiding (id)
-import qualified Data.IORef as IORef
 
 main :: IO ()
 main = do
@@ -892,7 +857,7 @@
               Responses._CreateResponse
                 { Responses.model = chatModel,
                   Responses.input = Just (Responses.Input
-                    [ Responses.Item_InputMessage
+                    [ Responses.Item_Input_Message
                         { Responses.role = Responses.User
                         , Responses.content = [ Responses.Input_Text{ Responses.text = "Say hello in one sentence." } ]
                         , Responses.status = Nothing
@@ -919,7 +884,7 @@
                 Responses._CreateResponse
                   { Responses.model = chatModel,
                     Responses.input = Just (Responses.Input
-                      [ Responses.Item_InputMessage
+                      [ Responses.Item_Input_Message
                           { Responses.role = Responses.User
                           , Responses.content = [ Responses.Input_Text{ Responses.text = "Stream a short haiku about the sea." } ]
                           , Responses.status = Nothing
@@ -963,7 +928,7 @@
                 Responses._CreateResponse
                   { Responses.model = chatModel,
                     Responses.input = Just (Responses.Input
-                      [ Responses.Item_InputMessage
+                      [ Responses.Item_Input_Message
                           { Responses.role = Responses.User
                           , Responses.content = [ Responses.Input_Text{ Responses.text = "Solve 3x + 11 = 14 and provide x as a number. Use the code interpreter." } ]
                           , Responses.status = Nothing
