Skip to content

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 MaxCompletionTokens rather than MaxTokens when the model reasons, so it has room to answer. go-openai rejects MaxTokens itself only for OpenAI reasoning model ids; plugboard accepts either.
  • Build the config before NewClientWithConfig; the base URL can't be changed afterwards.