DashScope (Qwen) plugin
The dashscope plugin gives Genkit access to Alibaba Cloud’s
Qwen models through DashScope’s
OpenAI-compatible mode. Models are named under the dashscope/ provider prefix.
Installation
Section titled “Installation”go get github.com/firebase/genkit/goConfiguration
Section titled “Configuration”Add &dashscope.DashScope{} to your plugin list. The plugin reads the API key from the
DASHSCOPE_API_KEY environment variable.
package main
import ( "context" "fmt" "log"
"github.com/firebase/genkit/go/ai" "github.com/firebase/genkit/go/genkit" "github.com/firebase/genkit/go/plugins/compat_oai/dashscope")
func main() { ctx := context.Background()
g := genkit.Init(ctx, genkit.WithPlugins(&dashscope.DashScope{}), genkit.WithDefaultModel("dashscope/qwen-plus"), )
text, err := genkit.GenerateText(ctx, g, ai.WithPrompt("Share a joke about bananas.")) if err != nil { log.Fatalf("could not generate: %v", err) }
fmt.Println(text)}You must provide an API key from
Alibaba Cloud Model Studio. Set
DASHSCOPE_API_KEY, or set the APIKey field. Extra OpenAI client request options ride in Opts,
applied after the plugin defaults so they win on overlap; option is
github.com/openai/openai-go/option.
g := genkit.Init(ctx, genkit.WithPlugins(&dashscope.DashScope{ APIKey: os.Getenv("MY_DASHSCOPE_KEY"), Opts: []option.RequestOption{ option.WithBaseURL("https://dashscope.aliyuncs.com/compatible-mode/v1"), },}))genkit.Init panics when neither the APIKey field nor DASHSCOPE_API_KEY is set. The endpoint
defaults to the shared international one, https://dashscope-intl.aliyuncs.com/compatible-mode/v1.
Mainland-China accounts and workspace-dedicated domains, which is Alibaba’s recommended production
setup, need a different base URL: set DASHSCOPE_BASE_URL or pass option.WithBaseURL in Opts.
As always, avoid embedding API keys directly in your code.
Models
Section titled “Models”The plugin registers these Qwen models when it initializes:
qwen-flash,qwen-plusqwen3.5-flash,qwen3.5-plusqwen3.6-flash,qwen3.6-plusqwen3.7-plus,qwen3.7-max,qwen3.7-max-2026-06-08qwen3-max,qwen3-vl-plus,qwen3-coder-plus
That list is a starting point rather than a limit. Any other Qwen model ID resolves on demand and takes the plugin’s text-only defaults, so a model Alibaba releases later works without a Genkit upgrade.
Dated snapshots are otherwise folded into their model’s versions rather than curated separately, so
pin one through the config’s Version field. qwen3.7-max-2026-06-08 is the exception: DashScope
documents image and video input for that snapshot, which the floating qwen3.7-max does not take, so
it is registered on its own for media requests to pass validation. It also stays in qwen3.7-max’s
versions, so both spellings work.
No Qwen model advertises tool choice, so tool selection is always automatic and a forced tool choice
is refused before the request goes out. Constrained generation is unclaimed too: DashScope’s
response_format takes json_object only, not json_schema, so an output schema reaches the model
as prompt instructions and comes back as the same typed result. qwen3.7-max and qwen3-coder-plus
go further and advertise text output only, since Alibaba’s capability tables say structured outputs
are unsupported for them.
dashscope.ModelRef pairs a model ID with a typed dashscope.ChatConfig, so the config is checked
where you write it and validated against the model’s schema before the request goes out.
resp, err := genkit.Generate(ctx, g, ai.WithModel(dashscope.ModelRef("qwen-plus", &dashscope.ChatConfig{ EnableThinking: openai.Ptr(true), ThinkingBudget: openai.Ptr(2048), })), ai.WithPrompt("Share a joke about bananas."),)if err != nil { log.Fatalf("could not generate: %v", err)}
fmt.Println(resp.Text())openai.Ptr is the OpenAI SDK’s own helper, imported from github.com/openai/openai-go. It is
convenient for the pointer fields; any *bool or *int works.
The ID passed to ModelRef works bare or provider-prefixed. You can also name a model as a string
with ai.WithModelName("dashscope/qwen-plus") or genkit.WithDefaultModel, and pass the config
separately with ai.WithConfig(&dashscope.ChatConfig{...}). The
DashScope sample
runs this as a streaming flow you can call from the Dev UI.
Generation config
Section titled “Generation config”dashscope.ChatConfig carries the generation fields the compatible mode accepts plus the
DashScope-specific controls:
| Field | Type | Notes |
|---|---|---|
Temperature | *float64 | Randomness of token selection, from 0 inclusive up to but not including 2. |
TopP | *float64 | Nucleus sampling threshold, above 0 and up to 1 inclusive. |
MaxOutputTokens | int | Sent as the API’s max_tokens. The default and the ceiling are both the model’s maximum output length. |
StopSequences | []string | Stop generation when produced by the model. |
PresencePenalty | *float64 | -2 to 2. The compatible mode documents no frequency penalty. |
Seed | *int | 0 to 2147483647. Makes generation reproducible across calls. |
EnableThinking | *bool | Turns the thinking mode of hybrid Qwen models on or off, sent as the API’s enable_thinking. |
ThinkingBudget | *int | Caps how many tokens the model may think with. Requires EnableThinking. |
EnableSearch | *bool | Lets the model consult web search, sent as the API’s enable_search. |
Pointer fields separate unset from a deliberate zero.
ChatConfig also embeds compat_oai.RequestConfig, which every plugin in the family shares: a
per-request APIKey, a Version pin, and an Extra map whose keys ride to the wire verbatim under
DashScope’s own names. See the
OpenAI-compatible plugin page.
Correcting what the plugin knows about a model
Section titled “Correcting what the plugin knows about a model”Every Qwen model works without an entry in Models. Supply one only to correct or extend the
capabilities the plugin resolves, most often for a model released after your Genkit version. Keys are
the model ID, bare or provider-prefixed, and fields left at their zero value keep what the plugin
resolved.
g := genkit.Init(ctx, genkit.WithPlugins(&dashscope.DashScope{ Models: map[string]ai.ModelOptions{ // A model the plugin does not curate resolves with the text-only // defaults, so an entry is how you tell Genkit it takes images. "qwen3-vl-flash": { Supports: &ai.ModelSupports{ Multiturn: true, Tools: true, SystemRole: true, Media: true, Output: []string{"text", "json"}, }, }, },}))Response behavior
Section titled “Response behavior”Reasoning text, streamed token usage, cached prompt tokens, and mid-generation provider failures are handled the same way for every plugin in this family. See the OpenAI-compatible plugin page.