Skip to content

The layers

catalog & pi — Wire It Together

Two ways to connect credentials, providers, and models: let pi decide, or own the registry with catalog

Read this when
  • Choosing between pkg/pi and pkg/catalog as your entry point
  • Understanding what a model spec string resolves against
  • Outgrowing environment-variable auto-detection

You can connect credentials, providers, models, and agents with pkg/pi or pkg/catalog.

pkg/catalog · piyour codepkg/aipkg/agentpkg/durable · session
fig. 01 — What a model spec resolves against

Both entry points fill the same registry. A spec string resolves to model metadata and one provider, which bind into an ai.LanguageModel. The agent layers build on that binding.

Let pi decide

// No registry, no provider construction: the first call detects both.
msg, err := pi.GenerateText(ctx, "openai-completions/gpt-5-mini", pi.Prompt{
Messages: []pi.Message{ai.UserMessage("Say hello.")},
})
a, err := pi.DurableAgent(ctx, "anthropic-messages/claude-sonnet-4-6",
durable.WithStore(store),
durable.WithSessionID("ticket-8472"),
)

The detection chain runs in this order, and the first match wins.

OrderSourceProvider ID
1ANTHROPIC_API_KEY or OAuth tokenanthropic-messages
2OPENROUTER_API_KEYopenai-responses
3OPENAI_OAUTH_TOKENopenai-responses
4OPENAI_API_KEYopenai-completions
5GOOGLE_API_KEYgoogle
pi.AddDetector(myStoredLogin) // higher priority, before the first resolution
d, err := pi.Detect("") // which source answered
fmt.Println(d.Name, d.Source)

GenerateText, GenerateObject, GenerateImage, GenerateSpeech, StreamText, Agent, and DurableAgent all run through the process-wide Default catalog.

Own the wiring with catalog

cat := catalog.New()
cat.RegisterTextProvider(openai.ID, prov, openai.Models()...)
cat.RegisterAgent("claude-cli", claude.Factory) // a spec prefix names a kind
// ... RegisterImageProvider, RegisterSpeechProvider, RegisterModel
model, err := cat.LanguageModel("openai-completions/gpt-5-mini")
a, err := cat.Agent("claude-cli/sonnet", agent.WithMaxTurns(20))

A Catalog keeps one provider map per capability — text, image, and speech — and one shared model index. Nothing is process-wide, so a test registry and a production registry can live in the same binary.

Move from pi to catalog

Move when you need more than auto-detection: several credentials for one provider, a custom base URL, a private provider, a test registry, or an explicit agent factory.

msg, err := pi.GenerateText(ctx, spec, prompt)
msg, err := cat.GenerateText(ctx, spec, prompt)

Your specs, prompts, and agent options do not change. You replace implicit registration with explicit registration.

Go deeper