fleet-memory/hindsight-docs/docs/sdks/go.md
Eliah Rusin 2a47389f2c
feat: add Go client SDK with ogen code generation (#375)
Add a Go client for the Hindsight API using ogen for strongly-typed code
generation from the OpenAPI 3.1 spec. The client provides a high-level
wrapper with functional options around the generated code, covering all
core operations (retain, recall, reflect, bank management).

Includes:
- ogen-based code generation with OpenAPI 3.1 spec preprocessing
- High-level Client wrapper with idiomatic Go API
- Functional options for all operations (WithBudget, WithTags, etc.)
- OgenClient() escape hatch for advanced operations
- Integration tests and godoc examples
- Go SDK reference docs and cookbook entries (quickstart, concurrent
  pipeline, memory-augmented API service)
- Updated generate-clients.sh with Go generation step

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 11:35:40 +01:00

294 lines
7.7 KiB
Markdown

---
sidebar_position: 3
---
# Go Client
Official Go client for the Hindsight API, built on [ogen](https://github.com/ogen-go/ogen) for strongly-typed code generation from the OpenAPI 3.1 spec.
## Installation
```bash
go get github.com/vectorize-io/hindsight-client-go
```
Requires Go 1.25+.
## Quick Start
```go
package main
import (
"context"
"fmt"
"log"
hindsight "github.com/vectorize-io/hindsight-client-go"
)
func main() {
client, err := hindsight.New("http://localhost:8888")
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
// Retain a memory
client.Retain(ctx, "my-bank", "Alice works at Google")
// Recall memories
resp, _ := client.Recall(ctx, "my-bank", "What does Alice do?")
for _, r := range resp.Results {
fmt.Println(r.Text)
}
// Reflect - generate response with disposition
answer, _ := client.Reflect(ctx, "my-bank", "Tell me about Alice")
fmt.Println(answer.Text)
}
```
## Client Initialization
```go
import hindsight "github.com/vectorize-io/hindsight-client-go"
// Default client
client, err := hindsight.New("http://localhost:8888")
// With API key authentication
client, err := hindsight.New("http://localhost:8888",
hindsight.WithAPIKey("your-api-key"),
)
// With custom HTTP client
client, err := hindsight.New("http://localhost:8888",
hindsight.WithHTTPClient(&http.Client{Timeout: 30 * time.Second}),
)
```
## Core Operations
### Retain (Store Memory)
```go
// Simple
_, err := client.Retain(ctx, "my-bank", "Alice works at Google as a software engineer")
// With options
_, err := client.Retain(ctx, "my-bank", "Alice got promoted",
hindsight.WithContext("career update"),
hindsight.WithTimestamp(time.Date(2024, 1, 15, 10, 0, 0, 0, time.UTC)),
hindsight.WithDocumentID("conversation_001"),
hindsight.WithMetadata(map[string]string{"source": "slack"}),
hindsight.WithTags([]string{"career", "updates"}),
)
```
### Retain Batch
```go
items := []hindsight.MemoryItem{
{Content: "Alice works at Google"},
{Content: "Bob is a data scientist"},
}
_, err := client.RetainBatch(ctx, "my-bank", items,
hindsight.WithDocumentTags([]string{"team-info"}),
hindsight.WithAsync(false), // Set true for background processing
)
```
### Recall (Search)
```go
// Simple
resp, err := client.Recall(ctx, "my-bank", "What does Alice do?")
for _, r := range resp.Results {
fmt.Printf(" %s (type: %s)\n", r.Text, r.Type.Or("unknown"))
}
// With options
resp, err := client.Recall(ctx, "my-bank", "What does Alice do?",
hindsight.WithTypes([]string{"world", "experience"}), // Filter by fact type
hindsight.WithMaxTokens(4096),
hindsight.WithBudget(hindsight.BudgetHigh), // BudgetLow, BudgetMid, BudgetHigh
hindsight.WithTrace(true), // Include execution trace
hindsight.WithRecallTags([]string{"career"}),
hindsight.WithRecallTagsMatch(hindsight.TagsMatchAnyStrict),
)
```
### Reflect (Generate Response)
```go
resp, err := client.Reflect(ctx, "my-bank", "What should I know about Alice?",
hindsight.WithReflectBudget(hindsight.BudgetMid),
hindsight.WithReflectMaxTokens(2048),
)
fmt.Println(resp.Text) // Generated markdown response
```
### Reflect with Structured Output
```go
resp, err := client.Reflect(ctx, "my-bank",
"What programming language should I learn for data science?",
hindsight.WithResponseSchema(map[string]any{
"type": "object",
"properties": map[string]any{
"recommendation": map[string]any{"type": "string"},
"reasons": map[string]any{"type": "array", "items": map[string]any{"type": "string"}},
"confidence": map[string]any{"type": "string"},
},
"required": []any{"recommendation", "reasons"},
}),
hindsight.WithReflectMaxTokens(4096),
)
// resp.StructuredOutput contains the parsed JSON schema result
```
## Bank Management
### Create Bank
```go
_, err := client.CreateBank(ctx, "my-bank",
hindsight.WithBankName("Assistant"),
hindsight.WithMission("Helpful AI assistant tracking user preferences."),
hindsight.WithDisposition(hindsight.DispositionTraits{
Skepticism: 3, // 1-5: trusting to skeptical
Literalism: 3, // 1-5: flexible to literal
Empathy: 3, // 1-5: detached to empathetic
}),
)
```
### Other Bank Operations
```go
// Get bank profile
profile, err := client.GetBankProfile(ctx, "my-bank")
fmt.Println(profile.Mission)
// List all banks
banks, err := client.ListBanks(ctx)
for _, b := range banks.Banks {
fmt.Println(b.BankID)
}
// Update mission
_, err = client.SetMission(ctx, "my-bank", "New mission statement")
// Update disposition
_, err = client.UpdateDisposition(ctx, "my-bank", hindsight.DispositionTraits{
Skepticism: 4,
Literalism: 2,
Empathy: 5,
})
// Delete bank (destructive, cannot be undone)
err = client.DeleteBank(ctx, "my-bank")
```
## Tag Filtering
Tags provide visibility scoping for memories. Use them to partition memories within a bank.
```go
// Store tagged memories
client.Retain(ctx, "my-bank", "Project X meeting notes",
hindsight.WithTags([]string{"project_x", "meetings"}),
)
// Recall only project_x memories (strict - excludes untagged)
resp, _ := client.Recall(ctx, "my-bank", "What happened in meetings?",
hindsight.WithRecallTags([]string{"project_x"}),
hindsight.WithRecallTagsMatch(hindsight.TagsMatchAnyStrict),
)
// Reflect scoped to tags
resp, _ := client.Reflect(ctx, "my-bank", "Summarize project X",
hindsight.WithReflectTags([]string{"project_x"}),
hindsight.WithReflectTagsMatch(hindsight.TagsMatchAnyStrict),
)
```
| Match Mode | Behavior |
|-----------|----------|
| `TagsMatchAny` | OR matching, includes untagged memories |
| `TagsMatchAll` | AND matching, includes untagged memories |
| `TagsMatchAnyStrict` | OR matching, excludes untagged memories |
| `TagsMatchAllStrict` | AND matching, excludes untagged memories |
## Advanced Usage (ogen Client)
For operations not covered by the high-level wrapper (documents, entities, mental models, directives, operations), access the generated ogen client directly:
```go
import "github.com/vectorize-io/hindsight-client-go/internal/ogenapi"
ogen := client.OgenClient()
// List entities
entities, err := ogen.ListEntities(ctx, ogenapi.ListEntitiesParams{
BankID: "my-bank",
})
// Create a mental model
model, err := ogen.CreateMentalModel(ctx,
&ogenapi.CreateMentalModelRequest{
Name: ogenapi.NewOptString("User Preferences"),
SourceQuery: "What are this user's preferences and habits?",
},
ogenapi.CreateMentalModelParams{BankID: "my-bank"},
)
// Create a directive
directive, err := ogen.CreateDirective(ctx,
&ogenapi.CreateDirectiveRequest{
Name: "Response Style",
Content: "Always respond in a friendly, concise manner",
},
ogenapi.CreateDirectiveParams{BankID: "my-bank"},
)
// List operations (async tasks)
ops, err := ogen.ListOperations(ctx, ogenapi.ListOperationsParams{
BankID: "my-bank",
})
// Get bank stats
stats, err := ogen.GetAgentStats(ctx, ogenapi.GetAgentStatsParams{
BankID: "my-bank",
})
```
## Error Handling
The client returns standard Go errors. HTTP errors from the API are returned as ogen error types:
```go
resp, err := client.Recall(ctx, "nonexistent-bank", "query")
if err != nil {
// Handle error - could be network, HTTP 4xx/5xx, etc.
log.Printf("recall failed: %v", err)
}
```
## Code Generation
The Go client is built on [ogen](https://github.com/ogen-go/ogen). The generated code lives in `internal/ogenapi/` and provides full type safety with no `interface{}` or reflection.
To regenerate after API changes:
```bash
cd hindsight-clients/go
go generate ./...
go build ./...
```