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

@ai11/openclaw-a2a

v0.1.0

Published

OpenClaw A2A Plugin — exposes OpenClaw agents via the Agent2Agent protocol

Readme

OpenClaw A2A Plugin

Expose OpenClaw agents via Google's Agent-to-Agent (A2A) protocol, enabling seamless interoperability with any A2A-compliant client or agent network.

Built on the official @a2a-js/sdk as the protocol engine.

Features

  • Agent Card DiscoveryGET /.well-known/agent-card.json serves a fully compliant A2A Agent Card
  • JSON-RPC message/send — synchronous task execution via standard A2A JSON-RPC
  • Streaming — SSE-based streaming responses with incremental artifact updates
  • Skill → Agent Routing — map A2A skills to OpenClaw agents via a configurable routing table
  • Authentication — static bearer tokens, JWT validation (HS256/RS256), and mTLS identity extraction
  • Per-Skill ACLs — fine-grained access control by subject or role per skill
  • SQLite Persistent TaskStore — survive Gateway restarts with WAL-mode SQLite (or use in-memory)
  • Rate Limiting — per-caller token bucket rate limiter with configurable RPM and burst
  • Health Checks — upstream /v1/responses reachability probes
  • Outbound Federationa2a-call-remote and a2a-discover tools for calling external A2A agents

Quick Start

1. Install

npm install @ai11/openclaw-a2a

2. Minimal Configuration

Add the plugin to your openclaw.json with just the essentials:

{
  "plugins": {
    "@ai11/openclaw-a2a": {
      "basePath": "/a2a",
      "gatewayBaseUrl": "http://127.0.0.1:3000",
      "gatewayToken": "<your OpenClaw Gateway token>",

      "routing": {
        "defaultAgentId": "default-agent"
      },

      "auth": {
        "allowedBearerTokens": ["<generate-a-strong-token>"],
        "agentCardPublic": true
      },

      "agentCard": {
        "name": "My OpenClaw Agent",
        "description": "An AI agent powered by OpenClaw",
        "version": "1.0.0",
        "skills": [
          {
            "id": "general",
            "name": "General",
            "description": "General-purpose assistant",
            "tags": ["general"]
          }
        ]
      }
    }
  }
}

Where do I get gatewayToken? This is the token configured in your OpenClaw Gateway's openclaw.json under the top-level "token" field. It authenticates this plugin's loopback calls to the Gateway's /v1/responses endpoint. If you haven't set one, add "token": "some-secret" to your Gateway config and use the same value here.

3. Start the Gateway

openclaw gateway start

You're up! The agent card is at http://localhost:3000/.well-known/agent-card.json and A2A requests go to POST http://localhost:3000/a2a.

Advanced Configuration

The full config adds JWT auth, per-skill ACLs, rate limiting, persistent task storage, and multi-agent routing:

{
  "plugins": {
    "@ai11/openclaw-a2a": {
      "basePath": "/a2a",
      "gatewayBaseUrl": "http://127.0.0.1:3000",
      "gatewayToken": "<your OpenClaw Gateway token>",

      "routing": {
        "defaultAgentId": "default-agent",
        "skillToAgentId": {
          "code-review": "code-reviewer-agent",
          "summarize": "summarizer-agent"
        }
      },

      "auth": {
        "allowedBearerTokens": ["token-abc-123"],
        "agentCardPublic": true,
        "jwt": {
          "hsSecret": "your-hs256-secret",
          "audience": "https://your-gateway.example.com",
          "issuer": "https://auth.example.com",
          "algorithms": ["HS256", "RS256"]
        },
        "acls": {
          "code-review": {
            "allowedSubjects": ["service-a"],
            "allowedRoles": ["developer"]
          }
        }
      },

      "rateLimit": {
        "requestsPerMinute": 60,
        "burst": 10
      },

      "taskStore": {
        "type": "sqlite",
        "dbPath": "./data/tasks.db",
        "ttlMs": 604800000,
        "cleanupIntervalMs": 3600000
      },

      "agentCard": {
        "name": "My OpenClaw Agent",
        "description": "An AI agent powered by OpenClaw",
        "version": "1.0.0",
        "capabilities": {
          "streaming": true,
          "pushNotifications": false,
          "stateTransitionHistory": false
        },
        "skills": [
          {
            "id": "code-review",
            "name": "Code Review",
            "description": "Reviews pull requests and provides feedback",
            "tags": ["code", "review"]
          },
          {
            "id": "summarize",
            "name": "Summarize",
            "description": "Summarizes documents and conversations",
            "tags": ["text", "summary"]
          }
        ]
      }
    }
  }
}

Usage Examples

Discover the Agent Card

curl http://localhost:3000/.well-known/agent-card.json

Send a message (JSON-RPC message/send)

curl -X POST http://localhost:3000/a2a \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer token-abc-123" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "message/send",
    "params": {
      "message": {
        "kind": "message",
        "messageId": "msg-001",
        "role": "user",
        "parts": [{ "kind": "text", "text": "Review this code" }],
        "metadata": { "ai11.skillId": "code-review" }
      }
    }
  }'

Stream a response (SSE)

curl -X POST http://localhost:3000/a2a \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer token-abc-123" \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "message/stream",
    "params": {
      "message": {
        "kind": "message",
        "messageId": "msg-002",
        "role": "user",
        "parts": [{ "kind": "text", "text": "Summarize this document" }],
        "metadata": { "ai11.skillId": "summarize" }
      }
    }
  }'

Security Considerations

Authentication

  • Bearer tokens are the simplest auth method. Generate strong, random tokens (e.g., openssl rand -hex 32). Never use placeholder values in production.
  • JWT validation supports HS256 and RS256. Always set audience and issuer to prevent token reuse across services.
  • mTLS extracts client identity from TLS certificates for high-trust environments.

Token Management

  • gatewayToken authenticates loopback calls from this plugin to the OpenClaw Gateway. Treat it like any internal secret — do not commit it to version control. Use environment variables or a secrets manager.
  • allowedBearerTokens should be rotated periodically. When rotating, temporarily allow both old and new tokens, then remove the old one.
  • JWT secrets (hsSecret) must be strong and unique. For RS256, use proper key management and rotate signing keys on a schedule.

Access Control (ACLs)

  • By default, all authenticated callers can access all skills. Use auth.acls to restrict sensitive skills to specific subjects or roles.
  • ACL subjects come from the authenticated identity (bearer token lookup, JWT sub claim, or mTLS CN).
  • Always apply the principle of least privilege — only grant access to the skills each caller needs.

Network Exposure

  • Do not expose the Gateway directly to the public internet without a reverse proxy (e.g., nginx, Caddy) handling TLS termination.
  • The Agent Card endpoint (/.well-known/agent-card.json) is public by default when agentCardPublic: true. Set it to false if your agent should not be discoverable.
  • Rate limiting (rateLimit) is per-caller and in-memory. For production deployments behind a load balancer, consider additional rate limiting at the proxy layer.
  • The loopback URL (gatewayBaseUrl) should always point to 127.0.0.1 or localhost — never expose it externally.

Task Store

  • SQLite task store files (data/tasks.db) may contain conversation content. Protect them with appropriate file permissions.
  • Set ttlMs to automatically purge old tasks and limit data retention.

Architecture

The plugin registers two HTTP routes on the OpenClaw Gateway:

  1. GET /.well-known/agent-card.json — serves the Agent Card (optionally public)
  2. POST {basePath} (prefix match, default /a2a) — JSON-RPC handler for A2A methods

Request flow:

Client → Auth middleware → Rate limiter → ACL check → a2a-js JsonRpcTransportHandler
  → OpenClawAgentExecutor → Router.resolve(skillId) → POST /v1/responses (loopback)
  → SSE stream parsed → EventBus artifact/status events → A2A response/stream

The OpenClawAgentExecutor implements the AgentExecutor interface from @a2a-js/sdk. It extracts text from incoming A2A messages, resolves the target OpenClaw agent via the skill router, calls the Gateway's loopback /v1/responses endpoint, and streams incremental results back through the A2A protocol.

For a deep dive, see:

Project Structure

src/
├── index.ts                      # Plugin entrypoint — route registration & wiring
├── config.ts                     # Config types, parsing, validation, AgentCard builder
├── transport.ts                  # HTTP bridge — adapts a2a-js handlers to raw Node.js req/res
├── router.ts                     # Skill → AgentId routing with default fallback
├── openclaw-agent-executor.ts    # AgentExecutor — bridges A2A to OpenClaw /v1/responses
├── auth.ts                       # Bearer token + JWT + mTLS auth, ACL authorization
├── rate-limit.ts                 # Per-caller token bucket rate limiter
├── sqlite-task-store.ts          # SQLite-backed TaskStore with TTL cleanup
├── health.ts                     # Upstream health check probe
├── *.test.ts                     # Co-located unit tests (Vitest)
docs/
├── prd.md                        # Product Requirements Document
├── architecture.md               # Architecture & design decisions

Development

# Install dependencies
npm install

# Build
npm run build

# Run tests
npm test

# Watch mode
npm run test:watch

# Clean build artifacts
npm run clean

Requirements: Node.js ≥ 18

License

MIT