Back ChatSnowflake() with the Cortex REST API: thin Anthropic/OpenAI provider subclasses, model-name dispatch, credentials-callable auth
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 176
- Forks
- 28
- Avg merge
- 18h 42m
- Merged PRs (30d)
- 16
Description
Proposal: back ChatSnowflake() with the Cortex REST API, delegating to AnthropicProvider/OpenAICompletionsProvider
Context
claude-sonnet-5 on Snowflake Cortex sends extended thinking blocks that the current SnowflakeProvider (built on snowflake-ml-python's CompleteRequest) never had to handle. Supporting them requires Snowflake-specific parsing/merging logic for thinking + signature fragments that duplicates what AnthropicProvider already does. Every future Anthropic (or OpenAI) feature Snowflake adopts — redacted thinking, interleaved thinking, server tools, new delta types — will require another patch against Snowflake's proprietary, undocumented streaming format, which the provider's own comments already flag as unstable. (Short-term fix for the immediate crash: branch fix/snowflake-anthropic-thinking-delta.)
The opportunity
Snowflake's Cortex REST API exposes two industry-standard endpoints:
| Chat Completions API | Messages API | |
|---|---|---|
| Compatibility | OpenAI Chat Completions | Anthropic Messages API |
| Endpoint | /api/v2/cortex/v1/chat/completions |
/api/v2/cortex/v1/messages |
| Models | All (Claude, OpenAI, Llama, Mistral, ...) | Claude only (incl. claude-sonnet-5) |
| SDK | openai |
anthropic |
Both are explicitly documented to work with the stock SDKs by overriding base_url and setting a Bearer token. The Messages API supports adaptive/extended thinking with signatures that round-trip in multi-turn conversations, proper SSE streaming, Anthropic-format tool calling, prompt caching, structured output, and anthropic-beta headers (interleaved thinking, effort, etc.).
Proposal
Combine two patterns already in chatlas:
Subclassing mechanics from BedrockMessagesProvider (chatlas/_provider_bedrock.py): thin subclasses that customize client construction and inherit everything else.
@no_file_management # no Files API on the gateway
class SnowflakeAnthropicProvider(AnthropicProvider):
"""Reaches Snowflake Cortex's Anthropic Messages API."""
# ~60 lines: anthropic.Anthropic with
# base_url="https://<account>.snowflakecomputing.com/api/v2/cortex"
class SnowflakeOpenAIProvider(OpenAICompletionsProvider):
"""Reaches Snowflake Cortex's OpenAI Chat Completions API."""
# base_url="https://<account>.snowflakecomputing.com/api/v2/cortex/v1"
Dispatch and auth ergonomics from ChatPosit (chatlas/_provider_posit.py):
- Dispatch by model name, not an
api=param.ChatPositselects its Anthropic vs OpenAI provider viamodel.startswith("claude"). Snowflake's endpoint coverage is cleanly partitioned by model family (Claude → Messages, everything else → Chat Completions), so unlike Bedrock — whereapi=exists because the APIs overlap in model coverage — no explicitapi=argument is needed. (An optional override could still force the legacy path during a transition period.) - A
credentials: Callable[[], str]parameter + an httpx auth flow that swaps the SDK's defaultx-api-keyheader forAuthorization: Bearer <token>— exactly what Snowflake requires, per its own docs. Because the callable is invoked per request, expiring tokens (OAuth, key-pair JWT) are naturally supported. One callable serves both REST flavors.
Benefits:
- All Anthropic/OpenAI thinking, tool-use, and streaming logic is inherited, not duplicated; future Snowflake-adopted features arrive for free.
- Thinking signatures round-trip correctly in multi-turn tool loops (the
CompleteRequestpath currently dropsContentThinkingwhen re-serializing history). - End state mirrors
ChatPosit: two thin provider subclasses plus auth, and thesnowflake-ml-pythondependency — along with its janky stream-merging code — can be deprecated rather than patched.
Open questions / costs
- Auth is the main work. The REST API needs a Bearer token: PAT (simplest for users), OAuth, or key-pair JWT (
X-Snowflake-Authorization-Token-Type: KEYPAIR_JWT; the header is optional since Snowflake sniffs token type). To preserve the currentconnections.toml/private_key_fileergonomics, chatlas should ship a default credentials helper that mints/refreshes a JWT from the existing connection params. Session tokens should be discouraged: their expiration surfaces as HTTP 200 with error code390112, which would need a response-body-inspecting error hook. - Observability differs: REST API calls don't write to
AI_OBSERVABILITY_EVENTS; usage moves toCORTEX_REST_API_USAGE_HISTORY. Worth documenting. - Transition plan: keep the legacy provider as the default initially, gate the new path behind opt-in (or new-model dispatch), and deprecate once the auth story is proven.
Related
- Short-term thinking-delta fix on the legacy path: branch
fix/snowflake-anthropic-thinking-delta
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read chatlas/_provider_bedrock.py and chatlas/_provider_posit.py first to compare subclass construction, model dispatch, and credentials handling. Then inspect the existing SnowflakeProvider and its tests or entry points, if present. Done means both Cortex REST API paths, callable Bearer authentication, dispatch, transition behavior, and documented observability differences are resolved and tested.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- ai, backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100