Every abstraction over a fast-moving API is wrong somewhere. If skyl's Request
cannot express the thing you need, skyl must not be what stops you.
The rule#
Two escape hatches, always present.
| Direction | Hatch | Guarantee |
|---|---|---|
| Send | Request.ProviderOptions | Arbitrary vendor fields, merged into the payload, overriding anything skyl set. |
| Read | Response.Raw | Always populated. Every adapter, every call. |
You should never have to fork skyl to use a provider feature. If you do, that is a bug worth reporting.
Why Raw is unconditional#
Deep diveAn option would make it absent exactly when it matters
The moment you need Raw is the moment something has already gone wrong — a
field is missing, a count looks off, a provider shipped something new — and that
is exactly when you cannot go back and re-run the request with a flag set.
The cost is a few kilobytes per response. The benefit is that skyl's abstraction can never trap you.
The gateway makes the opposite trade (SKYL_INCLUDE_RAW defaults off),
because there the body crosses a network boundary and can echo request content
back to a caller who should not see it. Same data, different trust boundary,
different default — which is itself an example of the rule being applied rather
than recited.
What it cost#
ProviderOptions had to be honoured by every adapter, and once was not:
provider/anthropic silently ignored it entirely, leaving cache_control,
top_k and every beta feature unreachable there with no workaround at all.
The fix was not just the code. The shared contract suite now asserts that every adapter honours it, so the rule cannot be met by one adapter and quietly missed by another.
The seam is escapable too#
The rule extends past the request. Provider is
four methods, so:
- You can decorate an adapter — caching, circuit breaking, request
rewriting — and still get retry and hooks by passing the result to
skyl.New. - You can replace it entirely with your own adapter, in your own repository, and inherit everything.
- You can bypass
ClientwithClient.Provider()when you want none of it.