Reference

Runtime SDK

@contexory/sdk resolves the release a label points at, so your agent runs on reviewed context without Contexory sitting in its request path.

Resolve a release

Call resolve with an agent and a label, authenticating with a runtime key.

// npm install @contexory/sdk
import { Contexory } from "@contexory/sdk";

const cx = new Contexory({ apiKey: process.env.CONTEXORY_API_TOKEN });
const ctx = await cx.resolve("support-agent", "production");

ctx.system;              // the release's system prompt
ctx.skills;              // pinned skill files
ctx.applyTools(myTools); // released tool descriptions

A runtime key belongs to the organization, is read-only, and is scoped to the agents you name. Do not use a personal token.

What resolve guarantees

Resolve is built to never be the reason an agent is down:

  • Cached. Releases are immutable, so they are held in memory in front of a disk cache (by content hash) and served without a request for the TTL, then revalidated with an ETag. Every read is verified against the signature again, memory included.
  • One request at a time. Concurrent calls for the same agent and label share a single request.
  • Never blocks on a refresh. Shortly after the TTL, the cached release is returned at once while a refresh runs in the background. A refresh that is refused or fails verification expires the cached release, so it is never served again: the next call asks Contexory and throws if the answer is still a refusal.
  • Last good release on failure. If Contexory is unreachable, times out, is rate limiting you or answers a server error, you get the last verified release marked stale. With nothing cached, it throws. A refusal (revoked key, unknown agent or label) throws too: the cache never overrides an answer.
  • Signed. Every response is verified with Ed25519 against the published signing keys, and cached releases are re-verified when read. A new key id triggers one discovery fetch, which is how rotation works.

A bad signature never falls back

A response that fails verification throws and is never cached. The SDK does not serve the cache instead, because tool descriptions are an injection channel into your agent and a bad signature means the channel is not to be trusted.

Options

Every option has a safe default.

OptionMeaning
apiKeyThe runtime key. Defaults to the CONTEXORY_API_TOKEN environment variable.
baseUrlThe Contexory API origin. Defaults to CONTEXORY_API_BASE, then the production API.
cacheDirWhere releases are cached. Defaults to CONTEXORY_CACHE_DIR, then a private directory under your home cache.
ttlMsHow long a cached release is served without asking Contexory. Defaults to the TTL Contexory sends, 60 seconds unless changed, with 10% jitter on each fetch.
staleWhileRevalidateMsHow long past the TTL a cached release is returned at once while a refresh runs. Default 30 seconds; 0 makes an expired release wait for the refresh.
timeoutMsHow long a request may take before the cache is used. Default 3 seconds. With nothing cached there is no fallback, so the first request gets 10 seconds.

How fast a label move arrives

Moving a label, whether a deploy or a rollback, reaches a running agent on its first resolve after the cached release expires: within the TTL, about a minute by default.

With revalidation in the background, a call right after the TTL can still return the old release while the refresh runs, so an agent that was idle can be up to the TTL plus the revalidation window behind, about 90 seconds by default. When a rollback must not wait, force a refresh.

// After moving a label, skip the cache and ask now.
const ctx = await cx.resolve("support-agent", "production", { forceRefresh: true });

Rate limits

The Contexory API limits how often one IP address can call it. The rate limits reference page has the current numbers.

A limited request gets 429 with Retry-After. The SDK treats a 429 as a transient failure: it serves the last good release marked stale, and does not ask again until Retry-After has passed. With nothing cached, it throws.

A cache hit makes no request and an unchanged release costs one 304, so one process stays far below any limit. Many servers behind one IP address add up: create the client once and reuse it, and raise ttlMs for a large fleet. To ask for a higher limit, email support@contexory.com.

Applying tool descriptions

applyTools puts the released tool descriptions onto your own tool objects.

// Vercel AI SDK 7: a record. OpenAI Agents SDK: an array.
const tools = ctx.applyTools(myTools);

// Opt in to a rename, then map the model's call back.
const renamed = ctx.applyTools(myTools, { renames: { issue_refund: "refund" } });
ctx.originalToolName("refund"); // "issue_refund"

It takes the Vercel AI SDK 7 tools record or the OpenAI Agents SDK tools array, and depends on neither package. By default it changes descriptions only. A rename is opt-in per tool, and the SDK keeps the map back so a call by the new name routes to the original.