Go
Obstruo exposes an OpenAI-compatible API. The official openai-go package supports custom base URLs and works with Obstruo without modification.
Prerequisites
- An ObstruoKey and endpoint URL - see Quick Start
- A Logical Model configured in your project
- Go 1.21 or later
openai-go
Install the module:
Chat completions
package main
import (
"context"
"fmt"
"os"
"github.com/openai/openai-go"
"github.com/openai/openai-go/option"
)
func main() {
client := openai.NewClient(
option.WithAPIKey(os.Getenv("OBSTRUO_API_KEY")),
option.WithBaseURL(os.Getenv("OBSTRUO_BASE_URL")),
)
response, err := client.Chat.Completions.New(
context.Background(),
openai.ChatCompletionNewParams{
Model: "obstruo-chat",
Messages: []openai.ChatCompletionMessageParamUnion{
openai.SystemMessage("You are a helpful assistant."),
openai.UserMessage("Summarise this contract: ..."),
},
},
)
if err != nil {
panic(err)
}
fmt.Println(response.Choices[0].Message.Content)
}
Streaming
stream := client.Chat.Completions.NewStreaming(
context.Background(),
openai.ChatCompletionNewParams{
Model: "obstruo-chat",
Messages: []openai.ChatCompletionMessageParamUnion{
openai.UserMessage("Tell me a story."),
},
},
)
for stream.Next() {
chunk := stream.Current()
if len(chunk.Choices) > 0 {
fmt.Print(chunk.Choices[0].Delta.Content)
}
}
if err := stream.Err(); err != nil {
panic(err)
}
Embeddings
result, err := client.Embeddings.New(
context.Background(),
openai.EmbeddingNewParams{
Model: "obstruo-embedding",
Input: openai.EmbeddingNewParamsInputArrayOfStrings([]string{"The quick brown fox"}),
},
)
if err != nil {
panic(err)
}
vector := result.Data[0].Embedding
Environment variables
export OBSTRUO_API_KEY="your-obstruo-key"
export OBSTRUO_BASE_URL="https://api.obstruo.ai/your-org/v1"
client := openai.NewClient(
option.WithAPIKey(os.Getenv("OBSTRUO_API_KEY")),
option.WithBaseURL(os.Getenv("OBSTRUO_BASE_URL")),
)
Reading gateway metadata
openai-go deserialises only known OpenAI fields. For the obstruo key, make a raw HTTP call:
import (
"encoding/json"
"net/http"
"bytes"
)
type Routing struct {
ResolvedModel string `json:"resolved_model"`
ProviderType string `json:"provider_type"`
DurationMs int `json:"duration_ms"`
}
type Redaction struct {
TotalEntities int `json:"total_entities"`
ByCategory map[string]int `json:"by_category"`
DurationMs int `json:"duration_ms"`
}
type ObstruoMeta struct {
Routing Routing `json:"routing"`
Redaction Redaction `json:"redaction"`
}
type ObstruoResponse struct {
Choices []struct {
Message struct {
Content string `json:"content"`
} `json:"message"`
} `json:"choices"`
Obstruo ObstruoMeta `json:"obstruo"`
}
body, _ := json.Marshal(map[string]any{
"model": "obstruo-chat",
"messages": []map[string]string{{"role": "user", "content": "Hello!"}},
})
req, _ := http.NewRequest("POST",
os.Getenv("OBSTRUO_BASE_URL")+"/chat/completions",
bytes.NewReader(body),
)
req.Header.Set("Authorization", "Bearer "+os.Getenv("OBSTRUO_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
var parsed ObstruoResponse
json.NewDecoder(resp.Body).Decode(&parsed)
fmt.Println(parsed.Obstruo.Routing.ResolvedModel) // "gpt-4o-mini"
fmt.Println(parsed.Obstruo.Routing.ProviderType) // "OpenAI"
fmt.Println(parsed.Obstruo.Redaction.TotalEntities) // 0 = no PII found
fmt.Println(parsed.Obstruo.Redaction.ByCategory) // map[EMAIL_ADDRESS:1]
Next steps
- Configure PII redaction: Redaction
- Configure safety rules: Guardrails