APIShift Docs
Same-provider API key pooling for LLM apps with adaptive key rotation, cooldown-aware retries, and optional cross-provider fallback. Available for Python and TypeScript/Node.js.
pip install APIShiftnpm install @apishift/corePython Quick Start
Install from PyPI and set up a same-provider key pool in under 10 lines.
Providers
All providers extend LLMProvider and expose a normalized chat interface with per-key rotation and cooldown tracking.
Retry-After header (or key_cooldown_seconds, default 60s). The next healthy key is selected automatically.priority values are tried first.discover_openrouter_models=True to query the OpenRouter API for all currently zero-priced models at runtime instead of using hardcoded defaults.Streaming
send_message_streamreturns an iterator that yields string chunks. Failover happens before the first chunk is yielded ("peeking" strategy).
RAG & Persistent Memory
APIShift optionally supports FAISS-backed retrieval and JSONL-based persistent memory.
Context Packing
Before each provider call, APIShift compiles messages into a token budget using pack_messages_to_token_budget.
Exceptions
All exceptions inherit from MultiLLMManagerError.
Python API Reference
Complete constructor signatures and method reference.
Conversation.__init__
Methods
- →
from_gemini_key_pool(api_keys, **kwargs)Create the primary same-provider Gemini key-pool setup. - →
send_message(message, **kwargs) → strSend a message and get a full response. Key rotation and fallback are automatic. - →
send_message_stream(message, **kwargs) → Iterator[str]Stream a response. Pre-yield failover on rate limits. - →
add_to_faiss(message)Index text into the optional FAISS store for retrieval. - →
retrieve_context(query, top_k) → List[str]Retrieve semantically relevant stored snippets. - →
get_history() → List[Dict]Return a copy of the conversation history. - →
get_compiled_context() → List[Dict]Inspect the exact messages that will be sent on the next call. - →
clear_history()Clear history, summary, FAISS index, and memory store. - →
add_provider(provider)Add a provider at runtime. Re-sorts by free/priority.
TypeScript Quick Start
@apishift/core integrates with the Vercel AI SDK. Pass any LanguageModelV1 instance.
APIShift Class (TS)
The orchestrator wraps generateText and streamText from the Vercel AI SDK, adding same-provider key pools, cooldowns, fallback, and context management.
Constructor: new APIShift(models, options?)
| models | Array<LanguageModel | ModelEntry> | Required | Model instances with optional routing metadata |
| systemPrompt | string | '' | Static system instructions |
| maxHistoryLength | number | 20 | Max recent messages kept |
| summaryMaxChars | number | 4000 | Max summary length |
| defaultCooldownMs | number | 60000 | Default cooldown per model/key entry |
| keyStrategy | string | 'adaptive' | adaptive, round_robin, or sticky |
| routingStrategy | string | 'same_provider_first' | Try all healthy keys in a provider pool before fallback |
| maxContextTokens | number | 6000 | Token budget per call |
| memoryStore | PersistentMemoryStore | undefined | JSONL or custom persistence |
TypeScript Streaming
Use streamMessage for context-preserving streaming, or streamText for stateless failover.
TypeScript Memory
Use JsonMemoryStore for JSONL-based persistence, or implement the PersistentMemoryStore interface for custom backends.
TypeScript API Reference
- →
generateText(params) → PromiseStateless text generation with failover. Omit the model parameter. - →
streamText(params) → PromiseStateless streaming with failover. First-chunk peeking strategy. - →
sendMessage(content, params?) → PromiseContext-preserving generation. History and summary managed automatically. - →
streamMessage(content, params?) → PromiseContext-preserving streaming. Chunks are auto-saved on stream completion. - →
getHistory() → Promise<ModelMessage[]>Return the current conversation history. - →
getCompiledContext() → Promise<ModelMessage[]>Inspect the compiled messages for the next call. - →
clearHistory() → Promise<void>Clear history, summary, and memory store. - →
lastRoute: RouteInfo | undefinedInfo about the last successful route (name, attempts, cooldown).
Architecture
How the same-provider key pool and fallback pipeline works internally.
FAQ
- ?What happens if all keys are rate-limited?NoAvailableProvidersError is raised. Keys recover automatically after their cooldown period expires.
- ?Does failover work mid-stream?Only before the first chunk is yielded (pre-yield failover). Once bytes reach the caller, mid-stream errors are raised directly — restarting would duplicate/garble output.
- ?Can I add fallback providers at runtime?Yes. Call conversation.add_provider(provider). It is sorted after the primary pool based on free and priority metadata.
- ?How does OpenRouter model discovery work?APIShift queries the OpenRouter /api/v1/models endpoint for models with zero prompt and completion pricing. Falls back to hardcoded defaults if the network request fails.
- ?What's the token counting accuracy?The default counter uses ~4 chars/token heuristic. It's fast and dependency-free. For exact counts, pass a custom token_counter (e.g., tiktoken) via the constructor.
- ?Can I use APIShift without the Vercel AI SDK?Python: Yes, it's standalone. TypeScript: The orchestrator wraps generateText/streamText from the Vercel AI SDK, so that dependency is required.
- ?Is FAISS required?No. RAG is completely optional. Without faiss-cpu and sentence-transformers, APIShift works identically — just without semantic retrieval.