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

@agentlattice/sdk

v0.2.0

Published

AgentLattice SDK — governance-aware AI agent actions

Readme

@agentlattice/sdk

Governance SDK for AI agents. Every action your agent takes goes through AgentLattice's audit trail, policy engine, and approval gates.

Install

npm install @agentlattice/sdk

Requires Node.js >=14.17.0.

Method Inventory

Core

| Capability | Method | Usage | Details | |-----------|--------|-------|---------| | Execute action | al.execute(actionType, opts?) | await al.execute("pr.open") | Reference | | Gate (block until approved) | al.gate(actionType, opts?) | await al.gate("pr.merge") | Reference |

Managed Agents

| Capability | Method | Usage | Details | |-----------|--------|-------|---------| | Govern a managed agent | al.govern(agentId, message, opts?) | await al.govern("agent_011Ca...", "Analyze this report") | Reference |

Delegation

| Capability | Method | Usage | Details | |-----------|--------|-------|---------| | Delegate sub-agent | al.delegate(name, opts, cb) | await al.delegate("reader", { capabilities: [...], ttl: 300 }, async (sub) => { ... }) | Reference | | Parallel fan-out | AgentLattice.parallel([...]) | await AgentLattice.parallel([al.delegate(...), al.delegate(...)]) | Reference | | Execute as child | sub.execute(actionType, opts?) | await sub.execute("read_data") | Reference | | Gate as child | sub.gate(actionType, opts?) | await sub.gate("read_data") | Reference | | Chain delegation | sub.delegate(name, opts, cb) | await sub.delegate("sub-reader", { capabilities: [...], ttl: 60 }, async (s) => { ... }) | Reference |

Types & Errors

| Export | Description | Details | |--------|-------------|---------| | ActionResult | Return type of execute() — status, audit ID, conditions | Reference | | ActionOptions | Options for execute() and gate() — data_accessed, metadata, event_id | Reference | | AgentLatticeError | Base error — code, message, details | Reference | | AgentLatticeDeniedError | Policy denial or reviewer rejection — reason, policy, conditions | Reference | | AgentLatticeTimeoutError | Approval window expired — approvalId | Reference |


Quickstart

import { AgentLattice } from "@agentlattice/sdk";

const al = new AgentLattice({ apiKey: process.env.AL_API_KEY! });

// gate() blocks until a human approves (or throws if denied/timed out)
await al.gate("pr.merge");

// Your agent code only runs if the action was approved
await mergePR(42);

With richer context for risk scoring:

await al.gate("pr.merge", {
  data_accessed: [
    { type: "source_code", count: 142, sensitivity: "medium" },
  ],
  metadata: { pr_number: 42, repo: "acme/backend" },
});

API Reference

new AgentLattice(config)

| Field | Required | Default | Description | |-------|----------|---------|-------------| | apiKey | Yes | — | Bearer token from your operator config | | baseUrl | No | https://www.agentlattice.io | Override for self-hosted or staging | | gatePollTimeoutMs | No | 8 * 60 * 60 * 1000 (8 hours) | How long gate() polls for approval | | gatePollIntervalMs | No | 5000 (5 seconds) | How often to check approval status |


al.govern(agentId, message, options?)

Run a governed Anthropic Managed Agent session. Requires @anthropic-ai/sdk as a peer dependency.

const al = new AgentLattice({
  apiKey: process.env.AL_API_KEY,
  anthropicApiKey: process.env.ANTHROPIC_API_KEY,
});

const result = await al.govern("agent_011Ca...", "Analyze this earnings report", {
  onToolCall: (tool) => console.log(`Tool: ${tool.name}`),
  onDecision: (d) => console.log(`${d.allowed ? "Allowed" : "Denied"}: ${d.actionType}`),
  onMessage: (text) => console.log(`Agent: ${text}`),
  failOpen: false, // default: deny if AL unreachable
});

console.log(result.output);     // Agent's text response
console.log(result.decisions);  // Per-tool governance decisions
console.log(result.sessionId);  // Anthropic session ID

Returns GovernResult with output, decisions (array of GovernDecision), sessionId, environmentId, and completed.

Pass sessionId and environmentId in options to reuse an existing Anthropic session instead of creating one.

See Managed Agents guide for full setup instructions.


al.gate(actionType, options?)

Blocks until the action is approved. Returns void on approval.

Throws on denial or timeout — use a try/catch to handle gracefully:

try {
  await al.gate("pr.merge", { metadata: { pr_number: 42 } });
  await mergePR(42);
} catch (e) {
  if (e instanceof AgentLatticeDeniedError) {
    // Denied — could be a policy rule or a human reviewer
    console.log(`Denied: ${e.reason}`);             // "CONDITIONS_DENIED" or "DENIED_BY_REVIEWER"
    console.log(`Policy: ${e.policy}`);              // "PR merge policy"
    console.log(`Failed rules:`, e.conditions);      // [{field:"pr_size", operator:"lt", expected:100, result:false}]
  } else if (e instanceof AgentLatticeTimeoutError) {
    // Approval window expired — log and abort
    console.log(`Approval timed out (id: ${e.approvalId})`);
  }
}

al.execute(actionType, options?)

Submit an action and return immediately without waiting for approval. Use this for logging or when you don't need to block.

Returns ActionResult:

type ActionResult = {
  status: "executed" | "requested" | "denied" | "timed_out" | "policy_not_found";
  audit_event_id: string;
  approval_id?: string;      // set when status is "requested" — poll this to check resolution
  denial_reason?: string;    // set when status is "denied" — e.g. "CONDITIONS_DENIED"
  policy_name?: string;      // the policy that governs this action type
  conditions_evaluated?: Array<{
    field: string;
    operator: string;
    expected: unknown;
    result: boolean;         // false = this rule failed
  }>;
};

Options

interface ActionOptions {
  resource?: string;  // target of the action: URL, table name, file path, API endpoint.
                      // used for resource-scoped policies (e.g., allow web.query only for linkedin.com)
  data_accessed?: Array<{
    type: string;    // what kind of resource: "source_code" | "database" | "external_api" |
                     //   "user_data" | "credentials" | "filesystem" | "network_request"
    count: number;   // how many records/files/rows accessed
    sensitivity: "low" | "medium" | "high" | "critical";
  }>;
  metadata?: Record<string, unknown>;  // arbitrary context (pr_number, repo, filename...)
  event_id?: string;  // idempotency key — duplicate submissions with the same key return
                      // the existing audit record without creating a new one. Pass a
                      // stable ID (e.g. task ID) when your agent might retry.
}

Error classes

// Thrown by gate() when a policy rule fires or a reviewer declines
class AgentLatticeDeniedError extends AgentLatticeError {
  approvalId?: string;   // present for reviewer-denied actions, absent for policy denials
  reason?: string;       // "CONDITIONS_DENIED" | "POLICY_TAMPERED" | "DENIED_BY_REVIEWER"
  policy?: string;       // policy name that governed this action
  conditions?: Array<{ field: string; operator: string; expected: unknown; result: boolean }>;
}

// Thrown by gate() when the approval window expires before a decision
class AgentLatticeTimeoutError extends AgentLatticeError {
  approvalId: string;
}

// Base class — check error.code for programmatic handling
class AgentLatticeError extends Error {
  code: string;    // "MISSING_API_KEY" | "POLICY_NOT_FOUND" | "API_ERROR" | ...
  details?: unknown;
}

Delegation — Scoped Sub-Agents

Create short-lived child agents with narrowed capabilities. Cleanup is automatic.

const result = await al.delegate("data-processor", {
  capabilities: ["read_data", "write_results"],
  ttl: 300,  // seconds
}, async (sub) => {
  await sub.execute("read_data", { metadata: { rows: 100 } });
  return sub.execute("write_results");
});

al.delegate(name, options, callback)

| Field | Required | Description | |-------|----------|-------------| | name | Yes | Display name for the ephemeral child agent | | options.capabilities | Yes | Array of action types the child can perform (must be subset of parent's) | | options.ttl | Yes | Time-to-live in seconds (max 86400 = 24 hours) | | callback | Yes | Async function receiving a DelegatedAgent |

The callback runs inside a try/finally — cleanup always happens, even on error. The child agent's scope is enforced server-side: any sub.execute() call outside the granted capabilities returns a 403.

DelegatedAgent

| Method | Description | |--------|-------------| | sub.execute(actionType, options?) | Execute an action as the child (includes X-AL-Delegation-ID header) | | sub.gate(actionType, options?) | Execute + block until approved | | sub.delegate(name, options, callback) | Chain further — create a sub-sub-agent with narrower scope |

AgentLattice.parallel(delegates)

Runs N delegation callbacks concurrently via Promise.all. Each delegation manages its own cleanup independently.

const results = await AgentLattice.parallel([
  al.delegate("reader-1", { capabilities: ["read_data"], ttl: 60 }, async (sub) => {
    return sub.execute("read_data", { metadata: { shard: 1 } });
  }),
  al.delegate("reader-2", { capabilities: ["read_data"], ttl: 60 }, async (sub) => {
    return sub.execute("read_data", { metadata: { shard: 2 } });
  }),
]);

See docs/ephemeral-agents.md for architecture details, security model, and cleanup guarantees.


Action Types

Action types are free-form strings matched against your configured policies. Use dot-notation namespaces:

| Action | Example | |--------|---------| | code.commit | Agent commits code changes | | pr.open | Agent opens a pull request | | pr.merge | Agent merges a pull request | | file.write | Agent writes to a file | | file.delete | Agent deletes a file | | db.migrate | Agent runs a database migration | | secret.read | Agent reads a secret or credential | | deploy.trigger | Agent triggers a deployment |

Define policies for each action type in your AgentLattice dashboard.


Patterns

Self-correcting agent

conditions_evaluated closes the feedback loop — agents can read which specific rule fired and adapt, not just fail.

const al = new AgentLattice({ apiKey: process.env.AL_API_KEY! });

async function openPRWithGovernance(files: string[]): Promise<void> {
  try {
    await al.gate("pr.open", {
      metadata: { pr_size: files.length, repo: "acme/backend" },
    });
    await openPR(files);

  } catch (e) {
    if (e instanceof AgentLatticeDeniedError && e.reason === "CONDITIONS_DENIED") {
      const failed = e.conditions?.filter(c => !c.result) ?? [];
      // e.g. [{field:"pr_size", operator:"lt", expected:50, result:false}]

      const prSizeRule = failed.find(c => c.field === "pr_size");
      if (prSizeRule) {
        // Policy says PRs must be < 50 files — split and retry
        const mid = Math.floor(files.length / 2);
        await openPRWithGovernance(files.slice(0, mid));
        await openPRWithGovernance(files.slice(mid));
        return;
      }
    }
    throw e; // reviewer denial or policy tamper — no retry
  }
}

LangGraph integration

import { tool } from "@langchain/core/tools";
import { AgentLattice } from "@agentlattice/sdk";

const al = new AgentLattice({ apiKey: process.env.AL_API_KEY! });

const mergeCodeTool = tool(async ({ pr_number, repo }) => {
  await al.gate("pr.merge", {
    metadata: { pr_number, repo },
  });
  return await mergePR(pr_number); // only reached if approved
}, {
  name: "merge_pr",
  description: "Merge a pull request (requires human approval)",
  schema: z.object({ pr_number: z.number(), repo: z.string() }),
});

Fire-and-forget logging

// Doesn't block — submits the audit event and continues
const { audit_event_id } = await al.execute("file.read", {
  data_accessed: [{ type: "filesystem", count: 1, sensitivity: "low" }],
  metadata: { path: "/etc/config.yaml" },
  event_id: `task-${taskId}-read`,  // stable ID for idempotency
});

Reliability

execute() and gate() retry automatically on 5xx and network errors — up to 3 attempts with 1s/2s/4s exponential backoff. Each request has a 30-second timeout. Pass event_id to make retries idempotent — the server deduplicates by that key and returns the existing audit record instead of creating a duplicate.