sashabaranov/go-openai: a Go client for the Responses API and the rest of OpenAI
OpenAI, GPT 5.6, GPT-Image-2, Whisper API clients for Go
At a glance
- What is it?
- An unofficial Go client that now steers new work toward the Responses API while keeping Chat Completions, audio, images and fine-tuning surfaces intact. It is a thin, configurable wrapper, not a framework, and the README is honest about that.
- Who is it for?
- Adopt it if you are writing Go services that call OpenAI directly and want typed request structs, configurable base URLs and error inspection without pulling in a framework. Skip it if you need a maintained, first-party SDK or if you want the client to manage conversation state for you; Store and PreviousResponseID are flags you set, not behaviour the library guarantees.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What sashabaranov/go-openai actually solves
The package exists so that Go programs do not have to hand-roll HTTP calls, JSON envelopes and streaming parsers for every OpenAI endpoint. It is explicit in the README that it is unofficial, which matters: the API surface is defined by OpenAI, and this library tracks it rather than owning it. The scope is broad. The README lists embeddings, images, audio, moderation, files, fine-tuning, batches, vector stores and the legacy Assistants API, and the repository layout backs that up with files such as embeddings.go, image.go, audio.go, moderation.go, files.go, fine_tunes.go, batch.go and assistant.go. Each of those is a separate concern with its own request and response types.
The intended audience is a Go engineer who already knows what they want to send and wants a typed struct to send it in. The README's own framing is that for new text-generation, reasoning, tool-calling and multi-turn integrations you should start with the Responses API, while Chat Completions remains available for existing integrations. That is an unusual thing for a client library to say out loud, and it is the most useful sentence in the document.
Responses, PreviousResponseID and how state is carried
The Responses API is the primary path in this client. You construct an openai.CreateResponseRequest with a Model, optional Instructions and an Input, then call CreateResponse. The README notes that Input can be a string or a slice of typed input items, and that GetOutputText is a convenience over the richer response.Output field. If you need reasoning content, tool calls or multimodal output, the convenience method is the wrong accessor and the README says so directly.
Multi-turn behaviour is where the design gets interesting. The client does not keep a conversation object. Instead you pass PreviousResponseID set to the previous response's ID, and the README's example also sets Store to a pointer to true and resends Instructions on every call. That means conversation continuity is a server-side feature you opt into per request, not client-side bookkeeping. If you forget to resend Instructions, the earlier system framing is not reapplied by this library. The README states the rule plainly: resend Instructions on each call when they should continue to apply.
Streaming is a separate entry point, CreateResponseStream, returning a stream you defer-close and read with stream.Recv() in a loop until io.EOF. Events are typed, and the example filters on openai.ResponseStreamEventOutputTextDelta and prints event.Delta. Anything that is not a text delta is yours to handle or ignore.
Installing it and sending a first response
Installation is a single go get, and the module declares go 1.18 in go.mod, so the README's stated requirement of Go 1.18 or later is consistent with the module file. The key is read from the environment in every README example rather than passed as a literal.
go get github.com/sashabaranov/go-openaiexport OPENAI_API_KEY="<your key>"The first real call creates a client and a response. Note that the model is a named constant, GPT5Dot6Sol, not a raw string, and that the output text comes from a convenience method.
client := openai.NewClient(os.Getenv("OPENAI_API_KEY"))
response, err := client.CreateResponse(context.Background(), openai.CreateResponseRequest{
Model: openai.GPT5Dot6Sol,
Instructions: "You are a concise technical explainer.",
Input: "Why is the sky blue?",
})
if err != nil {
log.Fatal(err)
}
fmt.Println(response.GetOutputText())If that compiles and prints a paragraph, your key, network path and model access are all working. The repository also ships runnable examples, and the README gives the invocation for one of them, which is a faster smoke test than writing main yourself.
go run ./examples/responsesModel constants, tiers and the string escape hatch
The GPT-5.6 family is exposed as four constants. GPT5Dot6Sol maps to gpt-5.6-sol and the README assigns it complex reasoning and coding. GPT5Dot6Terra maps to gpt-5.6-terra for a balance of intelligence and cost. GPT5Dot6Luna maps to gpt-5.6-luna for cost-sensitive, high-volume work. GPT5Dot6 is the family alias, which the README says currently routes to Sol.
The README's advice is to pick the tier that matches the workload rather than defaulting to the flagship for every request, which is a cost argument more than a capability one. The escape hatch is that model IDs are accepted as strings, so a model can be used before a named constant is added to the package. That cuts both ways. It means you are never blocked waiting for a release, and it also means a typo in a model string is a runtime error rather than a compile error. There is a models.go in the repository, and the README points at the OpenAI model catalog for capabilities and availability, which is the right place for that question rather than the client's source.
Base URLs, Azure and where this client stops helping
Configuration goes through DefaultConfig, which takes the API key and returns a struct you mutate before constructing the client. The README shows overriding BaseURL to point at a compatible endpoint, and mentions that the same config carries the HTTP client, organization and headers. That is the mechanism that makes this library usable against anything claiming OpenAI compatibility, and it is also the source of the most common failure mode: a compatible endpoint may implement Chat Completions and not the Responses request shape, in which case the primary documented path here will not work against it.
For Azure, the README says to start with DefaultAzureConfig and configure the deployment mapping or API version required by your Azure resource. It does not spell out the mapping API, so you are reading source or GoDoc for that. This is a genuine documentation gap, and it is the kind of gap that costs an afternoon.
Error handling is better served. Failures can be inspected with errors.As against *openai.APIError, exposing HTTPStatusCode, Code and Message. That is enough to distinguish a rate limit from a bad request from an auth problem without string matching, which is more than many thin clients offer.
Chat Completions is still here, and why that is a trade-off
Chat Completions remains supported, and the README's example uses GPT4oMini with a ChatCompletionRequest and reads response.Choices[0].Message.Content. The README's guidance is explicit: for a new integration, prefer Responses unless you specifically need the Chat Completions request or response shape. That is a real constraint rather than a preference. If your downstream code, your prompt templates or your logging pipeline are built around a messages array and a choices array, switching to Responses changes the shape of everything you persist and parse.
The cost of staying on Chat Completions is that you are on the path the README describes as being for existing integrations. The cost of moving is a rewrite of your request construction and your response parsing, plus a decision about whether to use Store and PreviousResponseID for state. Neither is free, and the library does not smooth the transition with an adapter. This is a client, not a migration tool.
Maintenance, versioning and what the licence permits
The repository is not archived, and the last push was on 2026-09-11, the same day as the v1.42.1 release. The release history is worth reading as a cadence signal rather than a quality signal: v1.42.0 landed on 2026-08-02, and the release before that, v1.41.2, was on 2025-09-12. A roughly year-long gap followed by two releases in about six weeks is not a steady drumbeat, and it suggests the project moves in bursts, often tracking upstream API changes.
That matters for upgrade cost. Because model IDs can be passed as raw strings, you can adopt a new model without waiting for a tagged release, but you also cannot rely on a constant existing the moment a model ships. Pin a version in go.mod and read the release notes before bumping. The module targets go 1.18, which is old enough that most modern toolchains will build it without complaint.
The licence is Apache-2.0, which permits commercial and closed-source use and includes an explicit patent grant. It also requires that you preserve the licence and notice files and state significant changes if you redistribute a modified copy. That is a summary of the terms, not legal advice; read LICENSE in the repository before shipping a fork.
Editorial conclusion
Adopt it if you are writing Go services that call OpenAI directly and want typed request structs, configurable base URLs and error inspection without pulling in a framework. Skip it if you need a maintained, first-party SDK or if you want the client to manage conversation state for you; Store and PreviousResponseID are flags you set, not behaviour the library guarantees. Before committing, verify that the model constants you plan to use exist in the version you pin, and check whether your endpoint is compatible with the Responses request shape rather than only Chat Completions.
Frequently asked questions
Is sashabaranov/go-openai an official OpenAI SDK?
No. The README describes it as an unofficial Go client for the OpenAI API, and the repository is maintained under the sashabaranov GitHub account rather than by OpenAI.
What Go version does sashabaranov/go-openai require?
The README states Go 1.18 or later, and the module file declares go 1.18, so the two agree.
How do I install sashabaranov/go-openai?
Run go get github.com/sashabaranov/go-openai. The README then has you export OPENAI_API_KEY and construct a client with openai.NewClient.
Does sashabaranov/go-openai support streaming responses?
Yes. The README shows CreateResponseStream returning a stream that you defer-close and read with stream.Recv() until io.EOF, filtering on openai.ResponseStreamEventOutputTextDelta for text deltas.
Can I use sashabaranov/go-openai with a non-OpenAI endpoint?
The README shows setting config.BaseURL to a compatible endpoint via DefaultConfig and NewClientWithConfig. Whether it works depends on that endpoint implementing the request shape you call, since the README does not guarantee compatibility beyond the base URL override.
How does sashabaranov/go-openai handle multi-turn conversations?
By passing PreviousResponseID set to the earlier response's ID in a new CreateResponseRequest, and setting Store to true. The README notes you should resend Instructions on each call when they should continue to apply.
Community notes