npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@keemakr/agent-sdk

v0.9.0

Published

The floor for keemakr marketplace agents: verify the capability grant and reach tenant connections, memory, and shared platform tools through keemakr-core — without holding raw secrets or resolving the tenant yourself.

Downloads

1,332

Readme

@keemakr/agent-sdk

The floor for keemakr marketplace agents — separately deployed eve agents that the keemakr operator delegates to. The SDK gives your agent a stable, secure contract to:

  • verify the operator's capability grant on every inbound delegation, and
  • reach tenant connections (and, in later versions, memory and shared tools) through keemakr-core — without holding raw secrets and without resolving the tenant yourself.

The tenant identity and scopes come from a short-lived signed grant the operator mints per delegation; keemakr-core re-verifies the grant and enforces scope on every capability call. Connection credentials never leave keemakr-core on the default (proxy) path.

Install

npm install @keemakr/agent-sdk

Peer dependencies (match your eve agent): [email protected], jose@^6.2.3.

Configure

Set these in your deployed agent's environment:

| Variable | Purpose | | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | KEE_CORE_JWKS_URL | keemakr-core's JWKS endpoint, e.g. https://app.keemakr.com/.well-known/jwks.json. Enables grant verification. | | KEE_AGENT_AUDIENCE | This deployment's audience — your runtime URL's origin, e.g. https://my-agent.example.com. Must match the audience the operator mints. | | KEE_CORE_URL | keemakr-core's base URL for capability calls, e.g. https://app.keemakr.com. (Derived from KEE_CORE_JWKS_URL if unset.) |

If KEE_CORE_JWKS_URL is unset, grantAuth() skips entirely — useful during local development.

1. Verify the grant in your channel

grantAuth() returns an eve AuthFn. Put it ahead of any fallback:

import { localDev, vercelOidc } from 'eve/channels/auth';
import { eveChannel } from 'eve/channels/eve';
import { grantAuth } from '@keemakr/agent-sdk';

export default eveChannel({
  auth: [localDev(), vercelOidc(), grantAuth()],
});

On success the verified tenant id and scopes are attached to the session auth context, where useKee reads them.

2. Reach tenant data from a tool

import { defineTool } from 'eve/tools';
import { z } from 'zod';
import { useKee } from '@keemakr/agent-sdk';

export default defineTool({
  description: "Find a lead's work email.",
  inputSchema: z.object({
    domain: z.string(),
    first_name: z.string(),
    last_name: z.string(),
  }),
  async execute(args, ctx) {
    const kee = useKee(ctx);
    // Proxy path: the credential stays in keemakr-core; you get the result.
    const result = await kee.connections.hunter.call('email-finder', args);
    return result; // { email, score, status }
  },
});

Connections API

const kee = useKee(ctx);
kee.tenantId;            // the tenant this delegation is for (from the grant)
kee.scopes;              // the scopes the grant carries

// Proxy (default): run a named operation; the secret never leaves core.
await kee.connections.hunter.call("email-finder", { domain, first_name, last_name });
await kee.connections.get("hunter").call("email-finder", { ... }); // equivalent

// Token (opt-in): only if your entry.json declared `access: "token"` on the
// dependency. Returns a short-lived credential you may use directly.
const { access_token } = await kee.connections.hunter.token();

Discover connectors + operations

@keemakr/agent-sdk/connectors ships a generated, typed manifest of every connector keemakr-core exposes — provider slugs, maturity, and each operation's name + JSON-Schema arg contract. Use it to discover what's callable (and get autocomplete on provider + op names) without scanning a core checkout or hitting a running instance. It's metadata only — no credentials.

import { connectors, opNames, isReady } from '@keemakr/agent-sdk/connectors';

opNames('hunter'); // → ["email-finder"]
connectors.hunter.ops['email-finder'].inputSchema; // JSON Schema for the args
isReady('meta'); // false while a connector is coming_soon
connectors.meta.maturity; // "coming_soon" | "ready"

A coming_soon connector is declarable in your entry.json dependencies today; its operations start callable (and isReady flips to true) once core ships them — no change to your agent.

Refresh the manifest after core ships new connectors/operations (it's a committed snapshot of GET /api/connections/catalog):

curl -s "$KEE_CORE_URL/api/connections/catalog" > src/connectors.snapshot.json
npm run gen:connectors    # or: npm run build (runs gen first)

Memory (cross-session, tenant-shared)

await kee.memory.set('prefs', 'tone', { tone: 'formal' });
await kee.memory.get('prefs', 'tone'); // → { tone: "formal" }
await kee.memory.list('prefs'); // → entries in the namespace
await kee.memory.delete('prefs', 'tone');
// Semantic search by meaning (embeddings):
const hits = await kee.memory.search('how should I speak to the user?', { limit: 5 });
// → [{ namespace, key, value, score, … }]  (score 0–1, nearest first)

Memory is tenant-shared: any of the tenant's installed agents can read/write any namespace. Concurrent writers should take turns — every entry carries a monotonic version, and conditional writes lose gracefully instead of clobbering:

const entry = await kee.memory.getEntry('crm', 'lead:acme'); // { value, version, … }
try {
  await kee.memory.set('crm', 'lead:acme', next, { ifVersion: entry!.version });
} catch (e) {
  if (e instanceof MemoryConflictError) {
    // someone wrote first — e.current is the winning entry; re-read, re-derive, retry
  }
}
// Or merge one field with no read at all (object values only):
await kee.memory.patch('crm', 'lead:acme', { status: 'contacted' });

Use memory for your agent's own continuity (preferences, cursors, entity state) — durable documents belong in the tenant knowledge base, which you read via kee.kb.

Knowledge base (read-only retrieval)

const hits = await kee.kb.search('what is our refund policy?', { k: 5 });
// → [{ text, score, provenance: { title, source_uri, … } }]

Scoped server-side to the collections bound to your agent + the tenant's default corpus + the shared platform KB (kb:retrieve scope, granted to every install). Hybrid retrieval, reranked in core; text may be a wider parent context for clause-level documents.

Platform tools

await kee.tools.list(); // tools this grant is entitled to
await kee.tools.run('current-time'); // run one in keemakr-core

A call whose grant lacks the required scope returns a KeeError with status: 403; an expired/invalid grant returns status: 401.

Grant refresh (automatic since 0.8.0)

Every useKee capability call keeps its grant alive by itself: when the active token has under two minutes left, the SDK exchanges it at core's POST /api/capability/grant/refresh (single-flight per delegation — concurrent tool calls share one refresh), and a 401 grant_expired gets one refresh + one retry before surfacing. You write nothing; long runs simply stop dying at the TTL.

The floor is core's, not the SDK's: an expired grant can never be refreshed, scopes are re-derived from the install at each exchange, and the whole chain dies at the renewal horizon (CAPABILITY_GRANT_MAX_LIFETIME_SECONDS on core, default 6h) with a relayable grant_horizon_exceeded error.

Headless callers holding a raw grant can drive the exchange directly:

import { refreshGrant } from '@keemakr/agent-sdk';

const { token, exp } = await refreshGrant(currentToken); // throws KeeError when core refuses

refreshGrant resolves core from KEE_CORE_URL / KEE_CORE_JWKS_URL (pass { coreUrl } to override) and never verifies or signs anything locally — core is the only judge.

Autonomous / scheduled runs

A cron/scheduled turn has no operator session, so it gets no session grant. keemakr-core can mint a machine grant for it (gated on the tenant's per-install unattended_consent). If your remote runs outside an eve channel, verify that grant directly:

import { verifyGrant } from '@keemakr/agent-sdk';

const claims = await verifyGrant(grantToken, { audience: process.env.KEE_AGENT_AUDIENCE });
if (!claims) throw new Error('invalid or expired grant');
// claims.tenantId, claims.scopes, claims.aud, claims.exp

Inside an eve channel, grantAuth() already accepts machine grants (same token shape) — no extra work.

Credential & model contract

  • Tenant/service credentials live in keemakr-core, reached only via the proxy — the credential never crosses the wire. Tenant is always the verified grant, resolved server-side; never pass a tenant id from tool input.
  • The token path is opt-in and scope-gated (conn:<provider>:token), declared per dependency in entry.json ("access": "token").
  • You MAY hold your own model key. There is no platform model gateway today, so an agent routing its own LLM calls (its own Anthropic/AI-Gateway key) is expected and fine — that is not a credential leak. A leak is a tenant/service credential read in agent code.
  • Every capability call re-verifies the grant and enforces scope on the server.

Full contract: keemakr-core docs/CONNECTOR-CONTRACT.md.

License

MIT