Go (go-openai)
github.com/sashabaranov/go-openai, the community Go client for the OpenAI API.
Connect
PLUGBOARD_BASE_URL is http://127.0.0.1:4010/v1 and PLUGBOARD_KEY is your plugboard key.
go
cfg := openai.DefaultConfig(os.Getenv("PLUGBOARD_KEY"))
cfg.BaseURL = os.Getenv("PLUGBOARD_BASE_URL") // already ends in /v1
client := openai.NewClientWithConfig(cfg)BaseURL replaces the default whole, so include /v1. Use an alias such as "fast", or any allowed provider/model[#variant], as the Model string.
Chat
go
response, err := client.CreateChatCompletion(ctx, openai.ChatCompletionRequest{
Model: model,
Messages: []openai.ChatCompletionMessage{{Role: openai.ChatMessageRoleUser, Content: prompt}},
})Tool calls
Plugboard returns the call. Your code runs the tool and sends the result back.
go
tools := []openai.Tool{{
Type: openai.ToolTypeFunction,
Function: &openai.FunctionDefinition{
Name: "get_weather",
Description: "Current weather for a city.",
Parameters: json.RawMessage(`{"type":"object","properties":{"city":{"type":"string"}},"required":["city"]}`),
},
}}go
messages := []openai.ChatCompletionMessage{{Role: openai.ChatMessageRoleUser, Content: "What is the weather in Paris? Use the tool."}}
first, err := client.CreateChatCompletion(ctx, openai.ChatCompletionRequest{Model: model, Messages: messages, Tools: tools})
if err != nil {
return nil, err
}
reply := first.Choices[0].Message
messages = append(messages, reply)
var call openai.ToolCall
var args struct {
City string `json:"city"`
}
if len(reply.ToolCalls) > 0 {
call = reply.ToolCalls[0]
if err := json.Unmarshal([]byte(call.Function.Arguments), &args); err != nil {
return nil, err
}
messages = append(messages, openai.ChatCompletionMessage{
Role: openai.ChatMessageRoleTool,
ToolCallID: call.ID,
Content: `{"temp_c": 18, "sky": "cloudy", "city": "` + args.City + `"}`,
})
}
final, err := client.CreateChatCompletion(ctx, openai.ChatCompletionRequest{Model: model, Messages: messages, Tools: tools})
if err != nil {
return nil, err
}Streaming
go
stream, err := client.CreateChatCompletionStream(ctx, openai.ChatCompletionRequest{
Model: model,
Messages: []openai.ChatCompletionMessage{{Role: openai.ChatMessageRoleUser, Content: prompt}},
Stream: true,
StreamOptions: &openai.StreamOptions{IncludeUsage: true},
})
if err != nil {
return nil, err
}
defer stream.Close()
var text, finish string
var usage any
for {
chunk, err := stream.Recv()
if errors.Is(err, io.EOF) {
break
}
if err != nil {
return nil, err
}
if chunk.Usage != nil {
usage = chunk.Usage
}
for _, choice := range chunk.Choices {
text += choice.Delta.Content
if choice.FinishReason != "" {
finish = string(choice.FinishReason)
}
}
}A complete program with a text reply, a stream and a tool round trip is in examples/go-openai/:
sh
cd examples/go-openai
PLUGBOARD_KEY=<app key> go run .What works
Chat Completions with streaming, tool calls and ResponseFormat JSON schema; the Responses API through CreateResponse.
Limits
- Set
MaxCompletionTokensrather thanMaxTokenswhen the model reasons, so it has room to answer. go-openai rejectsMaxTokensitself only for OpenAI reasoning model ids; plugboard accepts either. - Build the config before
NewClientWithConfig; the base URL can't be changed afterwards.