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

@reallyartificial/approval-protocol-core

v0.1.1

Published

A protocol for AI agent human-in-the-loop approval. What MCP did for tool access, AP does for human oversight.

Readme

@reallyartificial/approval-protocol-core

The safety layer between AI agents and the real world.

What MCP did for tool access, Approval Protocol does for human oversight.


AI agents take actions in the real world — send emails, spend money, modify databases, deploy code. Every agent framework has its own half-baked human-in-the-loop mechanism, all framework-locked, all missing notification channels and escalation.

Approval Protocol (AP) is a protocol — not a library — that standardizes how agents get human permission before executing actions, confirm execution results, and enable rollback when things go wrong.

Install

npm install @reallyartificial/approval-protocol-core

How It Works

Agent                    AP Server                   Human
  |                         |                          |
  |-- ap/negotiate -------->|                          |
  |<-- policies + session --|                          |
  |                         |                          |
  |-- ap/request ---------->|                          |
  |<-- request_id + mode ---|-- notify --------------->|
  |                         |                          |
  |-- ap/status ----------->|         ap/decide <------|
  |<-- approved ------------|                          |
  |                         |                          |
  |-- [execute action]      |                          |
  |                         |                          |
  |-- ap/confirm ---------->|  (result + undo info)    |
  |<-- confirmed -----------|                          |
  |                         |                          |
  |   ap/rollback <---------|--------------------------|
  |<-- undo instructions ---|                          |

Quickstart

Server

import { ApprovalServer, CliChannel } from "@reallyartificial/approval-protocol-core";

const server = new ApprovalServer({
  port: 4000,
  channel: new CliChannel(),
  policies: {
    send_email:     { requires: "always" },
    search_kb:      { requires: "never" },
    issue_refund:   { requires: "conditional", when: "params.amount > 100" },
    delete_records: { requires: "always", execution: "sandbox" },
  },
});

await server.start();

Client

import { ApprovalClient } from "@reallyartificial/approval-protocol-core";

const client = new ApprovalClient("http://localhost:4000");

// 1. Negotiate — declare what actions you may take
const session = await client.negotiate("my-agent", ["send_email", "search_kb"]);

// 2. Request approval
const { request_id, status, execution_mode } = await client.request({
  action: { name: "send_email", params: { to: "[email protected]", body: "Hello" } },
  context: { agent: "my-agent", reason: "Customer requested help" },
  risk: { reversible: false, blast_radius: "external" },
});

// 3. Wait for human decision
if (status === "pending") {
  const result = await client.waitForDecision(request_id, { timeout: 60_000 });

  if (result.status === "approved") {
    // 4. Execute the action
    const emailResult = sendEmail("[email protected]", "Hello");

    // 5. Confirm execution with undo instructions
    await client.confirm({
      request_id,
      success: true,
      result: { message_id: emailResult.id },
      undo: {
        type: "api_call",
        description: "Recall the email",
        instructions: { method: "POST", url: `/recall/${emailResult.id}` },
      },
      confirmed_by: "my-agent",
    });
  }
}

// 6. Later, if something went wrong:
await client.rollback({
  request_id,
  reason: "Email contained incorrect information",
  initiated_by: "[email protected]",
});

withApproval Wrapper

For transparent lifecycle management without manual request/confirm calls:

import { withApproval } from "@reallyartificial/approval-protocol-core/client";

const sendEmail = withApproval(
  async (to: string, body: string) => { /* actual send logic */ },
  {
    action: "send_email",
    client,
    risk: { reversible: false, blast_radius: "external" },
    undo: { type: "manual", description: "Contact recipient to disregard" },
  }
);

// Approval + execution + confirmation happens transparently
await sendEmail("[email protected]", "Your refund is ready");

The Protocol

6 methods over HTTP:

| Method | Purpose | |--------|---------| | ap/negotiate | Trust handshake — agent declares capabilities, server returns policies | | ap/request | Agent requests approval for an action | | ap/decide | Human submits approval decision (approve / deny / edit) | | ap/confirm | Agent confirms execution result with undo metadata | | ap/rollback | Request rollback of a confirmed action | | ap/status | Check full lifecycle status of any request |

Policies

Per-action rules that control approval behavior:

policies: {
  send_email:     { requires: "always" },                              // always ask a human
  search_kb:      { requires: "never" },                               // auto-approve
  issue_refund:   { requires: "conditional", when: "params.amount > 100" }, // ask if > $100
  delete_records: { requires: "always", execution: "sandbox" },        // ask + sandbox mode
}
  • "always" — human approval required
  • "never" — auto-approved, no human needed
  • "conditional" — evaluate expression against action params and risk metadata

Execution Modes

Policies can specify how the agent should execute:

| Mode | Behavior | |------|----------| | live | Normal execution (default) | | sandbox | Run in isolated/test environment | | dry_run | Simulate without side effects |

Channels

AP routes approval requests to humans via channels:

  • CliChannel — Terminal prompt (built-in, for development and demos)
  • WebhookChannel — POST to any URL (Slack bot, email service, custom UI)
import { WebhookChannel } from "@reallyartificial/approval-protocol-core";

const channel = new WebhookChannel({
  url: "https://your-slack-bot.example.com/approvals",
});

Exports

// Server
import { ApprovalServer, CliChannel, WebhookChannel } from "@reallyartificial/approval-protocol-core";
import { ApprovalServer } from "@reallyartificial/approval-protocol-core/server";

// Client
import { ApprovalClient, withApproval } from "@reallyartificial/approval-protocol-core";
import { ApprovalClient } from "@reallyartificial/approval-protocol-core/client";

// Types
import type { ApPolicy, ApRiskMetadata, ApUndoMetadata, ApChannel } from "@reallyartificial/approval-protocol-core";

// Zod Schemas (for validation in your own code)
import { ApRequestParamsSchema, ApDecideParamsSchema } from "@reallyartificial/approval-protocol-core";

Full Specification

See PROTOCOL.md for the complete protocol specification.

Related

License

MIT