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

@prometheus-ags/entity-graph-a2a

v4.0.2

Published

Policy-gated A2A v1 JSON-RPC and streaming SSE for the Prometheus entity graph, with deterministic A2UI artifacts.

Readme

@prometheus-ags/entity-graph-a2a

Official A2A 1.0 JSON-RPC and streaming SSE for the Prometheus normalized entity graph.

The package uses @a2a-js/[email protected] for the wire model and transport dispatcher. Prometheus owns the application policy, graph adapter, deterministic reference executor, and its versioned A2UI artifact adapter.

Supported boundary

| Surface | Stable 3.0 contract | | --- | --- | | Discovery | GET /.well-known/agent-card.json | | Binding | JSON-RPC only, A2A protocol 1.0 | | Methods | SendMessage, SendStreamingMessage, GetTask, ListTasks, CancelTask, SubscribeToTask | | Streaming | Ordered task, status, artifact, and terminal envelopes over SSE | | Graph authority | Default deny; application allowlists entity types, actions, and fields | | Destructive writes | replace and remove require an out-of-band approval decision | | A2UI | Prometheus-owned structured-data adapter carrying validated A2UI v0.9.1 messages | | Reference agent | Deterministic and keyless, with injectable IDs, clock, and delay | | Remote agent | Optional HTTPS/loopback JSON-RPC executor seam; never required by default CI |

The AgentCard truthfully disables push notifications and extended cards. REST, gRPC, signed AgentCards, hosted identity, and production multi-tenant routing are not certified by this package gate.

Installation

pnpm add @prometheus-ags/entity-graph-a2a @prometheus-ags/entity-graph-core

The A2A SDK is an exact production dependency of this package. Applications do not need to install a second SDK copy to use the public Prometheus API.

Quick start

import {
  buildAgentCard,
  createA2AServer,
  createBearerTokenAuthenticator,
  createEntityGraphA2APolicy,
} from "@prometheus-ags/entity-graph-a2a";

const policy = createEntityGraphA2APolicy({
  entities: {
    Invoice: {
      actions: ["upsert", "replace", "remove", "query", "snapshot"],
      fields: ["id", "amount", "status"],
    },
    "*": { actions: ["snapshot"], fields: [] },
  },
  authorize: ({ caller, tenantId }) =>
    caller.isAuthenticated &&
    caller.scopes.includes("invoice:a2a") &&
    tenantId === caller.claims?.tenantId,
  requestApproval: async (context) =>
    approvalService.decide({
      callerId: context.caller.id,
      operation: context.operation,
      entityType: context.entityType,
      entityId: context.entityId,
    }),
});

const authenticator = createBearerTokenAuthenticator({
  verify: async (token) => {
    const identity = await verifyAccessToken(token);
    return identity
      ? {
          id: identity.subject,
          scopes: identity.scopes,
          claims: { tenantId: identity.tenantId },
        }
      : null;
  },
});

const server = createA2AServer({
  card: buildAgentCard({
    url: "https://api.example.com/a2a",
    name: "Invoice Graph Agent",
    authentication: "bearer",
  }),
  authenticator,
  policy,
});

// Fetch-compatible runtimes: Workers, Bun, Deno, Hono, or a Node adapter.
export default {
  fetch(request: Request) {
    return server.fetch(request);
  },
};

server.fetch() serves both the discovery route and the configured JSON-RPC endpoint. Do not add a second, hand-written AgentCard route.

Security model

Protocol validity never grants application authority.

HTTP credential
  -> caller identity
  -> request/task visibility policy
  -> official A2A dispatcher
  -> graph entity/action/field policy
  -> destructive approval
  -> one atomic graph transaction
  • createDefaultDenyA2APolicy() allows ordinary task protocol operations but denies every graph read and write.
  • createDenyAllA2APolicy() denies protocol dispatch and graph access.
  • createEntityGraphA2APolicy() builds explicit application rules.
  • A batch is authorized in full before its transaction begins. One forbidden field rejects the entire batch.
  • Hidden and nonexistent tasks have the same lookup error class for callers outside the owning scope.
  • Approval metadata supplied by an agent cannot approve its own destructive operation.
  • Bearer credentials are passed to the application's verifier and are never logged by the package.

The supplied bearer helper is an adapter, not a hosted identity system. Signature, issuer, audience, expiry, revocation, and tenant validation remain the host application's responsibility.

Entity graph messages

Graph operations use an ordinary official A2A data part plus the Prometheus extension URI. They do not add a private member to the A2A Part union.

import {
  PROMETHEUS_GRAPH_EXTENSION_URI,
  Role,
  type EntityGraphA2ARequest,
  type Message,
} from "@prometheus-ags/entity-graph-a2a";

const request: EntityGraphA2ARequest = {
  kind: "prometheus.entity-graph.request",
  version: "1.0",
  operation: "mutate",
  mutations: [
    {
      op: "upsert",
      entityType: "Invoice",
      id: "invoice-1",
      data: { id: "invoice-1", amount: 100, status: "open" },
    },
  ],
};

const message: Message = {
  role: Role.ROLE_USER,
  messageId: crypto.randomUUID(),
  taskId: "",
  contextId: "",
  parts: [{
    content: { $case: "data", value: request },
    mediaType: "application/json",
    filename: "",
    metadata: { extensionUri: PROMETHEUS_GRAPH_EXTENSION_URI },
  }],
  metadata: {},
  extensions: [PROMETHEUS_GRAPH_EXTENSION_URI],
  referenceTaskIds: [],
};

Supported graph operations are upsert, replace, remove, patch, clearPatch, query, and snapshot. Local patches remain graph-local and are never represented as server-confirmed canonical data.

Deterministic A2UI artifacts

The built-in executor can emit an A2UI surface without a model credential when the client requests PROMETHEUS_A2UI_EXTENSION_URI.

import {
  PROMETHEUS_A2UI_EXTENSION_URI,
  PROMETHEUS_A2UI_PROTOCOL_VERSION,
  createA2UIArtifact,
  createDeterministicA2UIMessages,
} from "@prometheus-ags/entity-graph-a2a";

const messages = createDeterministicA2UIMessages(
  "The invoice is ready for review.",
  "invoice-review",
);
const artifact = createA2UIArtifact(messages, {
  artifactId: "invoice-review-artifact",
});

if (PROMETHEUS_A2UI_PROTOCOL_VERSION !== "v0.9.1") {
  throw new Error("unexpected protocol baseline");
}
void artifact;
void PROMETHEUS_A2UI_EXTENSION_URI;

This is a Prometheus-owned versioned adapter. It does not claim that the legacy upstream A2UI-for-A2A v0.8 extension defines v0.9.1 transport semantics. Renderer action authorization is still enforced by @prometheus-ags/a2ui-react.

For repeatable tests, pass deterministicExecutor options to createA2AServer:

const server = createA2AServer({
  card: buildAgentCard({ url: "http://127.0.0.1/a2a" }),
  deterministicExecutor: {
    clock: () => "2030-01-15T12:00:00.000Z",
    idFactory: (() => {
      let id = 0;
      return () => `fixture-${++id}`;
    })(),
    stepDelayMs: 25,
  },
});

Optional external executor

createExternalA2AExecutor() discovers an AgentCard from an HTTPS or loopback base URL, selects JSON-RPC, streams the remote lifecycle, and remaps remote IDs into the local task boundary.

import {
  buildAgentCard,
  createA2AServer,
  createExternalA2AExecutor,
} from "@prometheus-ags/entity-graph-a2a";

const server = createA2AServer({
  card: buildAgentCard({ url: "https://gateway.example.com/a2a" }),
  executor: createExternalA2AExecutor({
    baseUrl: "https://agent.example.com",
    serviceParameters: { Authorization: `Bearer ${await issueAgentToken()}` },
  }),
});

The external endpoint is an opt-in runtime dependency. HTTPS is required outside loopback development, and URL-embedded usernames or passwords are rejected before AgentCard discovery. Keep authenticated production routing and credentials in a server-side gateway. Default CI and the reference agent remain keyless and local.

Migrating alpha consumers

The pre-v3 slash methods are intentionally absent from the package root and the A2A 1.0 endpoint.

| Alpha surface | Stable replacement | | --- | --- | | /.well-known/agent.json | /.well-known/agent-card.json | | tasks/send | SendMessage | | tasks/sendSubscribe | SendStreamingMessage over SSE | | tasks/get | GetTask | | tasks/cancel | CancelTask | | bespoke part/status/task types | official @a2a-js/sdk types re-exported from the package root | | DefaultEntityGraphHandler | DeterministicEntityGraphExecutor plus an application policy |

For a bounded migration window, import the explicit adapter:

import { createLegacyA2AAdapter } from "@prometheus-ags/entity-graph-a2a/legacy";

const legacy = createLegacyA2AAdapter({ server });
const response = await legacy.handleRequest(oldSlashMethodRequest, {
  requestedVersion: "1.0",
});

The legacy adapter translates retained send/get/cancel shapes. It does not expose legacy streaming; migrate streaming callers to the official SSE method. New code must not use this subpath.

Verification

From the repository root:

pnpm run test:a2a-conformance
pnpm run verify:a2a-conformance
pnpm run test:a2a-tck
pnpm run bdd:a2a-conformance
pnpm --filter @prometheus-ags/entity-graph-a2a run verify:skills

The upstream gate pins a2aproject/a2a-tck at commit 5996b79f9cefa6fc390980e383e358a66fb9e49e. Its receipt separates MUST, SHOULD, MAY, binding, capability exclusions, and candidate artifact hashes. A failed applicable MUST or unexplained selected-binding skip blocks the gate.

These checks certify the headless package boundary. Browser rendering, accessibility, and visual evidence are owned by the v3-agentic-a2ui-example showcase; no screenshot is evidence for a headless transport.

The repository's dedicated agentic-a2ui-app is the reference composition for consuming the streamed A2UI artifact through the official renderer and application-owned action policy. Its deterministic source tests and clean three-flow production-browser gate are implemented. That rendered evidence does not change this package's headless certification boundary or certify an external hosted agent.

The runtime export ledger is a2a-library-exports.json. Public root or ./legacy export changes must update it.

License

MIT