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

agent-airlock

v0.1.6

Published

Human approval gate for AI agent actions. Drop-in protection against prompt injection for any API key.

Readme

airlock

Approval gate for autonomous AI agents. Protect any API key from prompt injection and rogue behavior.

Works with any agent framework: Hermes, LangChain, CrewAI, AutoGPT, Claude Code, or raw API calls.

If you're running an autonomous AI agent that's: responding to messages, running cron jobs, or browsing the internet, airlock lets you give it API access without giving it full control. Your agent queues actions, you approve or reject them from your phone via Telegram.

You decide which actions need approval and which don't. Let your agent read timelines, search, and manage lists freely, but require your approval before it tweets, sends DMs, or makes payments. Fine-grained control without slowing down the work that's safe to automate.

Prerequisites

Before setting up airlock, make sure:

  1. Your agent cannot read your API keys. Airlock stores secrets in its own .airlock/.env file, but if your agent runs as the same OS user, it can read that file. Run your agent as a separate OS user with no access to airlock's directory. On Linux:

    # Create a restricted user for your agent
    sudo useradd -m -s /bin/bash agent
    # Your main user runs airlock and owns the secrets
    # The agent user can only reach airlock via HTTP on localhost
  2. Your agent cannot sudo. If it can, it can read anything. Remove sudo access for the agent user.

  3. Your agent calls airlock instead of the API directly. Instead of giving your agent an X API key, give it access to http://localhost:4444/queue. Airlock holds the real keys and only uses them when you approve.

  4. Node.js 18+

Without #1 and #2, airlock's approval gate can be bypassed. The approval flow is cryptographically secure, but it assumes the agent process is isolated from the secrets.

Why

AI agents with API keys have two failure modes:

  1. Prompt injection - a crafted input tricks your agent into taking actions you never intended
  2. Rogue behavior - the agent misinterprets instructions or makes bad judgment calls on its own

Airlock solves both by putting a cryptographically verified human approval step between your agent and any sensitive action. The agent can read, search, and organize freely - but anything that speaks as you, spends your money, or contacts someone requires your explicit approval via Telegram.

How it works

Agent                    Airlock                  You (Telegram)
  |                        |                          |
  |-- POST /queue -------->|                          |
  |   {type, text, ...}    |-- sends message -------->|
  |                        |   with real content      |
  |<-- {id, pending} ------|   + approve/reject       |
  |                        |                          |
  |                        |<-- tap approve --------- |
  |                        |   (verified real tap)    |
  |                        |-- execute action         |
  |                        |-- "Approved" ----------->|

Security layers

  • OS-level secret isolation - API keys live where the agent process cannot read them
  • HMAC tamper detection - content is hashed at queue time and verified at execution, so the agent can't modify a pending request after you've seen it
  • Telegram callback verification - the server verifies each button tap is a real Telegram callback, not a forged HTTP request
  • User ID allowlist - only your Telegram account can approve actions

Quick start

npx agent-airlock init

This walks you through setup:

  1. Enter your Telegram bot token (create one via @BotFather)
  2. Enter your Telegram user ID
  3. Sends a test message to confirm it works

Then define your executors in airlock.config.ts:

import { type AirlockConfig } from 'agent-airlock'

const config: AirlockConfig = {
  // ... (generated by init)

  executors: {
    tweet: async (data) => {
      const res = await fetch('https://api.x.com/2/tweets', {
        method: 'POST',
        headers: { Authorization: `Bearer ${process.env.X_TOKEN}`, 'Content-Type': 'application/json' },
        body: JSON.stringify({ text: data.text }),
      })
      return { success: true, message: 'Tweet posted' }
    },

    email: async (data) => {
      // your email sending logic
      return { success: true, message: `Email sent to ${data.metadata?.to}` }
    },
  },
}

export default config

Start the server:

npx agent-airlock start

Agent integration

Your agent queues actions with a single HTTP call:

# Queue a tweet
curl -X POST http://localhost:4444/queue \
  -H "Content-Type: application/json" \
  -d '{"type": "tweet", "text": "hello world", "context": "engagement post"}'

# Queue an email
curl -X POST http://localhost:4444/queue \
  -H "Content-Type: application/json" \
  -d '{"type": "email", "text": "Meeting tomorrow?", "metadata": {"to": "[email protected]"}, "context": "follow-up"}'

# List pending approvals
curl http://localhost:4444/pending

The context field is optional - it lets the agent explain why it wants to take this action, which shows up in your Telegram message.

Works locally, on servers, anywhere Node runs. No public IP or domain required.

Architecture

Airlock runs one HTTP server on localhost and polls Telegram for approval button taps.

| Component | Port | Purpose | |-----------|------|---------| | Queue server | 4444 | Agent submits actions (localhost only) | | Telegram poller | - | Listens for approve/reject button taps |

The queue server binds to 127.0.0.1 - only local processes can reach it. Telegram communication uses long-polling, so no inbound ports or HTTPS certs are needed.

Files

.airlock/
  .env                 # Secrets (bot token, HMAC key)
  data/
    pending/           # Queued actions waiting for approval
    done/              # Resolved actions (approved/rejected)
airlock.config.ts      # Your executor definitions

Add .airlock/ to your .gitignore.

API

POST /queue

Queue an action for approval.

{
  "type": "tweet",
  "text": "The content to approve",
  "context": "Agent's reason for this action",
  "metadata": { "any": "extra data your executor needs" }
}

Returns: {"id": "a1b2c3d4", "status": "pending"}

GET /pending

List all pending approvals.

GET /health

Returns {"ok": true}.

License

MIT