Skip to content
skyl

skyl API Reference

Every exported symbol in the core module, with signatures, caveats, and usage recipes.

This section documents the core skyl module: the client, the request and response types, the conversation model, streaming, and the error surface. Every page follows the same shape — Reference for the exact contract, Usage for what you actually do with it, Troubleshooting for what goes wrong.

Installing#

Terminal
go get github.com/BAGOMBEKA-JOB-DEV/skyl
import "github.com/BAGOMBEKA-JOB-DEV/skyl"
import "github.com/BAGOMBEKA-JOB-DEV/skyl"

The core module requires Go 1.22 or later and has zero external dependencies. Importing it pulls in no router, no logger, no vendor SDK.

The modules#

skyl is four Go modules in one repository. Which one a symbol lives in tells you what it costs you.

ModuleImport pathGoDependencies
skylgithub.com/BAGOMBEKA-JOB-DEV/skyl1.22noneThe core library. Zero external dependencies.
provider/anthropicgithub.com/BAGOMBEKA-JOB-DEV/skyl/provider/anthropic1.24anthropic-sdk-goA separate module, because the official SDK brings a dozen transitive dependencies.
gatewaygithub.com/BAGOMBEKA-JOB-DEV/skyl/gateway1.25go-chi/chi, skyl/otelThe optional HTTP service. Importing the core library never pulls in chi.
otelgithub.com/BAGOMBEKA-JOB-DEV/skyl/otel1.25go.opentelemetry.io/otelOpenTelemetry instrumentation. Nobody who does not want it pays for it.

The shape of the API#

Four concepts carry the whole library.

your code

skyl.Client

validation · retry/backoff · timeout · hooks

skyl.Provider

the seam — four methods

anthropic

api.anthropic.com

openai

api.openai.com

gemini

generativelanguage…

openaicompat

any OpenAI-shaped host

Everything cross-cutting lives in Client, so it is written and tested once.

Provider is the seam — four methods, small enough to implement in your own repository. Client wraps a provider and adds everything cross-cutting, so retry and validation are written once instead of once per vendor. Request and Response are the provider-agnostic shapes that travel between them.

Client#

SymbolSignature
Newfunc New(p Provider, opts ...Option) *Client
Client.Completefunc (c *Client) Complete(ctx, *Request) (*Response, error)
Client.Streamfunc (c *Client) Stream(ctx, *Request) (Stream, error)
Client.Modelsfunc (c *Client) Models(ctx) ([]ModelInfo, error)
Client.Providerfunc (c *Client) Provider() Provider

Options#

Every option is a func(*Client), applied in order by New.

OptionDefaultWhat it bounds
WithMaxRetries3How many times a retryable failure is retried
WithRetryDelay500ms / 30sskyl's own computed backoff
WithRetryAfterCap5mHow long a provider's Retry-After may delay a retry
WithTimeout10mA single attempt — not the whole retry sequence
WithHooknoneNothing; it registers an observer

Requests and responses#

FieldTypeDescription
ModelstringThe provider's model identifier, passed through untouched. skyl never validates it against a list, so a model released after your skyl build works immediately — and a typo surfaces as the provider's own not-found error rather than a local one.
Zero value: rejected by Validate: the model is required
SystemstringThe system prompt. Adapters place it where the provider expects — a top-level field for Anthropic, a leading message for OpenAI, systemInstruction for Gemini.
Zero value: no system prompt is sent
Messages[]MessageThe conversation so far. skyl does not police role ordering: providers disagree about what is legal, and rejecting a shape one vendor accepts would be skyl deciding something it has no business deciding.
Zero value: rejected by Validate: at least one message is required
MaxTokensintCaps the response length.
Zero value: the provider's default — which for Anthropic is an error, so skyl supplies 4096 there. A negative value is rejected by Validate.
Temperature*float64Sampling temperature. A non-nil value is always sent: several current reasoning models reject it outright, and skyl does not second-guess that, because silently dropping a field you set is worse than the provider’s own error.
Zero value: nil means the provider's default; leave it nil unless you mean it
TopP*float64Nucleus sampling. Same always-sent semantics as Temperature.
Zero value: nil means the provider's default
Stop[]stringSequences that end generation.
Zero value: no stop sequences
Tools[]ToolTools the model may call. A tool with no name is rejected by Validate.
Zero value: no tools offered
ToolChoice*ToolChoiceConstrains whether and how the model may call tools: auto, none, required, or a named tool. All four modes are mapped on all four adapters.
Zero value: nil means ToolChoiceAuto
Thinking*ThinkingRequests reasoning. A nil pointer and a zero value mean different things: nil is "provider default", &Thinking{} is "explicitly off".
Zero value: nil means the provider's default
ProviderOptionsmap[string]anyAn escape hatch: arbitrary vendor-specific fields merged into the outbound payload, overriding anything skyl set. skyl does not validate the contents — that is the point.
Zero value: nothing extra is sent

Errors#

skyl classifies every provider failure onto one of eight sentinels, so you branch with errors.Is rather than on message text.

SentinelMessageRetried?Meaning
ErrAuthskyl: authentication failedNeverThe credential was missing, malformed, or rejected. The same key will fail again.
ErrRateLimitskyl: rate limitedYesThe provider is throttling. Retried with backoff, honouring Retry-After.
ErrNotFoundskyl: not foundNeverThe model or endpoint does not exist for this account. Because model IDs pass through unvalidated, a typo arrives here rather than failing locally.
ErrBadRequestskyl: invalid requestNeverThe request was malformed. Often produced locally by Request.Validate.
ErrServerskyl: provider server errorYesThe provider failed on its side. Retried with backoff.
ErrUnsupportedskyl: unsupported by this providerNeverThis provider cannot express part of the request. Returned instead of silently dropping data, because a quietly discarded image looks like a model that ignored the question.
ErrRefusalskyl: model declined the requestNeverThe model or its safety classifiers declined. The same prompt gets the same answer.
ErrStreamClosedskyl: stream is closedNeverThe stream was used after being closed.

Full detail: Errors.

Escape hatches#

Two, always present, because every abstraction over a fast-moving API is wrong somewhere:

Edit this page on GitHub