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

@crewrouter-agent/node

v1.0.0

Published

Deployment-neutral Node.js agent runtime for private, structured LLM workloads.

Readme

CrewAgent

CrewAgent is a small, deployment-neutral Node.js library for running structured LLM advice behind a private network boundary. It provides the shared mechanics around a model without claiming authority over the business system using it.

Author and attribution

CrewAgent is authored and maintained by Casey Stalnaker. Learn more at caseystalnaker.com.

The model recommends. Deterministic application code decides what is valid and performs any real action.

Status: the checked-out source identifies itself as 1.0.0, the first stable CrewAgent package line. The serialized advice contract remains version 2, service metadata remains schema version 1, and the unpublished 0.2.1 and 0.3.0 archives remain historical downstream checkpoints.

Why this exists

Most LLM integrations combine provider access, prompts, product rules, and mutation logic in one place. That makes provider changes expensive, failure behavior unclear, and proprietary application logic easy to leak.

CrewAgent keeps those responsibilities separate:

| Public library | Private application or deployment code | |---|---| | Versioned request and response contract | Product context construction and data minimization | | Authenticated HTTP client and server | CrewAgent prompts and agent definitions | | Runtime orchestration and response validation | Company policies and deterministic thresholds | | Ollama provider adapter | Route, schedule, notification, and other actions | | Reference grounding and safe public errors | Audit persistence and dispatcher approval workflow |

The public OSS project name is CrewAgent. The published npm package name is @crewrouter-agent/node. The available publication scope does not change the library's deployment-neutral design or limit it to one downstream consumer. The implementation is intentionally general enough for other structured advisory workloads.

Architecture

Private application
  -> createAgentClient
  -> HTTPS + bearer authentication
  -> createAgentServer
  -> createAgentRuntime
  -> private agent definition (prompt, schema, allowed refs)
  -> createOllamaProvider
  -> Ollama + chosen model

Validated advice returns to the private application
  -> product-specific validation
  -> human review or deterministic policy gate
  -> existing application services perform approved actions

The same service can run on owned hardware, a VPS, a private cloud host, or a developer machine. Location is deployment configuration, not part of the contract.

Downstream deployment support

The first CrewRouter downstream deployment composes this public library in private service and operator repositories. That deployment currently uses an authenticated private ingress, an independently supervised service, a local Ollama runtime, and a separate operator control plane for readiness checks.

Those choices are deployment support, not public package requirements. This repository should continue to document the reusable contract, runtime, client, server, provider, and validation behavior only. Product-specific context builders, prompts, Cloudflare configuration, host manifests, rollout gates, and operator runbooks belong in the private CrewRouter and CrewAgent Operator repositories.

Install From npm

npm install @crewrouter-agent/node

The stable support target is the Node.js 22 and Node.js 24 LTS lines, expressed as ^22.0.0 || ^24.0.0; the package has no runtime dependencies. Node.js 20 is excluded because its upstream support has ended. CI runs the complete tests and package-content check on both supported majors. A future LTS major may be added in a backward-compatible release after the same checks pass; removing a still- supported major requires a new CrewAgent major release.

The first stable package release is 1.0.0. The earlier unpublished 0.2.1 and 0.3.0 archives remain exact private-integration checkpoints and will not receive separate npm publications. See 1.0 release readiness for the release evidence.

For source-level development against this repository, use this workspace directly instead of installing the published package into itself.

Use From npm

Import from the root package for the common client, server, runtime, provider, and contract helpers:

import {
  AGENT_CONTRACT_VERSION,
  createAgentClient,
} from "@crewrouter-agent/node";

Subpath imports are also supported when you want a narrower entry point:

import { createAgentClient } from "@crewrouter-agent/node/client";
import { AGENT_CONTRACT_VERSION } from "@crewrouter-agent/node/contracts";

Public API

The root package exports the client, server, bearer authentication helper, runtime, Ollama provider, advice-contract constants and validators, metadata schema constants and limits, schema helper, and stable error classes. Focused imports are available through these public subpaths:

@crewrouter-agent/node/client
@crewrouter-agent/node/contracts
@crewrouter-agent/node/errors
@crewrouter-agent/node/providers/ollama
@crewrouter-agent/node/runtime
@crewrouter-agent/node/server

The package API and the serialized contract have separate compatibility concerns. contractVersion changes only when the transport envelope changes.

Run the example service

The included example registers a deliberately generic agent; it does not contain production prompts or product logic.

APPLICATION_VERSION='1.0.0' \
AGENT_TOKEN='replace-with-a-long-random-secret' \
OLLAMA_MODEL='gemma3:4b' \
node examples/basic-server.js

Optional environment variables:

HOST=127.0.0.1
PORT=3210
OLLAMA_BASE_URL=http://127.0.0.1:11434
AGENT_TIMEOUT_MS=30000

Put TLS and network access controls in front of the service for any non-development deployment. Do not expose Ollama directly.

createOllamaProvider retains Ollama's default model keep-alive behavior unless the composition sets the literal boolean unloadAfterResponse: true. That option sends keep_alive: 0 with each completed chat request so Ollama unloads the model after responding. It trades warm-request latency for bounded host memory and does not change the serialized CrewAgent advice contract.

Call the service

import {
  AGENT_CONTRACT_VERSION,
  createAgentClient,
} from "@crewrouter-agent/node";

const client = createAgentClient({
  baseUrl: "https://agent.example.com",
  maxResponseBytes: 1_000_000,
  token: process.env.AGENT_TOKEN,
  timeoutMs: 30_000,
});

const result = await client.advise({
  contractVersion: AGENT_CONTRACT_VERSION,
  requestId: crypto.randomUUID(),
  agentId: "example-risk-review",
  contextVersion: "example.workday.v1",
  context: {
    refs: ["work_1", "signal_1"],
    work: [{ ref: "work_1", window: "09:00-11:00" }],
    signals: [{ ref: "signal_1", summary: "Heavy rain possible" }],
  },
}, {
  allowedRefs: ["work_1", "signal_1"],
});

Passing allowedRefs to the client repeats grounding validation at the caller boundary. The service also validates references before returning a response.

Contract

Requests use a library contract version and a separate product context version:

{
  "contractVersion": "2",
  "requestId": "req_123",
  "agentId": "example-risk-review",
  "contextVersion": "example.workday.v1",
  "context": {}
}

Responses are structured, correlated, and grounded:

{
  "contractVersion": "2",
  "requestId": "req_123",
  "assessment": "watch",
  "summary": "Conditions may affect the current plan.",
  "recommendations": [
    {
      "kind": "review",
      "affectedRefs": ["work_1"],
      "rationale": "The supplied signal overlaps the work window.",
      "evidenceRefs": ["signal_1"],
      "confidence": 0.8,
      "payload": {}
    }
  ]
}

payload is intentionally opaque to the base contract. An agent that returns one must validate it with validateResponse; the library never executes it.

Agent definition

An agent definition supplies five pieces:

  • agentId: stable public selector for the workload.
  • contextVersions: a nonempty, sorted, duplicate-free list of the private context versions this active definition accepts.
  • buildPrompt: creates model messages, a JSON schema, and the complete allowedRefs set.
  • parseResponse: optional parser when a provider does not return plain JSON content.
  • validateResponse: a second deterministic validation pass for agent-specific recommendation-kind, payload, and other semantic rules.

Use createAgentResponseSchema({ requestId, recommendationKinds }) to keep generated output aligned with the base contract.

The generated schema intentionally leaves string-length limits to the runtime's mandatory deterministic response validation because Ollama's structured-output grammar rejects those otherwise valid JSON Schema keywords. Collection and numeric constraints remain in the generation schema; every public contract limit is still enforced before a response can be returned.

Production agent definitions belong in private deployment composition, not in this public repository. Any definition that introduces a product-specific payload must reject invalid payloads deterministically before advice can leave the runtime; model schema generation alone is not an authorization or validation boundary.

Every agent definition must implement validateResponse. JSON Schema permits composition through mechanisms such as $ref and allOf, so the runtime does not attempt to infer whether an arbitrary generation schema contains private semantic constraints. The hook receives a base-contract-valid, correlated, grounded, deeply frozen response and returns { ok: true } to accept it; every other result or attempted mutation rejects the response without exposing validator details. A deliberately generic agent may return { ok: true } after explicitly deciding that base validation is its complete deterministic rule set.

The runtime validates and snapshots contextVersions when an agent is registered. A request with another context version is rejected before prompt construction or provider work. Identifiers are bounded lowercase ASCII values; one agent may declare at most 16 context versions. The frozen getAgentMetadata() runtime accessor returns only sorted agent and context identity, never prompts, schemas, model configuration, or request data.

The example service demonstrates both halves of the boundary: its generated schema guides the model toward the review kind and a bounded priority payload, while validateResponse independently enforces those exact constraints after generation.

An integrating product may be the first downstream consumer of CrewAgent without becoming the package's naming or governance identity.

Service metadata

Every server composition supplies its own canonical numeric semantic version:

const server = createAgentServer({
  applicationVersion: "1.4.0",
  auth,
  maxConcurrentAdvice: 1,
  runtime,
});

applicationVersion identifies the deployed application composition, not the version of this npm package. A production composition should derive it from its immutable package or release manifest instead of duplicating an editable environment label.

Authenticated GET /v1/metadata returns one exact, no-store response:

{
  "schemaVersion": 1,
  "applicationVersion": "1.4.0",
  "contractVersion": "2",
  "agents": [
    {
      "agentId": "example-risk-review",
      "contextVersions": ["example.workday.v1"]
    }
  ]
}

The server derives contractVersion from CrewAgent itself and takes the sorted agent/context list from the active runtime registry. It rejects invalid or oversized identity configuration instead of truncating it, and a successful body cannot exceed 16 KiB. The endpoint uses the same bearer authentication as advice; it is unauthenticated only when the entire server explicitly enables isolated development mode. /healthz and /readyz remain unauthenticated and minimal. Metadata never includes timestamps, host or process details, paths, model/provider configuration, prompts, schemas, request context, or secrets.

The authenticated client performs the same exact validation without invoking an agent or loading a model:

const metadata = await client.metadata({ signal });

Client requests refuse redirects so authentication headers cannot follow a cross-origin redirect. Metadata uses the smaller of the configured client response limit and its fixed 16 KiB protocol ceiling.

Telemetry

The runtime accepts an optional non-blocking telemetry sink:

const runtime = createAgentRuntime({
  agents,
  provider,
  telemetry: {
    emit(event) {
      telemetryBuffer.push(event);
    },
  },
});

Each validated request emits one frozen agent.request.completed event. Its allowlisted fields are requestId, agentId, contract and context versions, duration, outcome, optional stable error code, provider kind, and model identifier. Events never contain context, prompts, recommendations, model content, provider bodies, or error messages. Telemetry failures do not affect advice. Error codes come only from CrewAgent's fixed runtime mapping; arbitrary properties on thrown values are ignored.

The HTTP server separately accepts httpTelemetry: { emit(event) {} }. It emits frozen accepted/completed lifecycle events for metadata and advice using only route class, outcome, status, duration, optional stable error code, and validated agent/context identity. HTTP telemetry deliberately excludes request IDs and all request or response content. Sink failures never alter HTTP behavior.

maxConcurrentAdvice defaults to unbounded for compatibility. A private composition may set a positive integer; excess authenticated advice requests fail immediately with 503 service_busy and are not queued or retried.

Test against Ollama

Normal tests replay synthetic recorded completions and do not require a model host. Run the opt-in live test with an installed Ollama model:

OLLAMA_INTEGRATION_MODEL='gemma3:4b' npm run test:ollama

Set OLLAMA_INTEGRATION_BASE_URL when Ollama is not available at http://127.0.0.1:11434, and use OLLAMA_INTEGRATION_TIMEOUT_MS to change the default 60-second budget. The integration prompt and context are synthetic and contain no product policy or customer data.

Security posture

  • Client and server fail closed when no bearer token is configured. Unauthenticated mode must be the literal boolean true and is only for isolated development; authentication callbacks grant access only with literal true.
  • Health and readiness endpoints contain no customer or model data.
  • Service metadata requires the advice bearer outside explicit development mode and exposes only bounded application, public-contract, agent, and accepted-context identity.
  • Request bodies are size-limited and response fields are bounded.
  • Client and provider response bodies are byte-limited before JSON parsing, and their timeouts cover body consumption.
  • Model output cannot cite references outside the set supplied by the agent.
  • Only a fully contract-valid request ID may enter server correlation logs or error responses, and response IDs must round-trip exactly.
  • Provider and model-validation failures are reduced to stable, non-sensitive logs and public errors.
  • Invalid request envelopes never reach a custom runtime. Unknown thrown values cannot choose a public status, code, exposure, message, or telemetry code.
  • Custom HTTP loggers are observational; synchronous throws and asynchronous rejections cannot replace readiness or advice responses.
  • API paths are not treated as secrets. TLS, authentication, token rotation, network isolation, and data minimization are the security controls.
  • The model host should be reachable only by the agent service. Ollama should not be internet-facing.

Bearer authentication is the first transport mechanism, not the final word on edge security. ADR-018 accepts TLS, Cloudflare Access, and an independent bearer token for the first private topology; signed requests are optional future defense in depth, not a 1.0.0 requirement. Other deployments may add IP allowlists, rate limits, mTLS, signed requests, or equivalent private-network controls without changing the agent contract.

Failure behavior

The agent is expected to be additive. A timeout, unavailable model, malformed response, invented reference, or failed readiness check must cause the caller to skip advice and continue its deterministic workflow.

This library does not implement retries or automatic actions. Retry budgets, idempotency, persistence, rollout modes, and action approval belong to the integrating application because they depend on business semantics.

Project memory

Future work should update these documents in the same change as any architectural or contract decision.

Contributing

See CONTRIBUTING.md. Please report security issues through the private process in SECURITY.md, not through a public issue.

Release notes are maintained in CHANGELOG.md.

License

Copyright © 2026 Casey Stalnaker.

Apache License 2.0. See LICENSE and NOTICE.