15<!-- x-release-please-start-version -->15<!-- x-release-please-start-version -->
16 16
17```ruby17```ruby
18gem "openai", "~> 0.77.1"18gem "openai", "~> 0.78.0"
19```19```
20 20
21<!-- x-release-please-end -->21<!-- x-release-please-end -->
107 107
108Note that you can also pass a raw `IO` descriptor, but this disables retries, as the library can't be sure if the descriptor is a file or pipe (which cannot be rewound).108Note that you can also pass a raw `IO` descriptor, but this disables retries, as the library can't be sure if the descriptor is a file or pipe (which cannot be rewound).
109 109
110### Custom HTTP clients
111
112`OpenAI::Client` accepts an `http_client` for advanced transport requirements.
113Provide an object that implements `execute(request)` and returns an
114`OpenAI::HTTPClient::Response`; subclassing `OpenAI::HTTPClient` is the easiest
115way to make that contract explicit. The request exposes the SDK-prepared HTTP
116method, URL, headers, encoded body, and timeout. Response bodies are enumerable
117byte-string chunks (or a single buffered string), so large and streaming
118responses do not need to be buffered.
119
120The OpenAI client owns API authentication, redirects, and API-level retries.
121The custom HTTP client owns connection pooling and lifecycle, must enforce
122`request.timeout`, and should raise `OpenAI::Errors::APIConnectionError` or
123`OpenAI::Errors::APITimeoutError` for retryable transport failures. Other
124exceptions propagate without an SDK retry. The SDK does not close an injected
125HTTP client.
126
127The default `OpenAI::NetHTTPClient` implements this contract with pooled
128`Net::HTTP` connections. It accepts an optional block for native connection
129configuration, as shown below. Call `close` to retire its current pools; the
130HTTP client remains reusable and creates fresh connections on its next request.
131
132### Mutual TLS with a custom HTTP client
133
134To opt in and activate mTLS for an organization or project, follow the
135[OpenAI Mutual TLS Beta Program
136guide](https://help.openai.com/en/articles/10876024-openai-mutual-tls-beta-program).
137If you use an intermediate chain, confirm that certificate-chain support is
138enabled for your organization.
139
140For API-key requests that also require mutual TLS (mTLS), set the mTLS endpoint
141explicitly and pass a configured `OpenAI::NetHTTPClient` as `http_client`.
142`OpenAI::Client` accepts an HTTP client object so advanced transport behavior
143does not require a separate SDK option for every use case. The default
144`OpenAI::NetHTTPClient` accepts a block that configures each native
145`Net::HTTP` connection before it is pooled and started.
146
147Ruby's native TLS properties configure the client identity. The certificate
148file must contain the leaf certificate first, followed by any intermediate
149certificates needed when certificate-chain support is enabled for your
150organization:
151
152```ruby
153require "openai"
154
155mtls_endpoint = URI("https://mtls.api.openai.com/v1")
156certificates = OpenSSL::X509::Certificate.load(
157 File.binread(ENV.fetch("OPENAI_CLIENT_CERTIFICATE_CHAIN"))
158)
159raise "Expected a client certificate" if certificates.empty?
160
161leaf_certificate, *intermediates = certificates
162private_key = OpenSSL::PKey.read(
163 File.binread(ENV.fetch("OPENAI_CLIENT_KEY")),
164 ENV["OPENAI_CLIENT_KEY_PASSPHRASE"]
165)
166raise "Certificate and key do not match" unless leaf_certificate.check_private_key(private_key)
167
168now = Time.now
169raise "Certificate is not yet valid" if now < leaf_certificate.not_before
170raise "Certificate has expired" if now > leaf_certificate.not_after
171
172mtls_destination = [mtls_endpoint.host, mtls_endpoint.port]
173http_client = OpenAI::NetHTTPClient.new do |http|
174 unless http.use_ssl? && mtls_destination == [http.address, http.port]
175 raise "Refusing to present the client certificate to an unexpected origin"
176 end
177
178 http.cert = leaf_certificate
179 http.extra_chain_cert = intermediates
180 http.key = private_key
181end
182
183client = OpenAI::Client.new(
184 api_key: ENV.fetch("OPENAI_API_KEY"),
185 base_url: mtls_endpoint.to_s,
186 http_client: http_client
187)
188```
189
190The SDK cannot infer whether custom HTTP configuration uses mTLS, so it does not
191automatically change `base_url`. An explicit `base_url`, including an EU or
192custom endpoint, is always preserved. Scope client certificates to the expected
193origin, as above, so they cannot be presented elsewhere. Use the
194`OpenAI::NetHTTPClient` block for TLS and other connection-level configuration.
195Server trust remains separate from the client identity and can be customized
196with `Net::HTTP` properties such as `cert_store` or `ca_file`.
197
198Each `OpenAI::NetHTTPClient` owns its connection pool, so separate HTTP client
199instances do not share connections or credentials.
200
201After a process forks, create new OpenAI and HTTP clients in the child. Keep the
202certificate configuration captured by an HTTP client immutable. For certificate
203rotation, build and atomically swap in new `OpenAI::NetHTTPClient` and
204`OpenAI::Client` instances, then call `close` on the retired HTTP client after
205in-flight work finishes. See the complete [custom HTTP client mTLS
206example](examples/mtls_custom_http_client.rb).
207
110## Amazon Bedrock208## Amazon Bedrock
111 209
112Use the standard client with the Bedrock provider to call OpenAI models through Amazon Bedrock's OpenAI-compatible API. Add `aws-sdk-core` to your application for AWS credential discovery and SigV4 signing:210Use the standard client with the Bedrock provider to call OpenAI models through Amazon Bedrock's OpenAI-compatible API. Add `aws-sdk-core` to your application for AWS credential discovery and SigV4 signing:
568 666
569### Concurrency & connection pooling667### Concurrency & connection pooling
570 668
571The `OpenAI::Client` instances are threadsafe, but are only fork-safe when there are no in-flight HTTP requests.669`OpenAI::Client` instances using the default `OpenAI::NetHTTPClient` are threadsafe, but are only fork-safe when there are no in-flight HTTP requests. Injected HTTP clients are responsible for documenting and enforcing their own concurrency guarantees.
572 670
573Each instance of `OpenAI::Client` has its own HTTP connection pool with a default size of 99. As such, we recommend instantiating the client once per application in most settings.671By default, each `OpenAI::Client` creates its own HTTP connection pool with a size of at least 99 connections. As such, we recommend instantiating the client once per application in most settings. An injected HTTP client may instead share its pool across multiple SDK clients; the caller owns that HTTP client's lifecycle.
574 672
575When all available connections from the pool are checked out, requests wait for a new connection to become available, with queue time counting towards the request timeout.673When all available connections from the pool are checked out, requests wait for a new connection to become available, with queue time counting towards the request timeout.
576 674