How to
Generate Text and Structured Output
One-shot text, typed objects, and streamed completions with pkg/pi
Read this when
- Making your first generation call
- Getting a typed Go value back instead of prose
Set OPENAI_API_KEY, then run the first program.
pkg/catalog · pi
The prompt and the model spec are the same in all three calls. Only the shape of the answer changes: a message, a typed value, or a stream of deltas.
Generate text
This is the whole program. Every other block on this page is a fragment.
package main
import ( "context" "fmt" "log"
"github.com/sonnes/pi-go/pkg/ai" "github.com/sonnes/pi-go/pkg/pi")
func main() { prompt := pi.Prompt{ Messages: []pi.Message{ ai.UserMessage("Write one sentence about durable agents."), }, }
msg, err := pi.GenerateText( context.Background(), "openai-completions/gpt-5-mini", prompt, ai.WithMaxTokens(120), ) if err != nil { log.Fatal(err) }
fmt.Println(msg.JoinText(""))}pi.GenerateText resolves the model spec, runs the stream, and returns the final
assistant message.
Get a typed object back
type recipe struct { Title string `json:"title"` Ingredients []string `json:"ingredients"` Minutes int `json:"minutes"`}
result, err := pi.GenerateObject[recipe](ctx, "openai-completions/gpt-5-mini", prompt)
fmt.Println(result.Object.Title, result.Object.Minutes)pi.GenerateObject builds a JSON Schema from the Go type. The provider must
implement object generation.
Stream instead of waiting
stream := pi.StreamText(ctx, "openai-completions/gpt-5-mini", prompt)
for event, err := range stream.Events() { if event.Type == ai.EventTextDelta { fmt.Print(event.Delta) } // ... thinking_delta, tool_delta, text_end}
msg, err := stream.Wait() // the same final message, after the deltasfmt.Println(msg.StopReason)Read EventTextDelta for UI text. Call Wait after the range to get the final
message.
Pick a model
- Use a full spec when more than one provider is available.
openai-completions/gpt-5-miniusesOPENAI_API_KEY.openai-responses/gpt-5-miniusesOPENAI_OAUTH_TOKEN.anthropic-messages/claude-haiku-4-5uses Anthropic credentials.- A bare model ID works only when one registered provider serves it.
Next: Authenticate Providers.