Seshat AIDocumentation

Documentation / SDK and API

Providers and authentication

Choose a model provider, point it at your own endpoint, set fallbacks, and manage keys and sign-in from your application.

A provider is a company or server that runs a model. Seshat talks to all of them through one interface, so changing provider is a change of configuration.

Choose a model

cfg := sdk.DefaultClientConfig()
cfg.Model = sdk.ModelIdentifier{
    Provider: sdk.APIProviderOpenAI,
    Model:    "gpt-5",
}

The provider constants are APIProviderAnthropic, APIProviderOpenAI, APIProviderMistral, APIProviderGemini, APIProviderDeepSeek, APIProviderOllama, APIProviderBedrock, APIProviderFoundry, APIProviderCodex, APIProviderMiniMax, APIProviderOpenCode and more. The full list of providers and models is in Configuration.

To discover what is available at run time, use the github.com/KPO-Tech/seshat-runtime/pkg/providers package:

info := providers.AllProvidersInfo()                 // every provider the runtime knows
models, err := providers.FetchModels(ctx, "ollama", providers.DefaultBaseURL("ollama"), "")

Keys

NewStoredCredentialResolver, one ready-made resolversdk.NewClient(cfg)the provider of cfg.ModelResolver gives a key ?Use the resolver keyCredentialResolver winsClientConfig.APIKeyalso used if the resolver failsEnvFirst: the variableof the provider, if setand EnvFirst is trueThe auth fileauth.json, or SESHAT_AUTH_PATHan API key or an OAuth tokenRefreshedan expired OAuth tokenwith its refresh tokenyesno, or no resolverelseOAuthThe stored resolver is one way to build a resolver.A server writes its own, one key per user.
A resolver that returns a key wins over APIKey. If the resolver fails, the failure is logged and APIKey is used.

Give the key in the config:

cfg.APIKey = os.Getenv("ANTHROPIC_API_KEY")

For a server that serves many users, implement CredentialResolver. It is asked for the key of a provider when the client is created, and its answer wins over APIKey:

type resolver struct{ db *DB }

func (r resolver) ResolveAPIKey(ctx context.Context, provider string) (string, error) {
    return r.db.KeyFor(ctx, currentUser(ctx), provider)
}

cfg.CredentialResolver = resolver{db}

For a desktop or command-line host, sdk.NewStoredCredentialResolver reads keys from the environment and from the local sign-in store:

cfg.CredentialResolver = sdk.NewStoredCredentialResolver(sdk.StoredCredentialResolverConfig{
    EnvFirst: true, // a variable in the environment wins over the stored key
})

Your own endpoint

Use ProviderConfig to point a provider at another base URL, add headers, or map model aliases. This is how you reach a gateway, a self-hosted server or an OpenAI-compatible service.

cfg.ProviderConfig = &providers.Config{
    Provider: sdk.APIProviderOpenAI,
    BaseURL:  "https://llm-gateway.internal.example/v1",
    CustomHeaders: map[string]string{"X-Team": "platform"},
}

providers.GetProviderConfig(provider) returns the defaults for a provider, a good starting point to copy.

Fallbacks

A provider configuration can name other models and providers to try when the first one fails. The loop tries the fallback models first (same provider), then the fallback providers. A circuit breaker stops calling a provider that keeps failing and tries it again after a delay.

By default, only models of the same provider are tried: for Anthropic, claude-3-5-sonnet and then claude-3-5-haiku. A prompt is never sent to another vendor unless you list one in Routing.FallbackProviders, so picking a provider is enough to keep your data with that provider.

Cross-vendor fallback is opt-in. Start from the defaults and add the providers you accept, or set the list to empty for none:

pc := providers.GetProviderConfig(sdk.APIProviderAnthropic)
if pc.Routing != nil {
    pc.Routing.FallbackModels = []sdk.ModelIdentifier{
        {Provider: sdk.APIProviderAnthropic, Model: "claude-3-5-haiku-20241022"},
    }
    pc.Routing.FallbackProviders = []sdk.APIProvider{sdk.APIProviderBedrock}
}
cfg.ProviderConfig = pc

Signing in with a ChatGPT subscription

Codex and OpenAI can use a ChatGPT subscription instead of an API key, through a device flow. The CLI does it with seshat login. From Go:

flow, err := sdk.NewOAuthDeviceFlow(sdk.OAuthDeviceFlowConfig{Provider: "codex", Persist: true})
if err != nil {
    log.Fatal(err)
}

challenge, err := flow.Start(ctx)          // show challenge.UserCode and challenge.VerificationURL
if err != nil {
    log.Fatal(err)
}
token, err := flow.Wait(ctx, challenge)    // blocks until the user has approved
if err != nil {
    log.Fatal(err)
}
if err := flow.SaveToken(ctx, token); err != nil {
    log.Fatal(err)
}

cfg.CredentialResolver = flow.CredentialResolver()

The resolver refreshes the access token when it expires.

Updated on 2026-10-14