deepseek-go: a Go SDK for DeepSeek V4, with Anthropic and OpenAI-compatible escape hatches
Go SDK for DeepSeek V4 API — chat, reasoning, Anthropic-compatible endpoint, tool calling, FIM, and streaming. Also supports OpenRouter, Azure, Ollama, and OpenAI-compatible providers.
At a glance
- What is it?
- cohesion-org/deepseek-go wraps the DeepSeek V4 chat, reasoning, FIM and tool-calling APIs behind typed Go structs, and can also point at OpenRouter, Azure, Ollama or any OpenAI-shaped endpoint. It suits Go services that want a thin client rather than a framework.
- Who is it for?
- Adopt deepseek-go if you are writing Go and want typed access to DeepSeek V4 chat, thinking mode, FIM or tool calling without pulling in a large framework, and if you are prepared to check the deprecation warnings on the older model constants. Do not adopt it if you need a provider abstraction that hides DeepSeek specifics, or if you cannot move to Go 1.26.0.
- Can I use it commercially?
- Yes. MIT 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 108 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 deepseek-go is for, and who should reach for it
Calling an LLM API from Go usually means either hand-rolling net/http calls and JSON structs, or adopting a framework that brings its own abstractions for agents, memory and routing. deepseek-go sits in between. It is a Go client for the DeepSeek platform, and the README describes it as providing "a clean and type-safe interface" to chat completions with streaming, token usage tracking and related features.
The audience is a Go service that already knows which model it wants. The repository ships model constants such as deepseek.DeepSeekV4Flash and deepseek.DeepSeekV4Pro, so the model name is a compile-time value rather than a string scattered through config. The README lists deepseek-v4-flash as the flagship with 1M context and 384K max output, and deepseek-v4-pro as the premium reasoning model for complex reasoning and agent tasks.
The awkward part is naming. The module is deepseek-go, and the search phrases around it mix the SDK with the consumer app and even with speculation about the company going public. If you arrived here looking for a DeepSeek desktop client, this is not it. It is a library you import.
How the client, requests and streaming are wired
The layout is conventional Go: client.go, chat.go, chat_stream.go, fim.go, anthropic.go, ollama.go, requestHandler.go and responseHandler.go sit at the repository root, with constants/ and internal/ alongside. That split tells you the design intent. There is a client that holds credentials and a base URL, request payload types that mirror the API, and handlers that serialise and deserialise.
The base URL is a first-class knob. NewClient takes an API key and a base URL, and the README's external provider example passes either https://models.inference.ai.azure.com/ or https://openrouter.ai/api/v1/. The README adds that for providers it does not support directly, you can extend the baseURL and pass the model name as a string, and it "will work as long as the provider follows the same API structure as Azure or OpenRouter." That is the whole compatibility story in one sentence, and it is worth taking literally: the library assumes an OpenAI-shaped wire format and does not translate between dialects.
Streaming lives in chat_stream.go, and there is a separate chat_thinking_mode_test.go plus a thinking_compat_test.go, which suggests reasoning output is handled as its own concern rather than folded into the normal message path. The Anthropic-compatible endpoint is separate again, reached through NewAnthropicClient, with content blocks, tool use and streaming. Two clients, two request shapes, one module.
Installing deepseek-go and sending a first message
The README gives a single install command. It also states that deepseek-go currently uses go 1.26.0, and go.mod confirms go 1.26.0, so a project pinned to an older toolchain will need to move before the module resolves.
go get github.com/cohesion-org/deepseek-goThe client reads the key from the environment when you pass an empty string. The README's comment on NewClient says an empty API key "triggers env lookup for DEEPSEEK_API_KEY", and env.example in the repository root is there to show the variable name.
client := deepseek.NewClient("")The minimal program below is the README's chat example. It builds a ChatCompletionRequest with a system message and a user message, calls CreateChatCompletion with a context, and prints response.Choices[0].Message.Content. If the key is missing or wrong, the error surfaces from CreateChatCompletion rather than from NewClient.
request := &deepseek.ChatCompletionRequest{
Model: deepseek.DeepSeekV4Flash,
Messages: []deepseek.ChatCompletionMessage{
{Role: deepseek.ChatMessageRoleSystem, Content: "Answer every question using slang."},
{Role: deepseek.ChatMessageRoleUser, Content: "Which is the tallest mountain in the world?"},
},
}
response, err := client.CreateChatCompletion(context.Background(), request)The repository also carries examples/01_chat/ and examples/02_chat_stream/ if you want a runnable starting point rather than a snippet. For a local model instead of the hosted API, examples/ollama.md and ollama.go cover that path.
Deprecated model constants and the sunset date
The clearest trap in the README is the model table. deepseek-chat and deepseek-reasoner are marked deprecated with a sunset of 2026/07/24. deepseek-chat maps to deepseek-v4-flash in non-thinking mode, and deepseek-reasoner maps to deepseek-v4-flash in thinking mode. The README says using either constant "emits a deprecation warning to stderr".
That warning is easy to miss in a container where stderr is not watched. Code that still references deepseek.DeepSeekReasoner will keep compiling and keep working until the sunset date, then stop. The migration is not a like-for-like constant swap either, because thinking mode is now a property of the request rather than a separate model. The README documents reasoning_effort with values "high" and "max" under thinking mode, and examples/14_reasoning_effort/ exists for it. Anyone moving off deepseek-reasoner has to decide what reasoning_effort value replaces the old implicit behaviour, and the README does not state a mapping. That is a real gap, not a nitpick.
The same caution applies to the deprecated constants in tests and dashboards. A grep for DeepSeekReasoner across your codebase is the cheapest way to find them.
Tool calling, FIM and JSON output: what is actually stable
Three features deserve separate treatment because their maturity differs.
Tool calling supports standard and strict mode, and the README labels strict mode as beta "with automatic /beta routing". Automatic routing means the library rewrites the endpoint for you, which is convenient but also means a beta path is baked into a call you might think is stable. examples/16_strict_tools/ is the reference. If you depend on strict tool schemas in production, the beta label is a fact you have to accept.
FIM completion is for fill-in-the-middle code generation and supports streaming, per the README. It is a different endpoint from chat, implemented in fim.go, with examples/03_fim/ as the example. This is the feature that most distinguishes a DeepSeek client from a generic OpenAI-compatible client, since FIM is not part of the standard chat surface.
JSON output is handled through ResponseFormat, with schema extraction. examples/04_json_mode/ shows the shape. The distinction between JSON output and tool calling matters: if you want structured data and do not need the model to choose a function, JSON mode is the smaller hammer. The README does not describe how schema extraction behaves when the model returns malformed JSON, so treat validation as your responsibility.
Where deepseek-go is the wrong choice
The library is a thin client, and that is a boundary as much as a benefit. It does not model conversations, retries, rate limiting or cost accounting beyond a balance check and client-side token estimation. Balance and models are supported, per the README, and tokens.go handles token counting for Chinese and English text, but token estimation on the client is an estimate. If you need exact billing figures, you get them from the provider, not from this library.
The base URL escape hatch is the other sharp edge. The README's claim that any OpenAI-compatible provider works assumes the provider matches the Azure or OpenRouter structure. Features that are DeepSeek-specific, such as FIM, thinking mode with reasoning_effort, or the Anthropic-compatible endpoint, will not survive that assumption. Pointing the client at a generic provider and then calling FIM is a category error.
Finally, the module requires Go 1.26.0. A team on an older toolchain cannot adopt it without an upgrade, and go.mod also carries retract directives for v1.1.0 and v1.0.1, described in the file as "a premature release". Version selection therefore matters: pin a release from the releases page rather than letting a loose constraint resolve.
How it compares with the official OpenAI Go client
The obvious alternative for a Go service is the official OpenAI Go client pointed at DeepSeek's OpenAI-compatible base URL. That approach works for chat and streaming, and it is maintained by the vendor whose wire format DeepSeek follows. What it does not give you is DeepSeek-specific surface: the V4 model constants, thinking mode with reasoning_effort, FIM completion, or the Anthropic-compatible endpoint via NewAnthropicClient. Those are the features deepseek-go exists to expose.
The trade is maintenance. An OpenAI-compatible client benefits from a large user base and vendor support, but leaves DeepSeek-only features unreachable. deepseek-go gives you those features and a smaller project to depend on. The last push to the repository was on 2026-05-30, and v1.4.0 on the same date is described in the release list as "DeepSeek V4 API alignment, Anthropic SDK support, and security fixes". That is roughly three and a half months before today, so the project is not archived but it is also not pushing daily.
A third option is to call the HTTP API directly. That is defensible for a single endpoint, and wrong once you need streaming plus tool calls plus FIM, which is where the typed structs start paying for themselves.
Licence, contribution and the cost of keeping up
The licence is MIT, and the README states it is "free for both personal and commercial use". MIT imposes no copyleft obligation on your own code, but it also means no warranty and no support commitment. This is not legal advice; read LICENSE in the repository if the distinction matters to your organisation.
The maintenance model is visible in the repository. CONTRIBUTING.md and .golangci.yml exist, and the Makefile defines the local workflow: make lint installs golangci-lint v1.64.8 into $(HOME)/.cache/deepseek-go/bin and runs it, make test runs go test -v ./..., make test-short and make test-race narrow or harden that, and make test-integration runs DEEPSEEK_LIVE_TESTS=1 go test -v -tags=integration ./... against the live API. The existence of a separate integration target means the default test run does not hit the network, which is the right default but also means API drift is caught by the integration job rather than by unit tests.
Upgrade cost is the model table. DeepSeek is retiring deepseek-chat and deepseek-reasoner, so a version bump is also a migration. Budget for that rather than treating go get -u as routine.
Editorial conclusion
Adopt deepseek-go if you are writing Go and want typed access to DeepSeek V4 chat, thinking mode, FIM or tool calling without pulling in a large framework, and if you are prepared to check the deprecation warnings on the older model constants. Do not adopt it if you need a provider abstraction that hides DeepSeek specifics, or if you cannot move to Go 1.26.0. Before you commit, run the example under examples/01_chat against your own key, confirm which model constant your code should use now that deepseek-chat and deepseek-reasoner are deprecated, and read the v1.4.0 release notes for the security fixes.
Frequently asked questions
What is deepseek-go used for?
It is a Go client for the DeepSeek platform, covering chat completions with streaming, token usage tracking, thinking mode, tool calling, FIM completion and JSON output. It can also be pointed at OpenRouter, Azure, Ollama or another OpenAI-compatible endpoint via the base URL.
Is deepseek-go good for coding tasks?
The README lists FIM completion, fill-in-the-middle for code generation with streaming, and JSON output with schema extraction. The repository also carries examples/03_fim/ and examples/04_json_mode/ for those paths. Whether the underlying model suits your task is a separate question the SDK does not answer.
How do I install deepseek-go and which Go version does it need?
Install it with go get github.com/cohesion-org/deepseek-go. The README states the module currently uses go 1.26.0, and go.mod confirms that, so an older toolchain will not resolve it.
Which model constants should I use in deepseek-go now?
Use deepseek.DeepSeekV4Flash or deepseek.DeepSeekV4Pro. The README marks deepseek-chat and deepseek-reasoner as deprecated with a sunset of 2026/07/24, and says using those constants emits a deprecation warning to stderr.
Does deepseek-go work with providers other than DeepSeek?
Yes. NewClient accepts a base URL, and the README shows Azure and OpenRouter. It states that other providers work as long as they follow the same API structure as Azure or OpenRouter, and that you pass the model name as a string in that case.
Community notes