Go SDK
package goodmem // import "fury.io/pairsys/goodmem"The GoodMem Go SDK offers an OpenAI-style API where any operation is accessed through client.<Namespace>().<Method>(ctx, ...) on a *goodmem.Client. It is synchronous and context.Context-driven — there is no async surface; cancellation and deadlines come from the context you pass in.
Installation
The SDK is distributed through GoodMem's public Gemfury Go module proxy — no account or token required. Point Go at the proxy once, then install as usual:
# One-time setup: resolve fury.io/pairsys/* through GoodMem's public proxy
# (the default proxy stays as the fallback for your other dependencies), and
# skip the public checksum database for that path only.
go env -w GOPROXY="https://go-proxy.fury.io/pairsys/,https://proxy.golang.org,direct"
go env -w GONOSUMDB="fury.io/pairsys/*"
# Install
go get fury.io/pairsys/goodmem@latestimport (
goodmem "fury.io/pairsys/goodmem"
"fury.io/pairsys/goodmem/models"
)Do not set GOPRIVATE or GONOPROXY for fury.io/pairsys/* — those tell Go to bypass the proxy and fetch the module directly, which fails. The package is public and is served through the proxy.
Requirements: Go 1.23+. The SDK depends only on the standard library.
Client
The Go SDK ships a single synchronous *goodmem.Client. Every method takes a context.Context and returns a typed response plus an error. A Client is safe for concurrent use by multiple goroutines.
Construction
client, err := goodmem.New("http://localhost:8080", "gm_...")
if err != nil {
log.Fatal(err)
}- The base URL may carry a mount-path prefix (e.g.
https://host/api) — it is preserved on every request. - An empty API key is allowed (the unauthenticated bootstrap endpoints
/v1/system/infoand/v1/system/initare callable without one); every other endpoint returns401from the server.
To supply your own *http.Client (interceptors, proxy, custom TLS, connection pool tuning), use the WithHTTPClient option:
client, err := goodmem.New("http://localhost:8080", "gm_...",
goodmem.WithHTTPClient(myHTTPClient))In bring-your-own mode you own the redirect policy; the SDK-built default refuses to follow redirects so the x-api-key header cannot leak across a host boundary.
Quickstart
package main
import (
"context"
"log"
goodmem "fury.io/pairsys/goodmem"
"fury.io/pairsys/goodmem/models"
)
func main() {
ctx := context.Background()
client, err := goodmem.New("http://localhost:8080", "gm_...")
if err != nil {
log.Fatal(err)
}
// Create an embedder. The registry auto-fills provider, endpoint and
// dimensionality from the model identifier; the bare apiKey is converted
// to structured credentials.
embedder, err := client.Embedders().Create(ctx, &models.EmbedderCreationRequest{
DisplayName: "My OpenAI",
ModelIdentifier: "text-embedding-3-large",
}, "sk-...")
if err != nil {
log.Fatal(err)
}
_ = embedder
}Pagination
List methods that page return a *Page[T]. Range over All(ctx) to walk every item across pages transparently, or drive the cursor yourself with Items(), NextToken(), HasMore() and Next(ctx).
page, err := client.Memories().List(ctx, spaceID, nil)
if err != nil {
log.Fatal(err)
}
for memory, err := range page.All(ctx) {
if err != nil {
log.Fatal(err)
}
_ = memory
}Streaming
Streaming methods return a *Stream[T]. Range over Events() and always Close() the stream when done.
stream, err := client.Memories().Retrieve(ctx, "What do you know about ...?", nil)
if err != nil {
log.Fatal(err)
}
defer stream.Close()
for event, err := range stream.Events() {
if err != nil {
log.Fatal(err)
}
_ = event
}Errors
Every method returns a typed error on failure. Transport problems come back as *goodmem.NetworkError; non-2xx HTTP responses come back as an *goodmem.APIError (or one of its status-specific subtypes). Branch with errors.As (from the standard-library errors package):
resp, err := client.Spaces().Get(ctx, spaceID)
if err != nil {
var notFound *goodmem.NotFoundError
if errors.As(err, ¬Found) {
// 404 — handle missing space
}
var apiErr *goodmem.APIError
if errors.As(err, &apiErr) {
log.Printf("server returned %d: %s", apiErr.StatusCode, apiErr.Message)
}
log.Fatal(err)
}
_ = respThe status-specific subtypes are *BadRequestError (400), *AuthenticationError (401), *PermissionDeniedError (403), *NotFoundError (404), *ConflictError (409), *UnprocessableEntityError (422), *RateLimitError (429) and *InternalServerError (5xx). All wrap *APIError, so an errors.As against *APIError matches any of them.
Namespaces
| Namespace | Description | Reference |
|---|---|---|
Embedders | Embedder management | client.Embedders() |
Rerankers | Reranker management | client.Rerankers() |
LLMs | LLM management | client.LLMs() |
Spaces | Memory space management | client.Spaces() |
Memories | Memory CRUD, retrieval, and batch operations | client.Memories() |
OCR | Document text extraction | client.OCR() |
System | Server info and initialization | client.System() |
Users | User lookup | client.Users() |
Admin | Server lifecycle operations | client.Admin() |
APIKeys | API key lifecycle management | client.APIKeys() |
Ping | Endpoint health probes (single-shot and streaming) | client.Ping() |
API reference
Full per-type and per-method documentation — every field, JSON wire name and method signature — is published on pkg.go.dev. The per-namespace pages below link into it.
Common Data Models
Wire types shared across namespaces. Every field, its Go type and JSON wire name is also on pkg.go.dev.
Index
- type ProviderType
- type Modality
- type EndpointAuthentication
- type CredentialKind
- type ApiKeyAuth
- type GcpAdcAuth
- type SecretReference
- type GoodMemStatus
- type ChunkingConfiguration
- type NoChunkingConfiguration
- type RecursiveChunkingConfiguration
- type SentenceChunkingConfiguration
- type SeparatorKeepStrategy
- type LengthMeasurement
- type SortOrder
type ProviderType
type ProviderType string
Embedding provider types
String enum (type ProviderType string): "OPENAI" · "VLLM" · "TEI" · "LLAMA_CPP" · "VOYAGE" · "COHERE" · "JINA"
type Modality
type Modality string
Content modality types supported by embedders
String enum (type Modality string): "TEXT" · "IMAGE" · "AUDIO" · "VIDEO"
type EndpointAuthentication
type EndpointAuthentication struct{ … }
Structured credential payload describing how GoodMem should authenticate with an upstream provider.
Kind(models.CredentialKind, wirekind) — Selected credential strategyAPIKey(models.ApiKeyAuth, optional, wireapiKey) — Configuration when kind is CREDENTIAL_KIND_API_KEYGCPADC(models.GcpAdcAuth, optional, wiregcpAdc) — Configuration when kind is CREDENTIAL_KIND_GCP_ADCLabels(map[string]string, optional, wirelabels) — Optional annotations to aid operators (e.g., "owner=vertex")
type CredentialKind
type CredentialKind string
Credential kinds supported for upstream endpoint authentication.
String enum (type CredentialKind string): "CREDENTIAL_KIND_UNSPECIFIED" · "CREDENTIAL_KIND_API_KEY" · "CREDENTIAL_KIND_GCP_ADC"
type ApiKeyAuth
type ApiKeyAuth struct{ … }
Configuration for classic API-key authentication.
InlineSecret(string, optional, wireinlineSecret) — Secret stored directly in GoodMem (mutually exclusive with secretRef)SecretRef(models.SecretReference, optional, wiresecretRef) — Reference to an external secret manager entry (mutually exclusive with inlineSecret)HeaderName(string, optional, wireheaderName) — Desired HTTP header to carry the credential (defaults to Authorization)Prefix(string, optional, wireprefix) — Optional prefix prepended to the secret (e.g., "Bearer ")
type GcpAdcAuth
type GcpAdcAuth struct{ … }
Configuration for Google Application Default Credentials (ADC).
Scopes([]string, optional, wirescopes) — Additional OAuth scopes. Empty list falls back to the default cloud-platform scope.QuotaProjectID(string, optional, wirequotaProjectId) — Optional quota project used for billing
type SecretReference
type SecretReference struct{ … }
URI(string, wireuri) — URI identifying where the secret can be resolved (e.g., vault://, env://)Hints(map[string]string, optional, wirehints) — Optional metadata to help resolvers decode the secret (e.g., {"encoding":"base64"})
type GoodMemStatus
type GoodMemStatus struct{ … }
Warning or non-fatal status with granular codes (operation continues)
Code(string, wirecode) — Status code for the warning or informational messageMessage(string, wiremessage) — Human-readable status messageDetails(map[string]string, optional, wiredetails) — Additional contextual details
type ChunkingConfiguration
type ChunkingConfiguration struct{ … }
Configuration for text chunking strategy used when processing content. Exactly one of none, recursive, or sentence must be provided.
None(models.NoChunkingConfiguration, optional, wirenone) — No chunking strategy - preserve original content as single unitRecursive(models.RecursiveChunkingConfiguration, optional, wirerecursive) — Recursive hierarchical chunking strategy with configurable separatorsSentence(models.SentenceChunkingConfiguration, optional, wiresentence) — Sentence-based chunking strategy with language detection
type NoChunkingConfiguration
type NoChunkingConfiguration struct{ … }
No chunking strategy - preserves original content as a single unit
(no exported fields)
type RecursiveChunkingConfiguration
type RecursiveChunkingConfiguration struct{ … }
Recursive hierarchical chunking strategy with configurable separators and overlap
ChunkSize(int32, wirechunkSize) — Maximum size of a chunk (should be ≤ context window)ChunkOverlap(int32, wirechunkOverlap) — Sliding overlap between chunksSeparators([]string, optional, wireseparators) — Hierarchical separator list (order = preference)KeepStrategy(models.SeparatorKeepStrategy, wirekeepStrategy) — How to handle separators after splitting. KEEP_NONE is deprecated and behaves as KEEP_END.SeparatorIsRegex(bool, optional, wireseparatorIsRegex) — Whether separators are regex patternsLengthMeasurement(models.LengthMeasurement, wirelengthMeasurement) — How to measure chunk length
type SentenceChunkingConfiguration
type SentenceChunkingConfiguration struct{ … }
Sentence-based chunking strategy with language detection support
MaxChunkSize(int32, wiremaxChunkSize) — Maximum size of a chunkMinChunkSize(int32, wireminChunkSize) — Minimum size before creating a new chunkEnableLanguageDetection(bool, optional, wireenableLanguageDetection) — Whether to detect language for better segmentationLengthMeasurement(models.LengthMeasurement, wirelengthMeasurement) — How to measure chunk length
type SeparatorKeepStrategy
type SeparatorKeepStrategy string
Strategy for handling separators after text splitting. KEEP_NONE is deprecated and treated as KEEP_END.
String enum (type SeparatorKeepStrategy string): "KEEP_NONE" · "KEEP_START" · "KEEP_END"
type LengthMeasurement
type LengthMeasurement string
Strategy for measuring chunk length during text splitting
String enum (type LengthMeasurement string): "CHARACTER_COUNT" · "TOKEN_COUNT" · "CUSTOM"
type SortOrder
type SortOrder string
String enum (type SortOrder string): "ASCENDING" · "DESCENDING" · "SORT_ORDER_UNSPECIFIED"
Support
File issues against the GoodMem repository. The Go SDK is generated from the same universal API IR (api_ir.json) that drives the Python, Java and MCP SDKs, so the wire contract is identical across every language.