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

@takk/glasshouse

v1.0.0

Published

Observability and a transparent, auditable agent graph for Massive Intelligence (IM) swarms: OpenTelemetry-compatible span tracing, incremental drift detection, failure attribution, loop detection, thirteen alert channels, and SHA-256-chained, Ed25519-sig

Readme

Glasshouse

status: stable license version node tests coverage runtime deps

Star History Chart

Observability and a transparent, auditable agent graph for Massive Intelligence (IM) swarms. Wrap each agent's work in a span, then read the glass: the agent graph, the per-step cost, drift on the metrics that matter, the root cause of a failure, the loops that waste tokens, OTLP export to any collector, and a tamper-evident, signable trace, all from a zero-dependency, node-free core that runs on your own infrastructure, including the EU.

Glasshouse is the observability satellite of the open multi-agent ecosystem, Briefing 5 of the @takk8is "Fugu open-source". A closed multi-agent endpoint is a black box: you cannot see which model answered, you cannot audit the path the answer took, and you cannot price the steps that produced it. Glasshouse is the glass house. It exposes the agent graph, the per-step decisions, and the per-step cost, it is OpenTelemetry-native, and it runs in your process on your infrastructure, not someone else's. The mental model is a real-time x-ray of the swarm: you watch each agent think, call a tool, and spend tokens.

Core promise: zero required runtime dependencies, a two-line setup, a node-free core that runs on Node, Bun, Deno, Cloudflare Workers, Vercel Edge, and the browser over Web Crypto, seventeen export entry points (the root aggregate plus sixteen subpaths) plus a CLI, an OpenTelemetry-native span model that flows into Langfuse, Arize, Datadog, or any OTLP collector, an agent graph that renders to Mermaid, Graphviz DOT, or a self-contained offline HTML viewer, streaming O(1) drift detection, heuristic failure attribution and loop detection, thirteen alert channels, head and tail sampling, default-on redaction, a SHA-256 audit chain, and Ed25519-signed snapshots, all over Web Crypto with no node:crypto in the core, and ESM plus CJS dual distribution.


Why Glasshouse

Observing a multi-agent swarm is a transparency problem with a sovereignty constraint. You want to know exactly what the swarm did, which agent thought what, which model it called, what it cost, where it looped, and why it failed, without shipping your traces to a vendor that holds them, prices them, and may not be available in your region. The two reflexive answers both fall short. A closed multi-agent endpoint hides the routing behind one call, so the path is unauditable by construction. A hosted observability SaaS makes you export every span off-box before you can see it. Glasshouse takes the correct shape: the measurement runs in your process, over the spans you already produce, on infrastructure you control, and exposes the whole graph as a value you can log, render, diff, and seal.

What sets it apart from a closed endpoint and from a hosted tracing SaaS:

  • Transparent by construction. The agent graph is the receipt. Every run exposes each agent's spans, tokens, cost, errors, and models, and the handoff edges between agents. Nothing about the composition is hidden.
  • Auditable path. Every finished span carries a SHA-256 content hash, and an optional audit chain links those hashes into a tamper-evident SHA-256 chain. A snapshot can be sealed with an Ed25519 signature. When an answer is questioned, you have the evidence a review asks for.
  • OpenTelemetry-native. Spans map to and from OTLP/JSON and fill the GenAI semantic-convention attributes, so a Glasshouse trace flows into Langfuse, Arize, Datadog, or any OTLP collector, and spans those tools emit flow back into the model.
  • Sovereign and local-first. The core is node-free and runs anywhere Web Crypto does, including the EU. No vendor in the middle of every call, no region block, no telemetry phoned home.
  • Honest measurement. Glasshouse measures and exposes what the swarm did. It does not run models or reach the network in its core; the edge exporter uses fetch by design. Drift detectors measure metric drift on numeric streams (latency, cost, tokens, error rate), not model quality. The package is clear about what it does and does not claim.
  • Production-shaped. Streaming drift detection that is O(1) per point, head and tail sampling, default-on redaction, thirteen alert channels, and a CLI for offline forensics over a trace file.
  • Zero dependencies. Nothing to audit transitively, nothing to break on a supply-chain advisory. The core has no runtime dependencies at all.

Install

pnpm add @takk/glasshouse
# or: npm install @takk/glasshouse
# or: yarn add @takk/glasshouse
# or: bun add @takk/glasshouse

The core has zero required runtime dependencies. Every @takk sibling is an optional peer; @takk/caduceus (transport) and @takk/coryphaeus (orchestrator) are optional companions in the ecosystem, and Glasshouse installs and runs standalone without either.


Quickstart

import { createGlasshouse } from "@takk/glasshouse";

const gh = createGlasshouse();

// Wrap each agent's work in `observe`. It starts a span, captures success,
// error and timing, and ends it for you. Nest children to build the swarm tree.
await gh.observe(
  "plan",
  async (span) => {
    span.setAttribute("task", "fix the failing test");

    await gh.observe(
      "research",
      (child) => {
        child
          .setModel("gpt-mini", "openai")
          .setUsage({ inputTokens: 220, outputTokens: 90, costUsd: 0.004 });
      },
      { kind: "llm", agentId: "researcher", parent: span },
    );

    await gh.observe(
      "apply",
      (child) => {
        child.setUsage({ inputTokens: 60, outputTokens: 200, costUsd: 0.006 });
      },
      { kind: "tool", agentId: "fixer", parent: span },
    );
  },
  { kind: "agent", agentId: "orchestrator" },
);

console.log(gh.spans.length); // every finished span, in end order
console.log(gh.totals());     // { inputTokens, outputTokens, totalTokens, costUsd }
console.log(gh.mermaid());    // the agent graph as a Mermaid flowchart

createGlasshouse returns the facade most callers hold. On top of the spans you observe, it gives you the agent graph, loop detection, failure attribution, token and cost totals, an optional audit chain, OTLP export, and signed snapshots, all node-free.


Span kinds

A span carries the kind of work it represents, so the graph reads like the turn it traced. The ten kinds mirror a multi-agent turn:

| Kind | What it marks | |---|---| | agent | An agent's whole turn, the parent of the rest. | | reasoning | A thinking or planning step. | | llm | A model call, annotated with model, provider, and token usage. | | tool | A tool or function invocation. | | memory | A read from or write to memory. | | state | A state transition. | | decision | A branch or routing choice. | | verification | A check of another agent's output. | | handoff | Work crossing from one agent to another. | | custom | Anything else; the default kind. |

Every finished span is immutable and carries a tamper-evident SHA-256 content hash over its canonical form, computed with createSpan and checkable with verifySpanHash.


The auditable agent graph

The agent graph is the "glass" in Glasshouse. Given the spans of a trace, buildAgentGraph collapses them into the swarm's agents, aggregates each agent's spans, tokens, cost, errors, time, and models, and draws an edge wherever work crossed from one agent to another. It detects cycles and renders to Mermaid, Graphviz DOT, or plain JSON for a dashboard.

import { buildAgentGraph, findCycles, hasCycle, toDot, toMermaid } from "@takk/glasshouse";

const graph = buildAgentGraph(gh.spans);
graph.nodes;            // one node per agent, with tokens, cost, errors, models
graph.edges;            // handoff edges between agents, with counts
toMermaid(graph);       // paste into any Mermaid renderer
toDot(graph);           // paste into any Graphviz DOT renderer
hasCycle(graph);        // true when the swarm handed work back in a cycle
findCycles(graph);      // each cycle as an ordered list of agent ids

The facade exposes the common paths directly: gh.graph(traceId?) and gh.mermaid(traceId?). This is the answer to the loudest criticism of a closed endpoint, that its routing is a black box. Here the whole arrangement is a value you can log, render, diff, and review.


Failure attribution

When a multi-agent run ends wrong, the hard question is who failed and when. attributeFailure answers it heuristically: it finds the error spans, distinguishes a leaf origin (the failure that started the cascade) from the downstream errors that merely inherited it, ranks the spans by blame, and names a likely root-cause span and the culprit agent.

import { createGlasshouse } from "@takk/glasshouse";

const gh = createGlasshouse();

const orchestrator = gh.startSpan("orchestrate", { kind: "agent", agentId: "orchestrator" });
const worker = orchestrator.startChild("call-tool", { kind: "tool", agentId: "worker" });
worker.recordError(new Error("schema validation failed"));
await worker.end();
orchestrator.recordError(new Error("child failed"));
await orchestrator.end();

const attribution = gh.attribute();
attribution.failed;        // true
attribution.culpritAgent;  // "worker", the leaf origin, not the orchestrator that inherited it
attribution.rootCause;     // the root-cause span: id, agent, kind, start time, message
attribution.blames;        // every error span ranked by blame, with a reason

The orchestrator's span errored because its child failed, but attribution blames the leaf origin, which is the span you actually need to fix.


Loop detection

A swarm fails quietly when it spins: the same agent redoes the same step, or two agents bounce a task back and forth without progress. These are runtime loops, distinct from the structural parent cycles the span tree rejects. detectLoops finds consecutive repeats and ping-pong between two agents, in the order spans actually ran.

import { detectLoops } from "@takk/glasshouse";

const findings = detectLoops(gh.spans, { repeatThreshold: 3, pingPongThreshold: 2 });
for (const finding of findings) {
  finding.kind;        // "repeat" or "pingpong"
  finding.agents;      // the agent(s) involved
  finding.occurrences; // how many times it spun
  finding.severity;    // "low" to "critical", scaled by the count
}

The facade exposes gh.loops(traceId?, options?) for the same result over a trace.


Drift detection

Multi-agent behavior drifts slowly: latency creeps up, a model starts costing more per call, an error rate climbs. The detectors are streaming and O(1) per observation, so they run cheaply on a live span feed. None of them keep the full history, only running sufficient statistics, which is what makes them usable at production volume. Drift here is metric drift on a numeric stream, not a judgment about model quality.

import {
  RunningStats,
  ZScoreDriftDetector,
  EwmaDetector,
  PageHinkleyDetector,
  populationStabilityIndex,
  psiSeverity,
} from "@takk/glasshouse";

const z = new ZScoreDriftDetector({ threshold: 3, warmup: 20 });
const ph = new PageHinkleyDetector({ delta: 0.5, lambda: 25 });

for (const latencyMs of latencyStream) {
  const zv = z.observe(latencyMs);   // { drifted, statistic, severity, baselineMean, ... }
  const pv = ph.observe(latencyMs);  // { drifted, statistic, mean }
  if (zv.drifted || pv.drifted) {
    // the metric just moved off its baseline
  }
}

// Welford's running mean and variance, the primitive under the detectors.
const stats = new RunningStats();
stats.push(118);
stats.mean; // updated in O(1)

// Population Stability Index between an expected and an actual distribution.
const psi = populationStabilityIndex({ a: 50, b: 50 }, { a: 80, b: 20 });
psiSeverity(psi); // "info" to "critical"

EwmaDetector adds an exponentially weighted moving average with a deviation alarm, for streams where you want a fast-reacting baseline.


OpenTelemetry interoperability

A Glasshouse span maps cleanly to and from an OTLP/JSON span, and the GenAI semantic-convention attributes (gen_ai.request.model, gen_ai.system, gen_ai.usage.input_tokens, gen_ai.usage.output_tokens, gen_ai.agent.id, and more) are filled in from the span's model, provider, and token usage.

import { toOtlpExport, toOtlpSpan, fromOtlpSpan } from "@takk/glasshouse";

const envelope = toOtlpExport(gh.spans, { serviceName: "my-swarm" });
// POST `envelope` to any collector's /v1/traces, or to Langfuse, Arize, or Datadog.

const otlp = toOtlpSpan(gh.spans[0]);   // one span as OTLP/JSON
const back = await fromOtlpSpan(otlp);  // and back into the Glasshouse model, re-hashed

The facade exposes gh.toOtlp(traceId?, options?) for the whole envelope. This is what lets a Glasshouse trace leave your box in the protocol every backend already accepts, and lets spans those backends emit flow back in.


Audit chain and signed snapshots

With auditing on, every finished span's content hash is linked into a SHA-256 chain. Any later edit, reorder, or deletion breaks the linkage, and verification reports the first broken index. A snapshot of the trace can then be sealed with an Ed25519 signature over Web Crypto, so anyone with the public key can prove it is unaltered.

import { createGlasshouse, generateSigningKeyPair, verifySnapshotSignature } from "@takk/glasshouse";

const gh = createGlasshouse({ audit: true });

await gh.observe("plan", () => {}, { kind: "agent", agentId: "orchestrator" });
await gh.observe("verify", () => {}, { kind: "verification", agentId: "tribunal" });

const audit = await gh.verifyAudit();
audit.valid; // true, until any entry is altered

const { publicKey, privateKey } = await generateSigningKeyPair();
const sealed = await gh.sealedSnapshot(undefined, privateKey, publicKey);
await verifySnapshotSignature(sealed); // true

// Tamper with the sealed snapshot and the proof fails.
const tampered = { ...sealed, snapshot: { ...sealed.snapshot, spanCount: 99 } };
await verifySnapshotSignature(tampered); // false

Appends to the chain are serialized internally, so concurrent appends keep the chain valid rather than racing on the head. The AuditChain and verifyChain primitives are exported directly from @takk/glasshouse/audit for use outside the facade.


Redaction

A trace is only safe to ship to a hosted dashboard or a third-party collector once secrets, keys, and personal data are masked. redactSpan and redactSpans apply a policy of redact, hash, or partial actions against attribute keys or scalar values. Hashing is deterministic SHA-256, so a masked value stays joinable across spans without revealing the plaintext.

import { redactSpans, defaultRedactionPolicy } from "@takk/glasshouse";

// Masks credential and identity attributes (api_key, authorization, token, email, user_id, ...).
const safe = await redactSpans(gh.spans, defaultRedactionPolicy());
// `safe` is a fresh, re-hashed set of spans, ready to export off-box.

Each redacted span is rebuilt and re-hashed, so it stays a valid, tamper-evident span after masking.


Sampling

Sampling keeps trace volume affordable without losing the traces that matter. Head sampling decides per trace up front and deterministically, by trace id, so every span of a trace shares the trace's fate and a sampled trace is never half-recorded. Tail sampling looks at a finished trace and keeps it if anything went wrong or ran slow.

import { RatioSampler, AlwaysSampler, NeverSampler, RateLimitSampler, tailSample } from "@takk/glasshouse";

// Head sampling: keep a deterministic 10% of traces, whole.
const head = new RatioSampler(0.1);
head.decide(span); // { sampled, reason }

// Tail sampling: cheap on the happy path, complete on the failures.
const kept = tailSample(gh.spans, { keepOnError: true, keepSlowerThanMs: 2000, ratio: 0.05 });

RateLimitSampler adds a hard ceiling of spans per second; AlwaysSampler and NeverSampler are the trivial poles.


Alerts

When drift, a loop, or a failure crosses a severity threshold, fan an alert out to one or more of thirteen channels. The AlertDispatcher enforces a minimum-severity threshold and never throws on a channel failure; it returns one result per channel so you can see exactly which sinks delivered. Network channels speak their provider's webhook or API shape over the global fetch, which is injectable for tests.

import { AlertDispatcher, consoleChannel, slackChannel, pagerDutyChannel } from "@takk/glasshouse";

const dispatcher = new AlertDispatcher({
  channels: [
    consoleChannel(),
    slackChannel(process.env.SLACK_WEBHOOK_URL ?? ""),
    pagerDutyChannel(process.env.PAGERDUTY_ROUTING_KEY ?? ""),
  ],
  minSeverity: "high",
});

const results = await dispatcher.dispatch({
  title: "Latency drift",
  message: "Agent researcher p95 latency moved off baseline.",
  severity: "high",
  source: "glasshouse",
});

The thirteen channel kinds are console, memory, callback, webhook, slack, discord, telegram, teams, pagerduty, opsgenie, datadog, sentry, and email. A facade configured with a dispatcher exposes gh.alert(alert). A file-backed channel that needs node:fs lives in the node entry point.


Observability as an MCP surface

A trace assistant exposes the swarm's spans, the agent graph, and a span query as Model Context Protocol tools plus a readable resource, all as plain objects that register on any MCP server without an SDK dependency. An agent debugging another agent can ask "show me the graph" or "which spans failed" through the protocol it already speaks.

import { createGlasshouse } from "@takk/glasshouse";
import { createTraceTools, createTraceResource } from "@takk/glasshouse/mcp";

const gh = createGlasshouse();
// ... observe a swarm ...

// A Tracer or a Glasshouse is a valid source: it has a `spans` getter.
const tools = createTraceTools(gh.tracer);
// tools: glasshouse_trace, glasshouse_graph, glasshouse_query
const resource = createTraceResource(gh.tracer);
// register `tools` and `resource` with your MCP server

The three tools return spans as JSON, the agent graph as Mermaid plus structured JSON, and a filtered span query by trace, agent, kind, status, or name substring.


Runtime exporters

The core is node-free, and the two runtime-specific entry points are kept separate so the core stays portable.

// Edge: push spans off the box over `fetch`, with no Node dependency.
import { otlpHttpExporter, fetchSpanExporter } from "@takk/glasshouse/edge";

const gh = createGlasshouse({
  exporters: [otlpHttpExporter("https://collector.example.com/v1/traces")],
});
// Node: persist a trace to disk so it survives a restart with no database.
import { fileSpanExporter, readTraceFile, fileAlertChannel } from "@takk/glasshouse/node";

const gh = createGlasshouse({ exporters: [fileSpanExporter("trace.json")] });
// ... observe a swarm ...
const spans = await readTraceFile("trace.json"); // read it back later, or feed it to the CLI

@takk/glasshouse/edge runs on Cloudflare Workers, Vercel Edge, Deno, Bun, and the browser; otlpHttpExporter speaks OTLP/HTTP JSON and fetchSpanExporter posts raw spans to any endpoint you control. @takk/glasshouse/node is the only surface that touches node:fs; writes are serialized and committed atomically through a temp file and rename.


Entry points

Seventeen entry points plus a CLI, the node-free root aggregate plus sixteen subpath exports, each importable on its own. The root is the node-free aggregate; only node touches a Node built-in.

| Import | What it gives you | |---|---| | @takk/glasshouse | The node-free aggregate: the tracer, the facade, the graph, drift, attribution, loops, alerts, sampling, redaction, audit, signing, OTLP, and MCP. | | @takk/glasshouse/glasshouse | The Glasshouse facade and createGlasshouse: observe, graph, loops, attribute, totals, audit, OTLP, sealed snapshots. | | @takk/glasshouse/tracer | The Tracer, the LiveSpan handle, observe, the SpanExporter seam, and the in-memory exporter. | | @takk/glasshouse/span | The span model: createSpan, verifySpanHash, the tree builders, and totalUsage. | | @takk/glasshouse/graph | buildAgentGraph, findCycles, hasCycle, and the Mermaid and DOT renderers. | | @takk/glasshouse/drift | RunningStats, ZScoreDriftDetector, EwmaDetector, PageHinkleyDetector, PSI. | | @takk/glasshouse/attribution | attributeFailure and the blame, root-cause, and culprit types. | | @takk/glasshouse/loops | detectLoops for repeats and ping-pong. | | @takk/glasshouse/alerts | The thirteen channels and the AlertDispatcher. | | @takk/glasshouse/sampling | RatioSampler, AlwaysSampler, NeverSampler, RateLimitSampler, and tailSample. | | @takk/glasshouse/redaction | redactSpan, redactSpans, and defaultRedactionPolicy. | | @takk/glasshouse/audit | AuditChain and verifyChain, the SHA-256 chain over span hashes. | | @takk/glasshouse/signing | generateSigningKeyPair, signSnapshot, verifySnapshotSignature (Ed25519 over Web Crypto). | | @takk/glasshouse/otel | toOtlpExport, toOtlpSpan, fromOtlpSpan, and the GenAI attribute keys. | | @takk/glasshouse/mcp | createTraceTools and createTraceResource for an MCP server. | | @takk/glasshouse/edge | otlpHttpExporter and fetchSpanExporter, fetch-based, for the edge. | | @takk/glasshouse/node | fileSpanExporter, readTraceFile, fileAlertChannel, the only node:fs surface. |


CLI

Glasshouse ships a glasshouse command-line tool for offline forensics over a trace file. A trace file is a JSON array of spans, as written by the file exporter.

# Build the agent graph from a trace file (Mermaid by default).
npx glasshouse graph trace.json --mermaid   # or --dot, or --json

# Render a self-contained, offline HTML trace viewer (no server, no runtime dependency).
npx glasshouse view trace.json --out trace.html

# Detect runtime loops (repeats and ping-pong).
npx glasshouse loops trace.json

# Attribute a failed trace to a root-cause span and agent.
npx glasshouse attribute trace.json

# Verify a trace end to end: per-span hashes, the Ed25519 signature of a sealed snapshot,
# and the audit chain with --audit. Pin the signer key with --pubkey to prove authorship;
# without it, the signature is only checked against the key embedded in the snapshot.
npx glasshouse verify sealed-snapshot.json --audit chain.json --pubkey signer.json

# Convert the trace file to an OTLP/JSON export envelope.
npx glasshouse otel trace.json

# Print span counts, token usage, and cost totals.
npx glasshouse stats trace.json

# Mint an Ed25519 signing key pair (JWK), printed as JSON.
npx glasshouse keygen

Exit codes are stable: 0 success, 2 usage error, 10 file not found, 20 invalid input, 21 verification failed. Run glasshouse --help or glasshouse --version for the rest. See examples/ for runnable demos that observe a swarm against the built artifact end to end.


How it works, in one paragraph

The Tracer turns running work into finished spans. A LiveSpan is the mutable handle you hold while an agent thinks, calls a model, or runs a tool; the observe wrapper starts a span, runs your function, marks it ok on success or captures the error and marks it error on a throw, and ends it either way. Ending a span seals it into an immutable Span with a SHA-256 content hash over its canonical form. The agent graph reads those spans back: it resolves each span to its agent, aggregates tokens, cost, errors, time, and models, and draws an edge wherever a span's agent differs from its parent's. Attribution walks the error spans to find the leaf origin; loop detection scans the start-time-ordered spans for repeats and ping-pong; drift detectors keep running sufficient statistics over a numeric stream. OTLP export maps every span into the protocol collectors accept, filling the GenAI attributes from model, provider, and usage. With auditing on, each span's hash links into a SHA-256 chain, and a snapshot can be signed with Ed25519. Every cryptographic primitive runs over globalThis.crypto.subtle, never node:crypto, which is what keeps the whole surface node-free, dependency-free, and testable with no network.


What the examples show

The runnable demos in examples/ observe against the built artifact, with every number produced by execution:

  • 01-observe-a-swarm wraps a nested orchestrator, researcher, and fixer in observe, then prints the totals and the agent graph as Mermaid.
  • 02-failure-attribution fails a worker under an orchestrator and shows attribution blaming the leaf origin, not the parent that inherited it.
  • 03-drift-detection feeds a stable latency baseline, then a regression, and reports the index where the z-score and Page-Hinkley detectors first alarm.
  • 04-loop-detection runs a swarm that spins and prints the repeat and ping-pong findings with their severity.
  • 05-otel-export observes a trace and prints the OTLP/JSON export envelope, GenAI attributes filled in.
  • 06-signed-snapshot seals a trace into a SHA-256 audit chain, signs the snapshot with Ed25519, verifies it, then tampers with it and watches the proof break.

Benchmark

benchmarks/observability-throughput.mjs measures the hot paths on an Apple M-series machine. The numbers are approximate and reproducible:

| Path | Throughput (approximate) | |---|---| | Spans created and hashed | about 82,000 per second | | Agent graph over 20,000 spans | builds in about 11 ms | | Audit chain links | about 141,000 entries per second | | Drift detection | about 27,800,000 points per second |

The drift detectors are O(1) per point and the graph builder is linear in span count, which is what makes Glasshouse usable on a live feed at production volume.


Quality

  • 115 tests across 22 suites, all green under Vitest on Node 20, 22, and 24.
  • Coverage: statements 88.48%, branches 85.1%, functions 91.15%, lines 88.48%.
  • Lint clean under Biome.
  • Typecheck clean under TypeScript in maximum strict mode (exactOptionalPropertyTypes, useUnknownInCatchVariables, noUncheckedIndexedAccess, noPropertyAccessFromIndexSignature).
  • publint clean and @arethetypeswrong/cli green across the root and all sixteen subpaths.
  • size-limit within budget on every bundle.
  • Distribution smoke test exercising the compiled ESM and CJS artifacts and the compiled CLI spawned as a single Node process.
  • SLSA provenance on every npm release via a two-step, review-required CI/CD flow.
  • Zero required runtime dependencies; a node-free core that runs on Node, Bun, Deno, Cloudflare Workers, Vercel Edge, and the browser; dual ESM plus CJS; TypeScript-first.

See SPEC.md for the formal specification, public surface, and stability promise.


FAQ

How is this different from a closed multi-agent endpoint? A closed endpoint is one opaque box: you cannot see which model answered, you cannot audit the path the answer took, and you cannot price the steps that produced it. Glasshouse is the glass house. It runs in your process, exposes the agent graph and the per-step cost, maps to OpenTelemetry, and lets you seal and sign the trace. The path is transparent and yours.

Does Glasshouse call any model itself? No. Glasshouse measures and exposes what the swarm did; it does not run models or reach the network in its core. You wrap the work your agents already do in observe, and the only outbound surface is the edge exporter, which uses fetch by design when you choose to push spans off the box.

What exactly do the drift detectors measure? Metric drift on a numeric stream, latency, cost, tokens, or error rate, not model quality. The detectors are streaming and O(1) per point, keeping running sufficient statistics rather than the full history, so they run cheaply on a live feed.

Does this work in Cloudflare Workers, Vercel Edge, Bun, and Deno? Yes. The core is node-free; SHA-256 and Ed25519 run over globalThis.crypto.subtle, not node:crypto. Import @takk/glasshouse or @takk/glasshouse/edge anywhere Web Crypto is present. Only @takk/glasshouse/node requires Node.

Can a non-human entity drive it? Yes. The MCP surface exposes the trace tools (glasshouse_trace, glasshouse_graph, glasshouse_query) and a readable resource as plain objects that register on any MCP server. An agent debugging another agent reads the graph through the protocol it already speaks.

Do I need the other @takk packages? No. Glasshouse installs and runs standalone. @takk/caduceus (transport) and @takk/coryphaeus (orchestrator) are optional companions in the ecosystem, never required.


Contributing

See .github/CONTRIBUTING.md for the contributor guide. Substantive proposals open a GitHub Issue first; trivial fixes can go straight to a PR. All commits require DCO sign-off (git commit -s). Non-trivial contributions are governed by the Contributor License Agreement.

Community and support

  • Issues and feature requests. Open a GitHub issue at davccavalcante/glasshouse/issues. Include the package version, a minimal reproduction, expected versus actual behavior, and where relevant the trace file or the graph() or attribute() output.
  • Security disclosures. Do not open public issues for vulnerabilities. Follow the responsible-disclosure flow in SECURITY.md, contact [email protected] (or [email protected]) with the [SECURITY] prefix.
  • Code of Conduct. This project follows the Contributor Covenant 2.1. Participation in any Glasshouse space implies agreement.
  • Contributions. All non-trivial contributions go through the Contributor License Agreement. Tests, lint, typecheck, and build must be green before review (pnpm verify).

Author

Created by David C Cavalcante, [email protected] (preferred), [email protected] (Takk relay), linkedin.com/in/hellodav, x.com/davccavalcante, github.com/davccavalcante.

Glasshouse is part of a broader portfolio of NPM packages targeting Massive Intelligence (IM) native infrastructure for 2026-2030, built at Takk Innovate Studio. Transparent, auditable observability of black-box model swarms is foundational infrastructure for that era, the glass that lets a fleet of non-human entities act as one without anyone losing sight of how.


Related research by the author

The architectural philosophy behind Glasshouse, exposing every step of a swarm of intelligences while keeping each decision inspectable and provable, echoes the author's research frameworks:

  • MAIC (Massive Artificial Intelligence Consciousness), a systemic intelligence framework designed to coordinate, supervise, and govern large-scale Massive Intelligence ecosystems, providing global context awareness, alignment, and orchestration across multiple models, agents, and decision layers.
  • HIM (Hybrid Entity Intelligence Model), a hybrid intelligence layer that integrates Massive Intelligence systems with human-defined logic, rules, heuristics, and strategic intent, interpreting objectives and structuring decision-making before and after model execution.
  • NHE (Noumenal Higher-order Entity), a non-human cognitive entity with a defined functional identity and operational agency within a Massive Intelligence ecosystem, operating through coordinated intelligence layers while maintaining a non-anthropomorphic identity.

These frameworks are published independently of Glasshouse and are separate works:


Sponsors

Join the journey as the portfolio continues to ship Massive Intelligence (IM) native infrastructure. Your support is the cornerstone of this work.


Privacy

Glasshouse runs entirely inside your own process and infrastructure. It makes no outbound calls to the author, collects no telemetry, and ships no analytics. The only outbound calls are the ones you opt into through the edge exporters and alert channels, to the collectors and sinks you choose. See PRIVACY.md for the full data-handling notice, including how the optional file exporter reads and writes a trace on disk.


License

Licensed under the Apache License 2.0. See LICENSE for the full text and NOTICE for attribution and third-party component licenses. You may use, modify, and distribute the code under the terms of that license, including its patent grant and attribution requirements.