MCPcopy
hub / github.com/openai/openai-go

github.com/openai/openai-go @v3.41.0 sqlite

repository ↗ · DeepWiki ↗ · release v3.41.0 ↗
10,664 symbols 25,170 edges 256 files 4,730 documented · 44%
README

OpenAI Go API Library

Go Reference

The OpenAI Go library provides convenient access to the OpenAI REST API from applications written in Go.

[!WARNING] The latest version of this package has small and limited breaking changes. See the changelog for details.

Installation

import (
    "github.com/openai/openai-go/v3" // imported as openai
)

Or to pin the version:

go get -u 'github.com/openai/openai-go/v3@v3.41.0'

Requirements

This library requires Go 1.22+.

Usage

The full API of this library can be found in api.md.

The primary API for interacting with OpenAI models is the Responses API. You can generate text from the model with the code below.

package main

import (
    "context"

    "github.com/openai/openai-go/v3"
    "github.com/openai/openai-go/v3/option"
    "github.com/openai/openai-go/v3/responses"
)

func main() {
    ctx := context.Background()
    client := openai.NewClient(
        option.WithAPIKey("My API Key"), // defaults to os.LookupEnv("OPENAI_API_KEY")
    )

    question := "Write me a haiku about computers"

    resp, err := client.Responses.New(ctx, responses.ResponseNewParams{
        Input: responses.ResponseNewParamsInputUnion{OfString: openai.String(question)},
        Model: openai.ChatModelGPT5_2,
    })

    if err != nil {
        panic(err)
    }

    println(resp.OutputText())
}

Multi-turn Responses

response, err := client.Responses.New(ctx, responses.ResponseNewParams{
    Model: openai.ChatModelGPT5_2,
    Input: responses.ResponseNewParamsInputUnion{
        OfString: openai.String("What is the capital of France?"),
    },
})
if err != nil {
    panic(err)
}
fmt.Println("First response:", response.OutputText())

// Use PreviousResponseID to continue the conversation
response, err = client.Responses.New(ctx, responses.ResponseNewParams{
    Model:              openai.ChatModelGPT5_2,
    PreviousResponseID: openai.String(response.ID),
    Input: responses.ResponseNewParamsInputUnion{
        OfString: openai.String("And what is the population of that city?"),
    },
})
if err != nil {
    panic(err)
}
fmt.Println("Second response:", response.OutputText())

Conversations

conv, err := client.Conversations.New(ctx, conversations.ConversationNewParams{})
if err != nil {
    panic(err)
}
fmt.Println("Created conversation:", conv.ID)

response, err := client.Responses.New(ctx, responses.ResponseNewParams{
    Model: openai.ChatModelGPT5_2,
    Input: responses.ResponseNewParamsInputUnion{
        OfString: openai.String("Hello! Remember that my favorite color is blue."),
    },
    Conversation: responses.ResponseNewParamsConversationUnion{
        OfConversationObject: &responses.ResponseConversationParam{
            ID: conv.ID,
        },
    },
})
if err != nil {
    panic(err)
}
fmt.Println("First response:", response.OutputText())

// Continue the conversation
response, err = client.Responses.New(ctx, responses.ResponseNewParams{
    Model: openai.ChatModelGPT5_2,
    Input: responses.ResponseNewParamsInputUnion{
        OfString: openai.String("What is my favorite color?"),
    },
    Conversation: responses.ResponseNewParamsConversationUnion{
        OfConversationObject: &responses.ResponseConversationParam{
            ID: conv.ID,
        },
    },
})
if err != nil {
    panic(err)
}
fmt.Println("Second response:", response.OutputText())

items, err := client.Conversations.Items.List(ctx, conv.ID, conversations.ItemListParams{})
if err != nil {
    panic(err)
}
fmt.Println("Conversation has", len(items.Data), "items")

Streaming responses

ctx := context.Background()

stream := client.Responses.NewStreaming(ctx, responses.ResponseNewParams{
    Model: openai.ChatModelGPT5_2,
    Input: responses.ResponseNewParamsInputUnion{
        OfString: openai.String("Write a haiku about programming"),
    },
})

for stream.Next() {
    event := stream.Current()
    print(event.Delta)
}

if stream.Err() != nil {
    panic(stream.Err())
}

See the full streaming example

Tool calling

ctx := context.Background()

params := responses.ResponseNewParams{
    Model: openai.ChatModelGPT5_2,
    Input: responses.ResponseNewParamsInputUnion{
        OfString: openai.String("What is the weather in New York City?"),
    },
    Tools: []responses.ToolUnionParam{{
        OfFunction: &responses.FunctionToolParam{
            Name:        "get_weather",
            Description: openai.String("Get weather at the given location"),
            Parameters: map[string]any{
                "type": "object",
                "properties": map[string]any{
                    "location": map[string]string{
                        "type": "string",
                    },
                },
                "required": []string{"location"},
            },
        },
    }},
}

response, _ := client.Responses.New(ctx, params)

// Check for function calls in the response output
for _, item := range response.Output {
    if item.Type == "function_call" {
        toolCall := item.AsFunctionCall()
        if toolCall.Name == "get_weather" {
            // Extract arguments and call your function
            var args map[string]any
            json.Unmarshal([]byte(toolCall.Arguments), &args)
            location := args["location"].(string)

            // Simulate getting weather data
            weatherData := getWeather(location)
            fmt.Printf("Weather in %s: %s\n", location, weatherData)

            // Continue conversation with function result
            response, _ = client.Responses.New(ctx, responses.ResponseNewParams{
                Model:              openai.ChatModelGPT5_2,
                PreviousResponseID: openai.String(response.ID),
                Input: responses.ResponseNewParamsInputUnion{
                    OfInputItemList: []responses.ResponseInputItemUnionParam{{
                        OfFunctionCallOutput: &responses.ResponseInputItemFunctionCallOutputParam{
                            CallID: toolCall.CallID,
                            Output: responses.ResponseInputItemFunctionCallOutputOutputUnionParam{
                                OfString: openai.String(weatherData),
                            },
                        },
                    }},
                },
            })
        }
    }
}

Structured outputs

import (
    "encoding/json"
    "github.com/invopop/jsonschema"
    // ...
)

// A struct that will be converted to a Structured Outputs response schema
type HistoricalComputer struct {
    Origin       Origin   `json:"origin" jsonschema_description:"The origin of the computer"`
    Name         string   `json:"full_name" jsonschema_description:"The name of the device model"`
    Legacy       string   `json:"legacy" jsonschema:"enum=positive,enum=neutral,enum=negative" jsonschema_description:"Its influence on the field of computing"`
    NotableFacts []string `json:"notable_facts" jsonschema_description:"A few key facts about the computer"`
}

type Origin struct {
    YearBuilt    int64  `json:"year_of_construction" jsonschema_description:"The year it was made"`
    Organization string `json:"organization" jsonschema_description:"The organization that was in charge of its development"`
}

// Structured Outputs uses a subset of JSON schema
// These flags are necessary to comply with the subset
func GenerateSchema[T any]() map[string]any {
    reflector := jsonschema.Reflector{
        AllowAdditionalProperties: false,
        DoNotReference:            true,
    }
    var v T
    schema := reflector.Reflect(v)

    data, _ := json.Marshal(schema)
    var result map[string]any
    json.Unmarshal(data, &result)
    return result
}

// Generate the JSON schema at initialization time
var HistoricalComputerSchema = GenerateSchema[HistoricalComputer]()

func main() {
    client := openai.NewClient()
    ctx := context.Background()

    response, err := client.Responses.New(ctx, responses.ResponseNewParams{
        Model: openai.ChatModelGPT5_2,
        Input: responses.ResponseNewParamsInputUnion{
            OfString: openai.String("What computer ran the first neural network?"),
        },
        Text: responses.ResponseTextConfigParam{
            Format: responses.ResponseFormatTextConfigParamOfJSONSchema(
                "historical_computer",
                HistoricalComputerSchema,
            ),
        },
    })
    if err != nil {
        panic(err)
    }

    // extract into a well-typed struct
    var historicalComputer HistoricalComputer
    _ = json.Unmarshal([]byte(response.OutputText()), &historicalComputer)

    historicalComputer.Name
    historicalComputer.Origin.YearBuilt
    historicalComputer.Origin.Organization
    for i, fact := range historicalComputer.NotableFacts {
        // ...
    }
}

See the full structured outputs example

Chat Completions API

The previous standard (supported indefinitely) for generating text is the Chat Completions API. You can use that API to generate text from the model with the code below.

package main

import (
    "context"

    "github.com/openai/openai-go/v3"
)

func main() {
    client := openai.NewClient()

    chatCompletion, err := client.Chat.Completions.New(context.TODO(), openai.ChatCompletionNewParams{
        Messages: []openai.ChatCompletionMessageParamUnion{
            openai.DeveloperMessage("You are a coding assistant that talks like a pirate."),
            openai.UserMessage("How do I check if a slice is empty in Go?"),
        },
        Model: openai.ChatModelGPT5_2,
    })
    if err != nil {
        panic(err)
    }

    println(chatCompletion.Choices[0].Message.Content)
}

Request fields

The openai library uses the omitzero semantics from the Go 1.24+ encoding/json release for request fields.

Required primitive fields (int64, string, etc.) feature the tag `api:"required"`. These fields are always serialized, even their zero values.

Optional primitive types are wrapped in a param.Opt[T]. These fields can be set with the provided constructors, openai.String(string), openai.Int(int64), etc.

Any param.Opt[T], map, slice, struct or string enum uses the tag `json:"...,omitzero"`. Its zero value is considered omitted.

The param.IsOmitted(any) function can confirm the presence of any omitzero field.

p := openai.ExampleParams{
    ID:   "id_xxx",             // required property
    Name: openai.String("..."), // optional property

    Point: openai.Point{
        X: 0,             // required field will serialize as 0
        Y: openai.Int(1), // optional field will serialize as 1
        // ... omitted non-required fields will not be serialized
    },

    Origin: openai.Origin{}, // the zero value of [Origin] is considered omitted
}

To send null instead of a param.Opt[T], use param.Null[T](). To send null instead of a struct T, use param.NullStruct[T]().

p.Name = param.Null[string]()       // 'null' instead of string
p.Point = param.NullStruct[Point]() // 'null' instead of struct

param.IsNull(p.Name)  // true
param.IsNull(p.Point) // true

Request structs contain a .SetExtraFields(map[string]any) method which can send non-conforming fields in the request body. Extra fields overwrite any struct fields with a matching key. For security reasons, only use SetExtraFields with trusted data.

To send a custom value instead of a struct, use param.Override[T](value).

// In cases where the API specifies a given type,
// but you want to send something else, use [SetExtraFields]:
p.SetExtraFields(map[string]any{
    "x": 0.01, // send "x" as a float instead of int
})

// Send a number instead of an object
custom := param.Override[openai.FooParams](12)

Request unions

Unions are represented as a struct with fields prefixed by "Of" for each of its variants, only one field can be non-zero. The non-zero field will be serialized.

Sub-properties of the union can be accessed via methods on the union struct. These methods return a mutable pointer to the underlying data, if present.

// Only one field can be non-zero, use param.IsOmitted() to check if a field is set
type AnimalUnionParam struct {
    OfCat *Cat `json:",omitzero,inline`
    OfDog *Dog `json:",omitzero,inline`
}

animal := AnimalUnionParam{
    OfCat: &Cat{
        Name: "Whiskers",
        Owner: PersonParam{
            Address: AddressParam{Street: "3333 Coyote Hill Rd", Zip: 0},
        },
    },
}

// Mutating a field
if address := animal.GetOwner().GetAddress(); address != nil {
    address.ZipCode = 94304
}

Response objects

All fields in response structs are ordinary value types (not pointers or wrappers). Response structs also include a special JSON field containing metadata about each property.

type Animal struct {
    Name   string `json:"name,nullable"`
    Owners int    `json:"owners"`
    Age    int    `json:"age"`
    JSON   struct {
        Name        respjson.Field
        Owner       respjson.Field
        Age         respjson.Field
        ExtraFields map[string]respjson.Field
    } `json:"-"`
}

To handle optional data, use the .Valid() method on the JSON field. .Valid() returns true if a field is not null, not present, or couldn't be marshaled.

If .Valid() is false, the corresponding field will simply be its zero value.

raw := `{"owners": 1, "name": null}`

var res Animal
json.Unmarshal([]byte(raw), &res)

// Accessing regular fields

res.Owners // 1
res.Name   // ""
res.Age    // 0

// Optional field checks

res.JSON.Owners.Valid() // true
res.JSON.Name.Valid()   // false
res.JSON.Age.Valid()    // false

// Raw JSON values

res.JSON.Owners.Raw()                  // "1"
res.JSON.Name.Raw() == "null"          // true
res.JSON.Name.Raw() == respjson.Null   // true
res.JSON.Age.Raw() == ""               // true
res.JSON.Age.Raw() == respjson.Omitted // true

These .JSON structs also include an ExtraFields map containing any properties in the json response that were not specified in the struct. This can be useful for API features not yet

Extension points exported contracts — how you extend this code

Unmarshaler (Interface)
Unmarshaler is the interface implemented by types that can unmarshal a JSON description of themselves. The input can be [1714 …
internal/encoding/json/decode.go
Union (Interface)
(no doc) [6 implementers]
internal/apiform/form_test.go
Queryer (Interface)
(no doc) [67 implementers]
internal/apiquery/query.go
Union (Interface)
(no doc) [6 implementers]
internal/apijson/json_test.go
SubjectTokenProvider (Interface)
(no doc) [5 implementers]
auth/types.go
ParamNullable (Interface)
ParamNullable encapsulates all structs in parameters, and all [Opt] types in parameters. [1 implementers]
packages/param/param.go
TokenCredentialOption (FuncType)
TokenCredentialOption is the type for any options that can be used to customize [WithTokenCredential], including things
azure/azure.go
HTTPDoer (Interface)
This interface is primarily used to describe an [*http.Client], but also supports custom HTTP implementations.
internal/requestconfig/requestconfig.go

Core symbols most depended-on inside this repo

UnmarshalRoot
called by 2355
internal/apijson/decoder.go
MarshalObject
called by 423
packages/param/encoder.go
IsOmitted
called by 394
packages/param/param.go
marshalString
called by 383
shared/constant/constants.go
Error
called by 314
auth/error.go
WithAPIKey
called by 289
option/requestoption.go
WithAdminAPIKey
called by 272
option/requestoption.go
String
called by 260
packages/param/option.go

Shape

Method 6,835
Struct 2,102
Function 855
TypeAlias 761
Interface 98
FuncType 13

Languages

Go100%

Modules by API surface

responses/response.go2,507 symbols
shared/constant/constants.go1,154 symbols
adminorganizationusage.go816 symbols
chatcompletion.go456 symbols
betaassistant.go263 symbols
adminorganizationauditlog.go249 symbols
realtime/realtime.go228 symbols
betathreadmessage.go214 symbols
betathread.go195 symbols
finetuningmethod.go192 symbols
gradergradermodel.go186 symbols
betachatkitthread.go186 symbols

Dependencies from manifests, versioned

github.com/Azure/azure-sdk-for-go/sdk/azcorev1.17.0 · 1×
github.com/Azure/azure-sdk-for-go/sdk/azidentityv1.7.0 · 1×
github.com/Azure/azure-sdk-for-go/sdk/internalv1.10.0 · 1×
github.com/AzureAD/microsoft-authentication-library-for-gov1.2.2 · 1×
github.com/bahlo/generic-list-gov0.2.0 · 1×
github.com/ebitengine/puregov0.7.0 · 1×
github.com/invopop/jsonschemav0.12.0 · 1×
github.com/kylelemons/godebugv1.1.0 · 1×

For agents

$ claude mcp add openai-go \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact