SDKs
Node.js / TypeScript SDK
Cache any model. Crowkis is model-agnostic, wrap the call you already make to OpenAI, Anthropic, a local model, or whatever comes next, and Crowkis serves the repeats for free. Fully async, TypeScript typings included.
Install#
One command. The base client has no runtime dependencies.
npm install @crowkis/client
The one idea#
Crowkis doesn't care which model you call. You wrap the call you already make; Crowkis remembers the answer by meaning, so the next time someone asks the same thing in different words it's served instantly and for free.
Connect#
import { Crowkis } from "@crowkis/client";
const cache = new Crowkis({ host: "127.0.0.1", port: 6379, tenant: "my-app" });Cache any model, the wrapper#
cache.cached() wraps any async function whose first argument is the prompt, and matches on meaning, so rephrased prompts hit too. The function inside can call any provider.
const answer = cache.cached(
async (prompt: string) => myModel(prompt), // OpenAI, Claude, local, anything
{ ttl: 3600 },
);
await answer("How do refunds work?"); // miss → your model runs, result cached
await answer("What's the refund process?"); // semantic HIT → no model callCache any model, explicit form#
const text = await cache.ask(
"How do refunds work?",
async (prompt) => myModel(prompt), // any model
{ ttl: 3600 },
);Lookup & store directly#
const hit = await cache.lookup("what's the refund timeline?");
if (hit) {
console.log(hit.text, hit.similarity, hit.confidence);
} else {
await cache.store("what's the refund timeline?", "5-7 business days.", { ttl: 3600 });
}Streaming with async iteration#
for await (const chunk of cache.stream(
"Explain vector caches",
async (prompt) => myModelStream(prompt),
{ ttl: 3600 },
)) {
process.stdout.write(typeof chunk === "string" ? chunk : chunk.toString());
}LangChain.js#
Matches on meaning, so rephrased prompts hit, unlike an exact-match cache. Drops into LangChain's cache option, no chain changes.
import { CrowkisCache } from "@crowkis/client/langchain";
import { OpenAI } from "@langchain/openai";
const llm = new OpenAI({ cache: new CrowkisCache({ tenant: "my-app", ttl: 3600 }) });Agent memory#
Durable, semantic, per-user memory for agents (LangGraph.js or any loop). Every recall is scoped to its agent and user.
import { CrowkisMemory } from "@crowkis/client/memory";
const mem = new CrowkisMemory("support-bot", { user: "alice" });
await mem.remember("Alice prefers email over phone");
await mem.recall("how should I contact Alice?"); // semantic recallMethod reference#
Grouped by purpose. The high-level methods cover most apps; the rest are on the Crowkis client for direct control.
cache.cached(fn, { ttl, threshold }) // wrap any async model call in a semantic cache
cache.ask(prompt, compute, opts) // recall, else run compute() and cache it
cache.stream(prompt, compute, opts) // same, as an async iterator of chunks
cache.lookup(prompt) // → { text, similarity, confidence } | null
cache.store(prompt, answer, { ttl }) // write an answer for a prompt
cache.similar(prompt, { k }) // k most similar cached prompts
cache.embed(text) // raw embedding vector
cache.flush() // clear this tenant's cachemem.remember(fact, { ttl }) // store a fact
mem.recall(query, { k }) // semantic recall
mem.extract(conversation) // pull facts from a transcript
mem.history(query, { k }) // recall including superseded versions
mem.forget({ query }) // forget matching facts
mem.link(subj, rel, obj) // knowledge-graph edge
mem.graph(entity, { depth }) // walk the graphcache.csessionAdd(session, role, text) cache.csessionRecent(session, { n })
cache.cpin(query, answer) cache.cflag(query, badAnswer)
cache.cguard(text) cache.coutcheck(text)
cache.cbudgetSet(tenant, { dailyUsd }) cache.ckeylimitSet(tenant, { rpm })
cache.cpiiReport(tenant) cache.csave(dest) cache.creload()index.d.ts typings; the RESP reader handles partial and RESP3 push frames. Sensible timeout/retry/backoff defaults match the Python SDK. The embedding model lives server-side, so the client uses whatever model the server runs.