README.md

  1# Anthropic Go API Library
  2
  3<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go"><img src="https://pkg.go.dev/badge/github.com/anthropics/anthropic-sdk-go.svg" alt="Go Reference"></a>
  4
  5The Anthropic Go library provides convenient access to the [Anthropic REST API](https://docs.anthropic.com/claude/reference/)
  6from applications written in Go.
  7
  8## Installation
  9
 10<!-- x-release-please-start-version -->
 11
 12```go
 13import (
 14	"github.com/anthropics/anthropic-sdk-go" // imported as anthropic
 15)
 16```
 17
 18<!-- x-release-please-end -->
 19
 20Or to pin the version:
 21
 22<!-- x-release-please-start-version -->
 23
 24```sh
 25go get -u 'github.com/anthropics/anthropic-sdk-go@v1.4.0'
 26```
 27
 28<!-- x-release-please-end -->
 29
 30## Requirements
 31
 32This library requires Go 1.18+.
 33
 34## Usage
 35
 36The full API of this library can be found in [api.md](api.md).
 37
 38```go
 39package main
 40
 41import (
 42	"context"
 43	"fmt"
 44
 45	"github.com/anthropics/anthropic-sdk-go"
 46	"github.com/anthropics/anthropic-sdk-go/option"
 47)
 48
 49func main() {
 50	client := anthropic.NewClient(
 51		option.WithAPIKey("my-anthropic-api-key"), // defaults to os.LookupEnv("ANTHROPIC_API_KEY")
 52	)
 53	message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
 54		MaxTokens: 1024,
 55		Messages: []anthropic.MessageParam{{
 56			Content: []anthropic.ContentBlockParamUnion{{
 57				OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?"},
 58			}},
 59			Role: anthropic.MessageParamRoleUser,
 60		}},
 61		Model: anthropic.ModelClaude3_7SonnetLatest,
 62	})
 63	if err != nil {
 64		panic(err.Error())
 65	}
 66	fmt.Printf("%+v\n", message.Content)
 67}
 68
 69```
 70
 71<details>
 72<summary>Conversations</summary>
 73
 74```go
 75messages := []anthropic.MessageParam{
 76    anthropic.NewUserMessage(anthropic.NewTextBlock("What is my first name?")),
 77}
 78
 79message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
 80    Model:     anthropic.ModelClaude3_7SonnetLatest,
 81    Messages:  messages,
 82    MaxTokens: 1024,
 83})
 84if err != nil {
 85    panic(err)
 86}
 87
 88fmt.Printf("%+v\n", message.Content)
 89
 90messages = append(messages, message.ToParam())
 91messages = append(messages, anthropic.NewUserMessage(
 92    anthropic.NewTextBlock("My full name is John Doe"),
 93))
 94
 95message, err = client.Messages.New(context.TODO(), anthropic.MessageNewParams{
 96    Model:     anthropic.ModelClaude3_7SonnetLatest,
 97    Messages:  messages,
 98    MaxTokens: 1024,
 99})
100
101fmt.Printf("%+v\n", message.Content)
102```
103
104</details>
105
106<details>
107<summary>System prompts</summary>
108
109```go
110message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
111    Model:     anthropic.ModelClaude3_7SonnetLatest,
112    MaxTokens: 1024,
113    System: []anthropic.TextBlockParam{
114        {Text: "Be very serious at all times."},
115    },
116    Messages: messages,
117})
118```
119
120</details>
121
122<details>
123<summary>Streaming</summary>
124
125```go
126content := "What is a quaternion?"
127
128stream := client.Messages.NewStreaming(context.TODO(), anthropic.MessageNewParams{
129    Model:     anthropic.ModelClaude3_7SonnetLatest,
130    MaxTokens: 1024,
131    Messages: []anthropic.MessageParam{
132        anthropic.NewUserMessage(anthropic.NewTextBlock(content)),
133    },
134})
135
136message := anthropic.Message{}
137for stream.Next() {
138    event := stream.Current()
139    err := message.Accumulate(event)
140    if err != nil {
141        panic(err)
142    }
143
144    switch eventVariant := event.AsAny().(type) {
145        case anthropic.ContentBlockDeltaEvent:
146        switch deltaVariant := eventVariant.Delta.AsAny().(type) {
147        case anthropic.TextDelta:
148            print(deltaVariant.Text)
149        }
150
151    }
152}
153
154if stream.Err() != nil {
155    panic(stream.Err())
156}
157```
158
159</details>
160
161<details>
162<summary>Tool calling</summary>
163
164```go
165package main
166
167import (
168	"context"
169	"encoding/json"
170	"fmt"
171
172	"github.com/anthropics/anthropic-sdk-go"
173	"github.com/invopop/jsonschema"
174)
175
176func main() {
177	client := anthropic.NewClient()
178
179	content := "Where is San Francisco?"
180
181	println("[user]: " + content)
182
183	messages := []anthropic.MessageParam{
184		anthropic.NewUserMessage(anthropic.NewTextBlock(content)),
185	}
186
187	toolParams := []anthropic.ToolParam{
188		{
189			Name:        "get_coordinates",
190			Description: anthropic.String("Accepts a place as an address, then returns the latitude and longitude coordinates."),
191			InputSchema: GetCoordinatesInputSchema,
192		},
193	}
194	tools := make([]anthropic.ToolUnionParam, len(toolParams))
195	for i, toolParam := range toolParams {
196		tools[i] = anthropic.ToolUnionParam{OfTool: &toolParam}
197	}
198
199	for {
200		message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
201			Model:     anthropic.ModelClaude3_7SonnetLatest,
202			MaxTokens: 1024,
203			Messages:  messages,
204			Tools:     tools,
205		})
206
207		if err != nil {
208			panic(err)
209		}
210
211		print(color("[assistant]: "))
212		for _, block := range message.Content {
213			switch block := block.AsAny().(type) {
214			case anthropic.TextBlock:
215				println(block.Text)
216				println()
217			case anthropic.ToolUseBlock:
218				inputJSON, _ := json.Marshal(block.Input)
219				println(block.Name + ": " + string(inputJSON))
220				println()
221			}
222		}
223
224		messages = append(messages, message.ToParam())
225		toolResults := []anthropic.ContentBlockParamUnion{}
226
227		for _, block := range message.Content {
228			switch variant := block.AsAny().(type) {
229			case anthropic.ToolUseBlock:
230				print(color("[user (" + block.Name + ")]: "))
231
232				var response interface{}
233				switch block.Name {
234				case "get_coordinates":
235					var input struct {
236						Location string `json:"location"`
237					}
238
239					err := json.Unmarshal([]byte(variant.JSON.Input.Raw()), &input)
240					if err != nil {
241						panic(err)
242					}
243
244					response = GetCoordinates(input.Location)
245				}
246
247				b, err := json.Marshal(response)
248				if err != nil {
249					panic(err)
250				}
251
252				println(string(b))
253
254				toolResults = append(toolResults, anthropic.NewToolResultBlock(block.ID, string(b), false))
255			}
256
257		}
258		if len(toolResults) == 0 {
259			break
260		}
261		messages = append(messages, anthropic.NewUserMessage(toolResults...))
262	}
263}
264
265type GetCoordinatesInput struct {
266	Location string `json:"location" jsonschema_description:"The location to look up."`
267}
268
269var GetCoordinatesInputSchema = GenerateSchema[GetCoordinatesInput]()
270
271type GetCoordinateResponse struct {
272	Long float64 `json:"long"`
273	Lat  float64 `json:"lat"`
274}
275
276func GetCoordinates(location string) GetCoordinateResponse {
277	return GetCoordinateResponse{
278		Long: -122.4194,
279		Lat:  37.7749,
280	}
281}
282
283func GenerateSchema[T any]() anthropic.ToolInputSchemaParam {
284	reflector := jsonschema.Reflector{
285		AllowAdditionalProperties: false,
286		DoNotReference:            true,
287	}
288	var v T
289
290	schema := reflector.Reflect(v)
291
292	return anthropic.ToolInputSchemaParam{
293		Properties: schema.Properties,
294	}
295}
296
297func color(s string) string {
298	return fmt.Sprintf("\033[1;%sm%s\033[0m", "33", s)
299}
300```
301
302</details>
303
304### Request fields
305
306The anthropic library uses the [`omitzero`](https://tip.golang.org/doc/go1.24#encodingjsonpkgencodingjson)
307semantics from the Go 1.24+ `encoding/json` release for request fields.
308
309Required primitive fields (`int64`, `string`, etc.) feature the tag <code>\`json:"...,required"\`</code>. These
310fields are always serialized, even their zero values.
311
312Optional primitive types are wrapped in a `param.Opt[T]`. These fields can be set with the provided constructors, `anthropic.String(string)`, `anthropic.Int(int64)`, etc.
313
314Any `param.Opt[T]`, map, slice, struct or string enum uses the
315tag <code>\`json:"...,omitzero"\`</code>. Its zero value is considered omitted.
316
317The `param.IsOmitted(any)` function can confirm the presence of any `omitzero` field.
318
319```go
320p := anthropic.ExampleParams{
321	ID:   "id_xxx",                // required property
322	Name: anthropic.String("..."), // optional property
323
324	Point: anthropic.Point{
325		X: 0,                // required field will serialize as 0
326		Y: anthropic.Int(1), // optional field will serialize as 1
327		// ... omitted non-required fields will not be serialized
328	},
329
330	Origin: anthropic.Origin{}, // the zero value of [Origin] is considered omitted
331}
332```
333
334To send `null` instead of a `param.Opt[T]`, use `param.Null[T]()`.
335To send `null` instead of a struct `T`, use `param.NullStruct[T]()`.
336
337```go
338p.Name = param.Null[string]()       // 'null' instead of string
339p.Point = param.NullStruct[Point]() // 'null' instead of struct
340
341param.IsNull(p.Name)  // true
342param.IsNull(p.Point) // true
343```
344
345Request structs contain a `.SetExtraFields(map[string]any)` method which can send non-conforming
346fields in the request body. Extra fields overwrite any struct fields with a matching
347key.
348
349> [!WARNING]
350> For security reasons, only use `SetExtraFields` with trusted data.
351
352To send a custom value instead of a struct, use `param.Override[T](value)`.
353
354```go
355// In cases where the API specifies a given type,
356// but you want to send something else, use [SetExtraFields]:
357p.SetExtraFields(map[string]any{
358	"x": 0.01, // send "x" as a float instead of int
359})
360
361// Send a number instead of an object
362custom := param.Override[anthropic.FooParams](12)
363```
364
365### Request unions
366
367Unions are represented as a struct with fields prefixed by "Of" for each of it's variants,
368only one field can be non-zero. The non-zero field will be serialized.
369
370Sub-properties of the union can be accessed via methods on the union struct.
371These methods return a mutable pointer to the underlying data, if present.
372
373```go
374// Only one field can be non-zero, use param.IsOmitted() to check if a field is set
375type AnimalUnionParam struct {
376	OfCat *Cat `json:",omitzero,inline`
377	OfDog *Dog `json:",omitzero,inline`
378}
379
380animal := AnimalUnionParam{
381	OfCat: &Cat{
382		Name: "Whiskers",
383		Owner: PersonParam{
384			Address: AddressParam{Street: "3333 Coyote Hill Rd", Zip: 0},
385		},
386	},
387}
388
389// Mutating a field
390if address := animal.GetOwner().GetAddress(); address != nil {
391	address.ZipCode = 94304
392}
393```
394
395### Response objects
396
397All fields in response structs are ordinary value types (not pointers or wrappers).
398Response structs also include a special `JSON` field containing metadata about
399each property.
400
401```go
402type Animal struct {
403	Name   string `json:"name,nullable"`
404	Owners int    `json:"owners"`
405	Age    int    `json:"age"`
406	JSON   struct {
407		Name        respjson.Field
408		Owner       respjson.Field
409		Age         respjson.Field
410		ExtraFields map[string]respjson.Field
411	} `json:"-"`
412}
413```
414
415To handle optional data, use the `.Valid()` method on the JSON field.
416`.Valid()` returns true if a field is not `null`, not present, or couldn't be marshaled.
417
418If `.Valid()` is false, the corresponding field will simply be its zero value.
419
420```go
421raw := `{"owners": 1, "name": null}`
422
423var res Animal
424json.Unmarshal([]byte(raw), &res)
425
426// Accessing regular fields
427
428res.Owners // 1
429res.Name   // ""
430res.Age    // 0
431
432// Optional field checks
433
434res.JSON.Owners.Valid() // true
435res.JSON.Name.Valid()   // false
436res.JSON.Age.Valid()    // false
437
438// Raw JSON values
439
440res.JSON.Owners.Raw()                  // "1"
441res.JSON.Name.Raw() == "null"          // true
442res.JSON.Name.Raw() == respjson.Null   // true
443res.JSON.Age.Raw() == ""               // true
444res.JSON.Age.Raw() == respjson.Omitted // true
445```
446
447These `.JSON` structs also include an `ExtraFields` map containing
448any properties in the json response that were not specified
449in the struct. This can be useful for API features not yet
450present in the SDK.
451
452```go
453body := res.JSON.ExtraFields["my_unexpected_field"].Raw()
454```
455
456### Response Unions
457
458In responses, unions are represented by a flattened struct containing all possible fields from each of the
459object variants.
460To convert it to a variant use the `.AsFooVariant()` method or the `.AsAny()` method if present.
461
462If a response value union contains primitive values, primitive fields will be alongside
463the properties but prefixed with `Of` and feature the tag `json:"...,inline"`.
464
465```go
466type AnimalUnion struct {
467	// From variants [Dog], [Cat]
468	Owner Person `json:"owner"`
469	// From variant [Dog]
470	DogBreed string `json:"dog_breed"`
471	// From variant [Cat]
472	CatBreed string `json:"cat_breed"`
473	// ...
474
475	JSON struct {
476		Owner respjson.Field
477		// ...
478	} `json:"-"`
479}
480
481// If animal variant
482if animal.Owner.Address.ZipCode == "" {
483	panic("missing zip code")
484}
485
486// Switch on the variant
487switch variant := animal.AsAny().(type) {
488case Dog:
489case Cat:
490default:
491	panic("unexpected type")
492}
493```
494
495### RequestOptions
496
497This library uses the functional options pattern. Functions defined in the
498`option` package return a `RequestOption`, which is a closure that mutates a
499`RequestConfig`. These options can be supplied to the client or at individual
500requests. For example:
501
502```go
503client := anthropic.NewClient(
504	// Adds a header to every request made by the client
505	option.WithHeader("X-Some-Header", "custom_header_info"),
506)
507
508client.Messages.New(context.TODO(), ...,
509	// Override the header
510	option.WithHeader("X-Some-Header", "some_other_custom_header_info"),
511	// Add an undocumented field to the request body, using sjson syntax
512	option.WithJSONSet("some.json.path", map[string]string{"my": "object"}),
513)
514```
515
516See the [full list of request options](https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go/option).
517
518### Pagination
519
520This library provides some conveniences for working with paginated list endpoints.
521
522You can use `.ListAutoPaging()` methods to iterate through items across all pages:
523
524```go
525iter := client.Beta.Messages.Batches.ListAutoPaging(context.TODO(), anthropic.BetaMessageBatchListParams{
526	Limit: anthropic.Int(20),
527})
528// Automatically fetches more pages as needed.
529for iter.Next() {
530	betaMessageBatch := iter.Current()
531	fmt.Printf("%+v\n", betaMessageBatch)
532}
533if err := iter.Err(); err != nil {
534	panic(err.Error())
535}
536```
537
538Or you can use simple `.List()` methods to fetch a single page and receive a standard response object
539with additional helper methods like `.GetNextPage()`, e.g.:
540
541```go
542page, err := client.Beta.Messages.Batches.List(context.TODO(), anthropic.BetaMessageBatchListParams{
543	Limit: anthropic.Int(20),
544})
545for page != nil {
546	for _, batch := range page.Data {
547		fmt.Printf("%+v\n", batch)
548	}
549	page, err = page.GetNextPage()
550}
551if err != nil {
552	panic(err.Error())
553}
554```
555
556### Errors
557
558When the API returns a non-success status code, we return an error with type
559`*anthropic.Error`. This contains the `StatusCode`, `*http.Request`, and
560`*http.Response` values of the request, as well as the JSON of the error body
561(much like other response objects in the SDK).
562
563To handle errors, we recommend that you use the `errors.As` pattern:
564
565```go
566_, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
567	MaxTokens: 1024,
568	Messages: []anthropic.MessageParam{{
569		Content: []anthropic.ContentBlockParamUnion{{
570			OfText: &anthropic.TextBlockParam{Text: "What is a quaternion?", CacheControl: anthropic.NewCacheControlEphemeralParam(), Citations: []anthropic.TextCitationParamUnion{{
571				OfCharLocation: &anthropic.CitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
572			}}},
573		}},
574		Role: anthropic.MessageParamRoleUser,
575	}},
576	Model: anthropic.ModelClaude3_7SonnetLatest,
577})
578if err != nil {
579	var apierr *anthropic.Error
580	if errors.As(err, &apierr) {
581		println(string(apierr.DumpRequest(true)))  // Prints the serialized HTTP request
582		println(string(apierr.DumpResponse(true))) // Prints the serialized HTTP response
583	}
584	panic(err.Error()) // GET "/v1/messages": 400 Bad Request { ... }
585}
586```
587
588When other errors occur, they are returned unwrapped; for example,
589if HTTP transport fails, you might receive `*url.Error` wrapping `*net.OpError`.
590
591### Timeouts
592
593Requests do not time out by default; use context to configure a timeout for a request lifecycle.
594
595Note that if a request is [retried](#retries), the context timeout does not start over.
596To set a per-retry timeout, use `option.WithRequestTimeout()`.
597
598```go
599// This sets the timeout for the request, including all the retries.
600ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
601defer cancel()
602client.Messages.New(
603	ctx,
604	anthropic.MessageNewParams{
605		MaxTokens: 1024,
606		Messages: []anthropic.MessageParam{{
607			Content: []anthropic.ContentBlockParamUnion{{
608				OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?"},
609			}},
610			Role: anthropic.MessageParamRoleUser,
611		}},
612		Model: anthropic.ModelClaude3_7SonnetLatest,
613	},
614	// This sets the per-retry timeout
615	option.WithRequestTimeout(20*time.Second),
616)
617```
618
619### Long Requests
620
621> [!IMPORTANT]
622> We highly encourage you use the streaming Messages API for longer running requests.
623
624We do not recommend setting a large `MaxTokens` value without using streaming as some networks may drop idle connections after a certain period of time, which
625can cause the request to fail or [timeout](#timeouts) without receiving a response from Anthropic.
626
627This SDK will also return an error if a non-streaming request is expected to be above roughly 10 minutes long.
628Calling `.Messages.NewStreaming()` or [setting a custom timeout](#timeouts) disables this error.
629
630### File uploads
631
632Request parameters that correspond to file uploads in multipart requests are typed as
633`io.Reader`. The contents of the `io.Reader` will by default be sent as a multipart form
634part with the file name of "anonymous_file" and content-type of "application/octet-stream", so we
635recommend always specifyig a custom content-type with the `anthropic.File(reader io.Reader, filename string, contentType string)`
636helper we provide to easily wrap any `io.Reader` with the appropriate file name and content type.
637
638```go
639// A file from the file system
640file, err := os.Open("/path/to/file.json")
641anthropic.BetaFileUploadParams{
642	File: anthropic.File(file, "custom-name.json", "application/json"),
643	Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaFilesAPI2025_04_14},
644}
645
646// A file from a string
647anthropic.BetaFileUploadParams{
648	File: anthropic.File(strings.NewReader("my file contents"), "custom-name.json", "application/json"),
649	Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaFilesAPI2025_04_14},
650}
651```
652
653The file name and content-type can also be customized by implementing `Name() string` or `ContentType()
654string` on the run-time type of `io.Reader`. Note that `os.File` implements `Name() string`, so a
655file returned by `os.Open` will be sent with the file name on disk.
656
657### Retries
658
659Certain errors will be automatically retried 2 times by default, with a short exponential backoff.
660We retry by default all connection errors, 408 Request Timeout, 409 Conflict, 429 Rate Limit,
661and >=500 Internal errors.
662
663You can use the `WithMaxRetries` option to configure or disable this:
664
665```go
666// Configure the default for all requests:
667client := anthropic.NewClient(
668	option.WithMaxRetries(0), // default is 2
669)
670
671// Override per-request:
672client.Messages.New(
673	context.TODO(),
674	anthropic.MessageNewParams{
675		MaxTokens: 1024,
676		Messages: []anthropic.MessageParam{{
677			Content: []anthropic.ContentBlockParamUnion{{
678				OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?"},
679			}},
680			Role: anthropic.MessageParamRoleUser,
681		}},
682		Model: anthropic.ModelClaude3_7SonnetLatest,
683	},
684	option.WithMaxRetries(5),
685)
686```
687
688### Accessing raw response data (e.g. response headers)
689
690You can access the raw HTTP response data by using the `option.WithResponseInto()` request option. This is useful when
691you need to examine response headers, status codes, or other details.
692
693```go
694// Create a variable to store the HTTP response
695var response *http.Response
696message, err := client.Messages.New(
697	context.TODO(),
698	anthropic.MessageNewParams{
699		MaxTokens: 1024,
700		Messages: []anthropic.MessageParam{{
701			Content: []anthropic.ContentBlockParamUnion{{
702				OfText: &anthropic.TextBlockParam{Text: "What is a quaternion?", CacheControl: anthropic.NewCacheControlEphemeralParam(), Citations: []anthropic.TextCitationParamUnion{{
703					OfCharLocation: &anthropic.CitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
704				}}},
705			}},
706			Role: anthropic.MessageParamRoleUser,
707		}},
708		Model: anthropic.ModelClaude3_7SonnetLatest,
709	},
710	option.WithResponseInto(&response),
711)
712if err != nil {
713	// handle error
714}
715fmt.Printf("%+v\n", message)
716
717fmt.Printf("Status Code: %d\n", response.StatusCode)
718fmt.Printf("Headers: %+#v\n", response.Header)
719```
720
721### Making custom/undocumented requests
722
723This library is typed for convenient access to the documented API. If you need to access undocumented
724endpoints, params, or response properties, the library can still be used.
725
726#### Undocumented endpoints
727
728To make requests to undocumented endpoints, you can use `client.Get`, `client.Post`, and other HTTP verbs.
729`RequestOptions` on the client, such as retries, will be respected when making these requests.
730
731```go
732var (
733    // params can be an io.Reader, a []byte, an encoding/json serializable object,
734    // or a "…Params" struct defined in this library.
735    params map[string]any
736
737    // result can be an []byte, *http.Response, a encoding/json deserializable object,
738    // or a model defined in this library.
739    result *http.Response
740)
741err := client.Post(context.Background(), "/unspecified", params, &result)
742if err != nil {
743    …
744}
745```
746
747#### Undocumented request params
748
749To make requests using undocumented parameters, you may use either the `option.WithQuerySet()`
750or the `option.WithJSONSet()` methods.
751
752```go
753params := FooNewParams{
754    ID:   "id_xxxx",
755    Data: FooNewParamsData{
756        FirstName: anthropic.String("John"),
757    },
758}
759client.Foo.New(context.Background(), params, option.WithJSONSet("data.last_name", "Doe"))
760```
761
762#### Undocumented response properties
763
764To access undocumented response properties, you may either access the raw JSON of the response as a string
765with `result.JSON.RawJSON()`, or get the raw JSON of a particular field on the result with
766`result.JSON.Foo.Raw()`.
767
768Any fields that are not present on the response struct will be saved and can be accessed by `result.JSON.ExtraFields()` which returns the extra fields as a `map[string]Field`.
769
770### Middleware
771
772We provide `option.WithMiddleware` which applies the given
773middleware to requests.
774
775```go
776func Logger(req *http.Request, next option.MiddlewareNext) (res *http.Response, err error) {
777	// Before the request
778	start := time.Now()
779	LogReq(req)
780
781	// Forward the request to the next handler
782	res, err = next(req)
783
784	// Handle stuff after the request
785	end := time.Now()
786	LogRes(res, err, start - end)
787
788    return res, err
789}
790
791client := anthropic.NewClient(
792	option.WithMiddleware(Logger),
793)
794```
795
796When multiple middlewares are provided as variadic arguments, the middlewares
797are applied left to right. If `option.WithMiddleware` is given
798multiple times, for example first in the client then the method, the
799middleware in the client will run first and the middleware given in the method
800will run next.
801
802You may also replace the default `http.Client` with
803`option.WithHTTPClient(client)`. Only one http client is
804accepted (this overwrites any previous client) and receives requests after any
805middleware has been applied.
806
807## Amazon Bedrock
808
809To use this library with [Amazon Bedrock](https://aws.amazon.com/bedrock/claude/),
810use the bedrock request option `bedrock.WithLoadDefaultConfig(…)` which reads the
811[default config](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html).
812
813Importing the `bedrock` library also globally registers a decoder for `application/vnd.amazon.eventstream` for
814streaming.
815
816```go
817package main
818
819import (
820	"github.com/anthropics/anthropic-sdk-go"
821	"github.com/anthropics/anthropic-sdk-go/bedrock"
822)
823
824func main() {
825	client := anthropic.NewClient(
826		bedrock.WithLoadDefaultConfig(context.Background()),
827	)
828}
829```
830
831If you already have an `aws.Config`, you can also use it directly with `bedrock.WithConfig(cfg)`.
832
833Read more about Anthropic and Amazon Bedrock [here](https://docs.anthropic.com/en/api/claude-on-amazon-bedrock).
834
835## Google Vertex AI
836
837To use this library with [Google Vertex AI](https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-claude),
838use the request option `vertex.WithGoogleAuth(…)` which reads the
839[Application Default Credentials](https://cloud.google.com/docs/authentication/application-default-credentials).
840
841```go
842package main
843
844import (
845	"context"
846
847	"github.com/anthropics/anthropic-sdk-go"
848	"github.com/anthropics/anthropic-sdk-go/vertex"
849)
850
851func main() {
852	client := anthropic.NewClient(
853		vertex.WithGoogleAuth(context.Background(), "us-central1", "id-xxx"),
854	)
855}
856```
857
858If you already have `*google.Credentials`, you can also use it directly with
859`vertex.WithCredentials(ctx, region, projectId, creds)`.
860
861Read more about Anthropic and Google Vertex [here](https://docs.anthropic.com/en/api/claude-on-vertex-ai).
862
863## Semantic versioning
864
865This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:
866
8671. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_
8682. Changes that we do not expect to impact the vast majority of users in practice.
869
870We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.
871
872We are keen for your feedback; please open an [issue](https://www.github.com/anthropics/anthropic-sdk-go/issues) with questions, bugs, or suggestions.
873
874## Contributing
875
876See [the contributing documentation](./CONTRIBUTING.md).