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

@octostaff/reef

v0.4.3

Published

OctoStaff reef connector worker — bridges Bubble and hosted A2A agents.

Readme

@octostaff/reef

Connect OctoStaff Bubble threads to hosted A2A agents and ACP agents.

@octostaff/reef is a connector worker that authenticates to Bubble as a bot principal, watches the Bubble threads that principal has joined, forwards user runs to an agent, and writes the agent's response stream back into Bubble. It speaks two protocols: A2A (a hosted agent behind an HTTP streaming endpoint) and ACP (Agent Client Protocol — a subprocess reef spawns and drives over stdio).

When to Use It

Use @octostaff/reef when your agent should be driven by a worker process rather than dialing into Bubble itself — a hosted A2A agent behind an HTTP endpoint, or an ACP-compatible agent reef launches as a subprocess. Reef is a good fit for server-side agents, containerized agents, and scale-to-zero deployments where the agent cannot keep its own long-lived Bubble WebSocket connection open.

Use @octostaff/claude-scuba instead when a local Claude Code process should dial into Bubble directly.

Install

npm install @octostaff/reef

The package includes the reef executable. Install it globally if you want the command on your shell path:

npm install -g @octostaff/reef

For local installs, run the executable from an npm script or with npx:

npx reef

Prerequisites

  • A running OctoStaff Bubble server.
  • A Bubble bot principal and bearer token for that principal.
  • A hosted A2A agent that serves an agent card and supports streaming. Reef supports the standard /.well-known/agent-card.json location and Azure AI Foundry's project-scoped A2A endpoint.
  • Network access from the Reef worker to both Bubble and the hosted agent.

Quick Start

Create reef.config.json:

{
  "bubble": {
    "url": "https://bubble.example.com",
    "principalId": "hosted-agent-bot",
    "token": { "env": "BUBBLE_BOT_TOKEN" }
  },
  "a2a": {
    "agentCardUrl": "https://agent.example.com/.well-known/agent-card.json",
    "authToken": { "env": "A2A_AGENT_TOKEN" }
  }
}

Run the connector:

BUBBLE_BOT_TOKEN=... A2A_AGENT_TOKEN=... reef

For Azure AI Foundry A2A, point Reef at the project endpoint and agent name:

{
  "bubble": {
    "url": "https://bubble.example.com",
    "principalId": "foundry-agent-bot",
    "token": { "env": "BUBBLE_BOT_TOKEN" }
  },
  "a2a": {
    "provider": "azure-foundry",
    "baseUrl": "https://acct.services.ai.azure.com/api/projects/project-name",
    "agentName": "your-agent-name",
    "auth": { "type": "azure-identity" }
  }
}

To use a token from the Azure CLI instead, set auth to a bearer env ref:

"auth": { "type": "bearer", "token": { "env": "AZURE_FOUNDRY_TOKEN" } }
AZURE_FOUNDRY_TOKEN=$(az account get-access-token --resource https://ai.azure.com --query accessToken -o tsv)
BUBBLE_BOT_TOKEN=... reef

By default, Reef reads ./reef.config.json. Point it at another file with --config (-c):

reef --config /etc/octostaff/reef.json

Ping

Use the executable to test only the configured A2A agent without starting the Bubble connector:

reef ping --config ./reef.azure.json --prompt "hi"

The ping fetches the agent card, sends one streaming A2A user message, and prints any text returned by the agent. For Azure AI Foundry with an Azure CLI token:

export AZURE_FOUNDRY_TOKEN=$(az account get-access-token --resource https://ai.azure.com --query accessToken -o tsv)
reef ping --config ./reef.azure.json --prompt "hi"

BUBBLE_BOT_TOKEN does not need to be set for the ping; Reef parses the Bubble config but does not resolve the Bubble token or contact Bubble. A2A auth env refs still must be set.

Configuration

bubble

  • url: Base URL of the Bubble server.
  • principalId: Bubble bot principal ID Reef authenticates as.
  • token: Bearer token for the principal. Use a string or { "env": "NAME" }.
  • consumer: Optional cursor policy for thread consumption.

Default consumer policy:

{
  "coldStart": { "mode": "from-head" },
  "resume": { "mode": "durable" }
}

The durable resume default is intentional: Reef is usually deployed as infrastructure, so missed user prompts should be replayed after a restart.

a2a

Generic A2A agents:

  • agentCardUrl: URL of the hosted agent's card, or the hosted agent's base origin.
  • agentCardPath: Optional card path to append when agentCardUrl is a base endpoint. Defaults to /.well-known/agent-card.json.
  • authToken: Optional bearer token sent to the hosted agent. Use a string or { "env": "NAME" }.

Azure AI Foundry A2A agents:

  • provider: Set to "azure-foundry".
  • baseUrl: Project endpoint, e.g. https://{account}.services.ai.azure.com/api/projects/{project}.
  • agentName: Foundry agent name in that project.
  • protocolVersion: Optional "1.0" or "0.3"; defaults to "1.0".
  • auth: Optional. Defaults to { "type": "azure-identity" }, which uses @azure/identity DefaultAzureCredential with the https://ai.azure.com/.default scope. Use { "type": "bearer", "token": { "env": "AZURE_FOUNDRY_TOKEN" } } for a token supplied by az account get-access-token.

Reef supports the A2A HTTP JSON streaming binding and the canonical JSON-RPC streaming binding exposed by compatible A2A servers.

acp

Set acp instead of a2a to bridge an Agent Client Protocol agent. Reef acts as the ACP client: it spawns the configured command as a subprocess and speaks JSON-RPC over its stdio, opening one ACP session per Bubble thread and forwarding user turns as session/prompt. The agent's session/update stream (message chunks, thoughts, tool calls) is translated back into Bubble events.

{
  "bubble": {
    "url": "https://bubble.example.com",
    "principalId": "acp-agent-bot",
    "token": { "env": "BUBBLE_BOT_TOKEN" }
  },
  "acp": {
    "command": "my-acp-agent",
    "args": ["--stdio"],
    "cwd": "/workspace"
  }
}
  • command: Executable to spawn (any ACP-compatible agent).
  • args: Optional command-line arguments.
  • env: Optional extra environment variables, merged over reef's process env.
  • cwd: Optional absolute working directory passed as the session cwd on session/new. Defaults to reef's process working directory.
  • protocolVersion: Optional ACP protocol version to negotiate. Defaults to the SDK's current version.

Exactly one of a2a or acp must be set. In this release reef auto-approves the agent's permission requests and advertises no filesystem/terminal client capabilities; reef ping is A2A-only.

logger

Optional. Controls reef's output.

  • level: One of trace debug info warn error. Defaults to info (or the LOG_LEVEL env var). Sets the threshold for the stdout [reef] log.
  • pretty: Force colour (true) or plain (false) output. Defaults to TTY-detection.
  • runLog: Per-run audit logging to disk for debugging. Off by default.
    • enabled: Set true to turn it on. Requires dir.
    • dir: Directory the log files are written to (created on demand).

When runLog is enabled, each bot reply opens one NDJSON file named:

<UTC-timestamp>__<principalId>__thread-<threadId>__run-<runId>.jsonl

Every line is { ts, principalId, threadId, runId, kind, … }, so you can find a problem by thread id or run id — list the files, or grep a run id across the whole dir. Each file captures the A2A exchange for that run:

  • a2a_request — the message reef forwarded to the hosted agent.
  • a2a_response — each stream response the agent sent back.
  • event — lifecycle markers (run_started, task_id, interrupted, error, run_finished).
{
  "bubble": { "url": "https://bubble.example.com", "token": { "env": "BUBBLE_BOT_TOKEN" } },
  "a2a": { "agentCardUrl": "https://agent.example.com/.well-known/agent-card.json" },
  "logger": { "level": "debug", "runLog": { "enabled": true, "dir": "./logs" } }
}

It is off by default because the files accumulate one-per-run; enable it on the worker you are debugging and point dir at scratch storage.

Library Usage

import { ReefConnector, loadReefConfig } from '@octostaff/reef';

const config = await loadReefConfig('./reef.config.json');
const logger = console;

const connector = new ReefConnector(config, logger);
await connector.start();

process.once('SIGTERM', () => {
  void connector.stop();
});

Operations

  • Reef starts one relay per Bubble thread where the configured principal has a participant role.
  • Adding the principal to a thread starts a relay for that thread.
  • Revoking the principal's thread grant stops the relay.
  • User runs are forwarded to the hosted A2A agent as streaming messages.
  • Agent text, task status, artifacts, and recognized tool data are translated back into Bubble events.
  • run_interrupt_requested events cancel the active A2A task when a task ID is known.
  • Send SIGINT or SIGTERM for graceful shutdown.

Package Contents

The npm package ships compiled, minified JavaScript, the reef executable, and TypeScript declarations. The runtime bundles the Bubble SDK code it uses. Public declarations may reference @octostaff/sdk where public APIs expose shared Bubble protocol types.