Contextwaise

Contextwaise is in early access: API keys and the dashboard open at launch. Join the waitlist to get yours first.

Docs · Core API and events›
Agent SDK

Core API and events

The adapters (Vercel AI SDK, Anthropic, OpenAI) are thin layers over four methods. Use them directly to add Contextwaise to any agent loop, in TypeScript or Python.

Any framework#

Call shrink when a tool returns, and give the model its text instead of the raw output:

import { createContextwaise } from "contextwaise";

const cw = createContextwaise({ agent: "support-agent" });

for (const call of response.toolCalls) {
  cw.noteIntent(call.id, response.text); // what the model said before calling
  const output = await runTool(call);
  const view = await cw.shrink({ callId: call.id, tool: call.name, args: call.args, output });
  messages.push({ role: "tool", toolCallId: call.id, content: view.text });
}

Use the tool call's own id as callId. Asking again for the same id returns the same view, so rebuilding messages on later turns keeps them byte-identical.

Methods#

shrink(input)#

Returns the model's view of a tool result. Decided once per callId, then replayed.

callIdstringrequired

The tool call's id.

toolstringrequired

The tool's name. Selects its budget and groups results in the dashboard.

argsunknownrequired

The call's arguments, used to judge relevance.

outputunknownrequired

The raw result: a string, or any value (serialized as JSON).

noteIntent(callId, text)#

Records why the agent made a call: the text the model wrote before it, or the user's request. Call it before shrink. Arguments alone rarely say what the agent is looking for.

expand(ref, question?)#

Returns the original output behind a ref, or the parts of it that answer question. Expose it to your model as a tool so it can recover anything that was trimmed. Pass the input size of the model call that asked for it: an expand costs one more model call about that size, and the dashboard counts it against the savings (the adapters do this for you).

// Expose expand to your model as a tool. contextTokens: the input size of the model
// call that asked for it (your provider's usage), so the dashboard counts its cost.
async function expandTool({ ref, question }: { ref: string; question?: string }) {
  return cw.expand(ref, question, { contextTokens: response.usage.input_tokens });
}

flush()#

Sends pending dashboard reports now. Await it before a script or serverless function exits.

The result#

textstringrequired

What the model reads.

mode"full" | "shaped" | "trimmed"required

full: untouched. shaped: noise removed, fits the budget. trimmed: only the relevant parts kept.

refstringrequired

The reference to pass to expand.

kindstringrequired

The detected format: json, html, test, listing, log or text.

tokensBefore · tokensAfternumberrequired

Size of the raw output and of the view.

notesstring[]required

What cleanup did, in plain words.

sectionsarrayrequired

Each part of the output with its score, whether it was kept, and why.

Ledger#

The ledger keeps each original and its decision, so views can be replayed and expanded. The default lives in memory and holds the last 5,000 tool calls, which suits a single process. When an agent's steps can run in different processes, store it somewhere shared:

import type { Ledger } from "contextwaise";

const ledger: Ledger = {
  async get(callId) {
    const raw = await redis.get(`cw:ledger:${callId}`);
    return raw ? JSON.parse(raw) : undefined;
  },
  async set(callId, entry) {
    await redis.set(`cw:ledger:${callId}`, JSON.stringify(entry), { EX: 7 * 24 * 3600 });
  },
};

const cw = createContextwaise({ ledger });

Events#

onEvent receives every decision as it happens:

EventWhen
shrinkA result was decided: { callId, tool, result, ms }.
replayA known result was asked for again and replayed as is.
expandThe model asked for a trimmed part: { ref, question, tokens }.
engine_fallbackThe API couldn't judge a result's relevance, so the model got its cleaned output whole.
api_errorA call to the API failed, with a message.