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

@lakefrontai/sdk

v0.1.0

Published

Interceptor SDK for AI agents — tamper-evident evidence capture with zero added failure modes

Readme

@lakefrontai/sdk

TypeScript SDK for lakefrontai — tamper-evident evidence capture for AI agents.
Wraps any agent framework and intercepts actions before they execute. Adds <5ms overhead. Fails open.

Install

npm install @lakefrontai/sdk
# With LangChain support
npm install @lakefrontai/sdk @langchain/core
# With OpenAI support
npm install @lakefrontai/sdk openai

Quickstart

import { createInterceptor } from "@lakefrontai/sdk";

const lf = createInterceptor({
  apiKey: "lf_your_api_key",
  mandate: {
    mandateId:        "mnd_abc123",   // ID from the Lakefront Mandates UI
    agentId:          "payment-agent-v1",
    displayName:      "Payment Agent",
    authorizedScopes: ["payment.write", "payment.refund"],
    expiresAt:        1780000000000,  // unix ms — copied from the UI
    issuedBy:         "[email protected]",
  },
});

// Wait for startup mandate validation (optional — first action will surface errors too)
await lf.ready();

// 1. wrap() — drop-in replacement for any async function
const charge = lf.wrap(stripe.charges.create.bind(stripe.charges), {
  method:   "stripe.charges.create",
  category: "payment",
  extractArgs: (params) => ({
    amount:   params.amount,
    currency: params.currency,
  }),
});

const result = await charge({ amount: 2000, currency: "usd", source: "tok_visa" });
// ↑ The original function runs normally. Before and after are recorded
//   as a hash-chained evidence event. If lakefrontai's API is down,
//   the charge still completes — evidence is buffered locally.

// 2. @intercept decorator
class PaymentAgent {
  @lf.intercept({ method: "refund", category: "refund" })
  async refund(chargeId: string, amount: number) {
    return stripe.refunds.create({ charge: chargeId, amount });
  }
}

// 3. trace() — for streaming / manual flows
const finish = lf.trace("openai.chat", "api_call", { model: "gpt-4" });
const response = await openai.chat.completions.create({ ... });
finish({ result: response });

// Flush before process exit
await lf.flush();
lf.shutdown();

Mandate enforcement

Mandates are created in the Lakefront dashboard and enforced by the SDK at three levels:

1 · Startup validation

On createInterceptor(), the SDK fetches the mandate from the server and verifies it:

try {
  const lf = createInterceptor({ apiKey, mandate });
  await lf.ready(); // throws if revoked or expired
} catch (err) {
  if (err instanceof MandateRevokedError) { /* mandate was revoked in the UI */ }
  if (err instanceof MandateExpiredError) { /* mandate past its expiry date */ }
}

If the API is unreachable at startup, the SDK fails open — the agent starts and uses the locally supplied mandate values.

2 · Per-call scope check

Before every wrap() / intercept() / trace() / wrapSync() call, the SDK checks that the action's category is covered by authorizedScopes:

| Category | Required scope | |---|---| | payment | payment.write | | refund | payment.refund | | auth | auth.write | | data_access | data.read | | api_call | data.read | | tool_use | data.read | | decision | data.read |

import { MandateScopeError } from "@lakefrontai/sdk";

// If the mandate only has ["payment.write"] and the agent tries:
lf.wrap(deleteUser, { method: "deleteUser", category: "data_access" });
// → MandateScopeError: Mandate mnd_abc123 does not permit category "data_access".
//   Allowed: payment.write

Control what happens on a scope violation:

createInterceptor({
  // ...
  onScopeViolation: "throw",  // default — blocks the action
  onScopeViolation: "warn",   // logs a warning, action proceeds
  onScopeViolation: "allow",  // silently permits (audit-only mode)
});

3 · Background re-validation

Every 5 minutes (configurable), the SDK re-fetches the mandate from the server. If a compliance officer revokes the mandate in the UI, the running agent will refuse new actions within one refresh interval — no restart required.

createInterceptor({
  // ...
  mandateRefreshMs: 60_000, // re-validate every 60s
  mandateRefreshMs: 0,      // disable background refresh
});

Error types

import {
  MandateExpiredError,  // mandate.expiresAt is in the past
  MandateRevokedError,  // mandate was revoked via the dashboard or API
  MandateScopeError,    // action category not in authorizedScopes
} from "@lakefrontai/sdk";

Getting a mandate ID

  1. Go to Dashboard → Mandates → New mandate
  2. Set the agent ID, authorized scopes, spending limit, and expiry
  3. Click Create mandate
  4. Expand the row → copy the ready-to-paste SDK snippet

LangChain

import { LakefrontCallbackHandler } from "@lakefrontai/sdk/langchain";

const handler = new LakefrontCallbackHandler({ apiKey, mandate });
const executor = new AgentExecutor({ agent, tools, callbacks: [handler] });
await executor.invoke({ input: "charge $20 to card on file" });

OpenAI Assistants

import { wrapOpenAI, pollRunToCompletion } from "@lakefrontai/sdk/openai";

const openai = wrapOpenAI(new OpenAI({ apiKey: "sk-..." }), lfConfig);
// Now every chat.completions.create and runs.create is intercepted

const run = await openai.beta.threads.runs.create(threadId, { assistant_id });
const done = await pollRunToCompletion(openai, lf, threadId, run.id);

CrewAI (TypeScript)

import { wrapCrewTools } from "@lakefrontai/sdk/crewai";

const tools = wrapCrewTools([searchTool, calculatorTool], lfConfig);
const crew  = new Crew({ agents, tasks, tools });

Fail-open behaviour

| Scenario | Agent behaviour | Evidence | |---|---|---| | lakefrontai API up | Normal | Written immediately | | lakefrontai API down | Normal ✓ | Buffered in memory, retried every 2s | | API down > buffer full | Normal ✓ | Spilled to /tmp/lf_buffer_*.ndjson | | Filesystem also down | Normal ✓ | onDropped callback fired |

Mandate enforcement uses cached state — if the refresh call fails, the agent keeps running with the last-known mandate until the next successful fetch. Only a hard MandateExpiredError or MandateRevokedError at startup blocks the agent.

Latency budget

| Phase | Time added | |---|---| | Pre-action capture | ~0.5ms | | Enqueue to buffer | ~0.3ms | | Scope check (cached) | <0.1ms | | Total hot-path | < 5ms | | Mandate re-validation | async, never blocks |

Configuration reference

createInterceptor({
  apiKey:            "lf_...",          // required
  mandate:           { ... },           // required — from Mandates UI
  apiUrl:            "https://...",     // default: http://localhost:3001
  sessionId:         undefined,         // auto-generated as "<pid>-<random>"
  bufferSize:        200,               // max events before spill to file
  flushIntervalMs:   2_000,            // background drain frequency
  bufferPath:        undefined,         // file path for crash-safe spill
  onDropped:         undefined,         // called on irrecoverable event drop
  attestationToken:  undefined,         // Ed25519 token for Layer 3 attestation
  mandateRefreshMs:  300_000,          // how often to re-validate mandate (ms)
  onScopeViolation:  "throw",          // "throw" | "warn" | "allow"
});

Horizontal scaling

Rule: one LakefrontInterceptor instance per worker process. Never share a sessionId across workers.

The hash chain is computed locally per interceptor. If two processes write to the same sessionId, their sequence numbers will collide and chain verification will fail.

// ✅ Each worker gets its own session — use transaction_id to group them
const lf = createInterceptor({
  apiKey: "lf_...",
  mandate,
  // sessionId auto-generated as `<pid>-<random>` — unique per process
});

// Link sessions to a payment by passing transaction_id when opening a dispute:
// POST /disputes { session_id: lf.sessionId, transaction_id: "pi_xxx", ... }
// ❌ Never do this across workers
const SHARED_SESSION = "order-789";
// Worker 1: createInterceptor({ sessionId: SHARED_SESSION }) ← collision
// Worker 2: createInterceptor({ sessionId: SHARED_SESSION }) ← collision

If you need to correlate evidence across multiple parallel agents working on the same payment, use transaction_id / payment_intent_id on the dispute — that field exists precisely for this purpose.