Skip to content
Runic
English
Esc
navigateopen⌘Jpreview
On this page

Quickstart

Wire askRunic and storeResult into an existing agent in a few minutes.

Install

npm install @runic-labs/sdk
pnpm add @runic-labs/sdk
yarn add @runic-labs/sdk
bun add @runic-labs/sdk

@runic-labs/sdk depends on @runic-labs/cache and @runic-labs/ledger — you don’t need to install those separately unless you want to construct custom store instances yourself (see Cache and Ledger).

Wrap the call your agent already makes

Find the place in your agent where it turns a task into a call to an LLM or tool, and wrap it with askRunic / storeResult:

import { askRunic, storeResult } from "@runic-labs/sdk";

async function reviewFile(repo: string, file: string) {
  const decision = { intent: "review_code", params: { repo, file } };

  const cached = await askRunic(decision);
  if (cached) {
    console.log(`cache hit — saved ${cached.tokensSpent} tokens`);
    return cached.artifact;
  }

  const response = await callYourLLM(promptFor(repo, file));
  await storeResult(decision, response.text, response.tokensUsed);
  return response.text;
}

That’s the whole integration. No configuration is required to get started — askRunic/storeResult use a default file-backed store under .runic/ in your working directory.

Choosing intent and params

The signature is exact-match, so decide what actually makes two calls “the same decision” for your use case:

  • Good: { intent: "summarize_pr", params: { repo: "acme/widgets", pr: 482 } } — same repo, same PR number, same intent, every time this exact PR is asked about.
  • Bad: { intent: "summarize_pr", params: { prompt: fullPromptString } } — including the raw prompt text as a param means any wording change (even whitespace) produces a cache miss, defeating the point.

Put only the parameters that actually identify the decision in params. Leave prompt text, reasoning traces, and anything non-deterministic out of the signature entirely — see How it works for why.

Inspect what’s cached

npm install -g @runic-labs/cli
pnpm add -g @runic-labs/cli
npm install -g @runic-labs/cli
bun add -g @runic-labs/cli
runic cache status
runic ledger status

See CLI for full output examples.

Point at a different store location

By default, Runic writes to .runic/ in process.cwd(). Override it with an environment variable if your agent runs from a different working directory than where you want state to live:

RUNIC_HOME=/var/lib/my-agent/runic node agent.js

Use in-memory storage instead (tests, ephemeral runs)

import { createRunicClient } from "@runic-labs/sdk";
import { createCache, MemoryCacheStore } from "@runic-labs/cache";
import { createLedger, MemoryLedgerStore } from "@runic-labs/ledger";

const runic = createRunicClient({
  cache: createCache(new MemoryCacheStore()),
  ledger: createLedger(new MemoryLedgerStore()),
});

const cached = await runic.askRunic({ intent: "summarize_pr", params: { repo, pr } });

This is exactly what benchmarks/reuse-sweep and benchmarks/openrouter-savings use, so nothing persists between separate script runs.

Was this page helpful?