OP

openrouter-caching-strategy

Strategies to cache deterministic LLM responses to improve performance and save costs.

Install

mkdir -p .claude/skills/openrouter-caching-strategy && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/7583" && unzip -o skill.zip -d .claude/skills/openrouter-caching-strategy && rm skill.zip

Installs to .claude/skills/openrouter-caching-strategy

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Implement caching for OpenRouter API responses to reduce cost and latency.
74 charsno explicit “when” trigger
Intermediate

Key capabilities

  • Cache deterministic OpenRouter API responses to reduce cost and latency
  • Implement in-memory caching with TTL expiry and hit/miss counters
  • Utilize persistent caching with Redis for multi-instance deployments
  • Design cache keys to include model ID, messages, and relevant parameters
  • use Anthropic prompt caching via OpenRouter for large system prompts

How it works

The skill intercepts OpenRouter API calls, generates a cache key from the request parameters, and checks if a cached response exists. If not, it makes the API call and stores the result in either an in-memory or Redis cache.

Inputs & outputs

You give it
OpenRouter API call messages, model, and kwargs with temperature=0
You get back
Cached completion payload or a direct API response if not cached

When to use openrouter-caching-strategy

  • Reduce AI API spend via response caching
  • Implement Redis-backed LLM result cache
  • Optimize latency for repeat queries
  • Manage caching for RAG systems

About this skill

OpenRouter Caching Strategy

Overview

OpenRouter charges per token, so caching identical or similar requests can dramatically cut costs. Deterministic requests (temperature=0) with the same model and messages produce identical outputs -- these are safe to cache. This skill covers in-memory caching, persistent caching with TTL, and Anthropic prompt caching via OpenRouter.

Prerequisites

  • An OpenRouter API key (sk-or-v1-...) exported as OPENROUTER_API_KEY — see the openrouter-install-auth skill for setup
  • Python 3.8+ with the OpenAI SDK, plus the redis client package for the persistent cache; Node.js 18+ with the OpenAI SDK for the TypeScript variant in the references
  • A Redis server reachable at localhost:6379 for Persistent Cache with Redis (the in-memory LLMCache needs no infrastructure)
  • Deterministic request settings — caching is only safe at temperature=0

Instructions

  1. Confirm the requests you want to cache are deterministic (temperature=0); non-zero temperatures produce different outputs each call and must never be cached.
  2. Start with the In-Memory Cache: LLMCache plus cached_completion() gives you TTL expiry and hit/miss counters in a single process.
  3. For multi-instance deployments, switch to Persistent Cache with Redis — redis_cached_completion() stores results under or:<sha256> keys with r.setex TTL expiry and falls through to a direct API call on a miss.
  4. Build keys per Cache Key Design: include the model ID (with variants like :floor), messages, temperature, max_tokens, and top_p; exclude stream and the HTTP-Referer/X-Title headers.
  5. For large static system prompts (RAG context), add cache_control: {"type": "ephemeral"} per Anthropic Prompt Caching via OpenRouter — cache reads bill at 0.1x the input rate.
  6. Wire the Cache Invalidation table: flush per-model keys on model version updates, flush everything on system prompt changes, and let TTL handle the rest.

In-Memory Cache

import os, hashlib, json, time
from typing import Optional
from openai import OpenAI

client = OpenAI(
    base_url="https://openrouter.ai/api/v1",
    api_key=os.environ["OPENROUTER_API_KEY"],
    default_headers={"HTTP-Referer": "https://my-app.com", "X-Title": "my-app"},
)

class LLMCache:
    def __init__(self, ttl_seconds: int = 3600):
        self._cache: dict[str, tuple[dict, float]] = {}
        self._ttl = ttl_seconds
        self.hits = 0
        self.misses = 0

    def _key(self, model: str, messages: list, **kwargs) -> str:
        blob = json.dumps({"model": model, "messages": messages, **kwargs}, sort_keys=True)
        return hashlib.sha256(blob.encode()).hexdigest()

    def get(self, model: str, messages: list, **kwargs) -> Optional[dict]:
        k = self._key(model, messages, **kwargs)
        if k in self._cache:
            data, ts = self._cache[k]
            if time.time() - ts < self._ttl:
                self.hits += 1
                return data
            del self._cache[k]
        self.misses += 1
        return None

    def set(self, model: str, messages: list, response: dict, **kwargs):
        k = self._key(model, messages, **kwargs)
        self._cache[k] = (response, time.time())

cache = LLMCache(ttl_seconds=1800)

def cached_completion(messages, model="anthropic/claude-3.5-sonnet", **kwargs):
    """Only cache deterministic requests (temperature=0)."""
    kwargs.setdefault("temperature", 0)
    kwargs.setdefault("max_tokens", 1024)

    cached = cache.get(model, messages, **kwargs)
    if cached:
        return cached

    response = client.chat.completions.create(model=model, messages=messages, **kwargs)
    result = {
        "content": response.choices[0].message.content,
        "model": response.model,
        "usage": {"prompt": response.usage.prompt_tokens, "completion": response.usage.completion_tokens},
    }
    cache.set(model, messages, result, **kwargs)
    return result

Persistent Cache with Redis

import redis, json, hashlib

r = redis.Redis(host="localhost", port=6379, db=0)

def redis_cached_completion(messages, model="openai/gpt-4o-mini", ttl=3600, **kwargs):
    """Cache in Redis with automatic TTL expiry."""
    kwargs["temperature"] = 0  # Must be deterministic
    key = f"or:{hashlib.sha256(json.dumps({'m': model, 'msgs': messages, **kwargs}, sort_keys=True).encode()).hexdigest()}"

    cached = r.get(key)
    if cached:
        return json.loads(cached)

    response = client.chat.completions.create(model=model, messages=messages, **kwargs)
    result = {
        "content": response.choices[0].message.content,
        "model": response.model,
        "tokens": response.usage.prompt_tokens + response.usage.completion_tokens,
    }
    r.setex(key, ttl, json.dumps(result))
    return result

Anthropic Prompt Caching via OpenRouter

Anthropic models on OpenRouter support prompt caching -- large system prompts are cached server-side, reducing input cost by 90% on cache hits.

# Mark large static content blocks with cache_control
response = client.chat.completions.create(
    model="anthropic/claude-3.5-sonnet",
    messages=[
        {
            "role": "system",
            "content": [
                {
                    "type": "text",
                    "text": "You are an expert. Here is the full source:\n" + large_context,
                    "cache_control": {"type": "ephemeral"},  # Cache this block
                }
            ],
        },
        {"role": "user", "content": "What does the main() function do?"},
    ],
    max_tokens=1024,
)
# First call: cache_creation_input_tokens charged at 1.25x
# Subsequent: cache_read_input_tokens charged at 0.1x (90% savings)

Cache Key Design

def cache_key(model: str, messages: list, **params) -> str:
    """Deterministic cache key. Include everything that affects output.

    Include: model ID (with variant like :floor), messages, temperature,
    max_tokens, top_p, transforms, provider routing.
    Exclude: stream (doesn't affect content), HTTP-Referer, X-Title.
    """
    canonical = json.dumps({
        "model": model, "messages": messages,
        "temperature": params.get("temperature", 0),
        "max_tokens": params.get("max_tokens"),
        "top_p": params.get("top_p"),
    }, sort_keys=True)
    return hashlib.sha256(canonical.encode()).hexdigest()

Cache Invalidation

TriggerActionWhy
Model version updateFlush keys for that modelNew version may give different outputs
System prompt changeFlush all keysOutput semantics changed
TTL expiryAutomatic evictionPrevents stale data
Manual purger.delete(key) or clear by prefixDebugging or policy change

Output

  • Cached completion payloads returned without an API round-trip: {"content", "model", "usage"} from the in-memory cache or {"content", "model", "tokens"} from Redis
  • Redis keys of the form or:<sha256-of-canonical-request> that expire automatically via TTL
  • Hit/miss counters and a hit_rate figure you can use to justify the caching infrastructure
  • On Anthropic models, cache_creation_input_tokens billed at 1.25x on the first call and cache_read_input_tokens at 0.1x (90% savings) on subsequent hits

Examples

Two identical deterministic calls through the ResponseCache from the references — the second returns instantly from cache:

result1 = cached_completion("What is Python?")   # [Cache MISS] key=3f8a92c1... (stored)
result2 = cached_completion("What is Python?")   # [Cache HIT] key=3f8a92c1...
print(f"Hit rate: {cache.hit_rate:.0%}")         # Hit rate: 50%

More worked examples, including a TypeScript Redis-style cache: references/examples.md.

Error Handling

ErrorCauseFix
Stale cache responseTTL too longReduce TTL or version cache keys
Cache miss stormCold start or invalidationWarm cache with common queries at deploy
Redis connection errorRedis downFall through to direct API call
Non-deterministic cachetemperature > 0 cachedOnly cache when temperature=0

Enterprise Considerations

  • Only cache deterministic requests (temperature=0) -- non-zero temperatures produce different outputs each time
  • Use Anthropic prompt caching for large system prompts (RAG context) -- 90% cost reduction on cache hits
  • Set TTL based on content freshness needs (30 min for dynamic, 24h for reference data)
  • Track cache hit rate to justify caching infrastructure cost
  • Use Redis or Memcached for multi-instance deployments; in-memory only works for single-process
  • Version cache keys when updating system prompts or switching model versions

References

When not to use it

  • When requests are non-deterministic (temperature > 0)

Prerequisites

An OpenRouter API key (sk-or-v1-...) exported as OPENROUTER_API_KEYPython 3.8+ with the OpenAI SDK, plus the redis client package for the persistent cacheA Redis server reachable at localhost:6379 for Persistent Cache with Redis

Limitations

  • Only cache deterministic requests (temperature=0)
  • Stale cache response if TTL is too long
  • Cache miss storm during cold start or after invalidation

How it compares

This skill provides specific caching strategies for OpenRouter API calls, including handling deterministic requests and use Anthropic's prompt caching, which is more specialized than generic caching solutions.

Compared to similar skills

openrouter-caching-strategy side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
openrouter-caching-strategy (this skill)124dReviewIntermediate
openrouter-streaming-setup124dReviewIntermediate
generating-grpc-services124dReviewAdvanced
etag04moNo flagsIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

More by jeremylongshore

View all by jeremylongshore

analyzing-logs

jeremylongshore

Analyze application logs to detect performance issues, identify error patterns, and improve stability by extracting key insights.

14123

ollama-setup

jeremylongshore

Configure auto-configure Ollama when user needs local LLM deployment, free AI alternatives, or wants to eliminate hosted API costs. Trigger phrases: "install ollama", "local AI", "free LLM", "self-hosted AI", "replace OpenAI", "no API costs". Use when appropriate context detected. Trigger with relevant phrases based on skill purpose.

1167

backtesting-trading-strategies

jeremylongshore

Backtest crypto and traditional trading strategies against historical data. Calculates performance metrics (Sharpe, Sortino, max drawdown), generates equity curves, and optimizes strategy parameters. Use when user wants to test a trading strategy, validate signals, or compare approaches. Trigger with phrases like "backtest strategy", "test trading strategy", "historical performance", "simulate trades", "optimize parameters", or "validate signals".

1071

generating-database-seed-data

jeremylongshore

Process this skill enables AI assistant to generate realistic test data and database seed scripts for development and testing environments. it uses faker libraries to create realistic data, maintains relational integrity, and allows configurable data volumes. u... Use when working with databases or data models. Trigger with phrases like 'database', 'query', or 'schema'.

1033

cursor-codebase-indexing

jeremylongshore

Execute set up and optimize Cursor codebase indexing. Triggers on "cursor index setup", "codebase indexing", "index codebase", "cursor semantic search". Use when working with cursor codebase indexing functionality. Trigger with phrases like "cursor codebase indexing", "cursor indexing", "cursor".

885

testing-mobile-apps

jeremylongshore

Execute mobile app testing on iOS and Android devices/simulators. Use when performing specialized testing. Trigger with phrases like "test mobile app", "run iOS tests", or "validate Android functionality".

810

You might also like

openrouter-streaming-setup

jeremylongshore

Implement streaming responses with OpenRouter. Use when building real-time chat interfaces or reducing time-to-first-token. Trigger with phrases like 'openrouter streaming', 'openrouter sse', 'stream response', 'real-time openrouter'.

111

generating-grpc-services

jeremylongshore

Generate gRPC service definitions, stubs, and implementations from Protocol Buffers. Use when creating high-performance gRPC services. Trigger with phrases like "generate gRPC service", "create gRPC API", or "build gRPC server".

13

etag

aalmada

Use this skill for any request involving HTTP ETags, conditional requests, or optimistic concurrency in REST APIs: implementing/explaining ETag headers, preventing lost updates, designing cache validation or conditional GET/PUT/DELETE, explaining If-Match, If-None-Match, 304 Not Modified, or 412 Pre

00

mcp-builder

anthropics

Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).

136215

telegram-bot-builder

davila7

Expert in building Telegram bots that solve real problems - from simple automation to complex AI-powered bots. Covers bot architecture, the Telegram Bot API, user experience, monetization strategies, and scaling bots to thousands of users. Use when: telegram bot, bot api, telegram automation, chat bot telegram, tg bot.

106130

stripe-integration

wshobson

Implement Stripe payment processing for robust, PCI-compliant payment flows including checkout, subscriptions, and webhooks. Use when integrating Stripe payments, building subscription systems, or implementing secure checkout flows.

48165

Search skills

Search the agent skills registry