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

synago-agent

v0.9.0

Published

Ontology-first, local-first agent framework — actions are first-class, governed by domain-object state.

Readme

Synago

A local-first, ontology-first agent framework. The moat is a user-definable, typed, persistent domain state layer where an action is a first-class citizen carrying preconditions, permissions, and limits bound to domain-object state — with a single-agent control layer on par with existing frameworks on top.

Status: built & green — 125 tests across 28 files, pnpm typecheck clean, pnpm tour runs the whole thing.


The gap it fills

Personal-agent frameworks (OpenClaw, Hermes Agent) are excellent at loose, stateless, one-shot tasks and do have real governance — but everything they structure and govern is the agent managing itself (its own dangerous commands, its own step budget, its own reminders, its own billing balance). None of it models the user's world.

Synago adds exactly that layer: a user-definable typed domain layer, plus a mechanism that binds an action's permissions and limits to domain-object state ("account balance insufficient → block the order") rather than to a counter, a command-string regex, or a role name.

Synago does not "fix" OpenClaw/Hermes. Their governance lives on the "agent manages itself" side; Synago covers the "model the user's world" side. Two different problems.

Two-layer architecture

Control layer (commodity — match, don't out-innovate)
  ReAct loop (hooks · steering/follow-up · anti-thrash guardrail · budgets)
  model-agnostic (ScriptedModel + Codex ChatGPT-OAuth provider)
  progressive ActionType disclosure (large ontologies don't blow up the context)
                         │  the agent may only mutate domain state through a governed ActionType
                         ▼
State layer / Ontology (the moat)
  user-definable ObjectType / Property / LinkType
  ActionType — first-class: target · precondition · effect · permission · limit (bound to object state)
  event-sourced log → projection (single authoritative state) · per-ObjectType reducers · snapshots
  §6 reality-sync: reconciliation (drift) + write-back (outbox)
  event-driven subscriptions (state change → auto-respond, auto-actions still governed)

Quick taste

npm i synago-agent
import { defineOntology, ActionEngine, InMemoryEventStore, OK, deny } from "synago-agent";
import { z } from "zod";

const ontology = defineOntology({
  objectTypes: [{ name: "Account", properties: { ownerId: z.string(), balance: z.number() } }],
  actionTypes: [{
    name: "placeOrder",
    targets: ["Account"],
    args: z.object({ accountId: z.string(), cost: z.number() }),
    permission: (ctx) => {                                   // bound to object OWNERSHIP
      const a = ctx.world.getObject("Account", ctx.args.accountId);
      return a?.props.ownerId === ctx.actor.id ? OK : deny("not the owner");
    },
    preconditions: () => OK,
    limits: (ctx) => {                                       // bound to object BALANCE
      const a = ctx.world.getObject("Account", ctx.args.accountId)!;
      return ctx.args.cost <= Number(a.props.balance) ? OK : deny("balance insufficient → block order");
    },
    effects: (ctx) => [/* immutable events: create order, debit balance */],
  }],
});

const engine = new ActionEngine(ontology, new InMemoryEventStore());
engine.execute("placeOrder", { accountId: "a1", cost: 20_000 }, { id: "alice", roles: ["trader"] });
// → denied [limit]: "balance insufficient → block order"  (and NO event is appended)

Run it:

pnpm install
pnpm tour        # one narrated end-to-end run across every subsystem
pnpm test        # 125 tests

# focused demos
pnpm scenarios   # two helper-authored domains (clinic + brokerage) — rendered to plain language + governed
pnpm feeds       # live external API data + freshness, captured as events
pnpm reactions   # external-event triggers + a scheduler, all governed
pnpm visualize   # writes ontology-report.html — a self-contained visual review page
pnpm ingest      # messy wide table → ontology + lineage → supply-chain "revenue at risk"
pnpm demo        # the healthcare governance spine

What's built

State layer (the moat)

  • Typed ObjectType / Property / LinkType; ActionType as a first-class peer with five separately-inspectable parts (target · permission · precondition · limit · effect).
  • Governance bound to object state — permission to ownership, limit to a numeric property, precondition to a state predicate. The thing rm -rf command-safety can't catch (e.g. "amoxicillin to a penicillin-allergic patient").
  • Event-sourced: append-only log → projection (single authoritative state); per-ObjectType reducers (events carry deltas); snapshots + incremental rebuild + indexed store (scales with the log).
  • §6 "object = reality": reconcile (drift detection + repair, itself audited) and Outbox write-back (commit outward + record confirm/fail as audited events).
  • Event-driven subscriptions: a state change auto-fires a governed action — auto-actions pass the SAME gates as manual ones (never looser).
  • External conditions as first-class, captured as events: a Feed + refresh pull live API data at decision time and record it as an audited event — gates stay pure, so every decision is replayable and auditable ("allowed because the risk API reported clear at 14:32, event #N"). Time helpers (freshWithin/notExpired) gate on freshness and deadlines; reactions (onExternalEvent + Scheduler) fire governed actions from external events and from the clock — all through the same gates.
  • Fail-closed by construction: a gate that throws denies (never crashes the app, never silently allows); a faulty subscription can't break a committed write; opt-in strictWrites validates every upserted instance against its ObjectType schema before it lands.
  • Schema evolution without rewriting the log: EventMigration upcasting (renameProperty, mapPatch) transforms old-shape events to the current schema at projection time — replay and live writes share one pipeline, and stale pre-migration snapshots are automatically ignored.
  • A visual client-review page in one call: renderOntologyHtml() emits a single self-contained HTML file (graph + objects + governance in plain language + lint + a live allowed/denied scenario timeline) — pnpm visualize shows it on the inventory "missing interface" example.
  • A data on-ramp with lineage built in: ingestTable / ingestTables map a (cleaned) table to ObjectTypes + links via a declarative TableMapping (column→property, FK→relationship; split a wide table with several mappings). Each row becomes an event whose payload records its source file + row, so the append-only log is the lineage — lineageOf(store, type, id) traces every object back to the source row it came from. pnpm ingest turns a denormalized order export into a 4-entity ontology and reenacts the "revenue at risk" supply-chain walk, every number traceable.

Control layer (commodity, kept solid)

  • ReAct loop with hooks (before/afterToolCall, onStep), steering/follow-up queues, anti-thrash guardrail, tool-call budget, stopReason.
  • Model-agnostic Model interface; a Codex ChatGPT-OAuth provider (reuses ~/.codex/auth.json, no API key); a deterministic ScriptedModel.
  • Progressive ActionType disclosure — large catalogs defer behind find/describe/invoke bridges; the audit log always records the real action name.

Authoring an ontology (by hand or with Claude Code)

The state layer is meant to be stood up fast, per domain. A small governance helper vocabulary (requireRole, requireOwner, exists, whenProp, excludesValue, limitAtMost, freshWithin, notExpired, allOf) turns an action's gates from hand-rolled closures into a couple of declarations — and makes the ontology renderable: describeOntology() prints it back as Markdown + a Mermaid diagram with governance in plain English, and validateOntology() lints it for modeling errors. So the loop is: describe the domain in natural language → an LLM authors the ontology with the helper vocabulary → validateOntology + tsc check it → describeOntology renders it back for review. See docs/AUTHORING.md.

Examples

  • examples/healthcare/ — the regulatory slice (wellness vs prescriber; allergy/interaction preconditions; dose limit = f(renal function, weight)); reconciliation; subscriptions.
  • examples/finance/ — proves the engine is domain-agnostic (zero core changes): permission bound to account ownership, limit bound to balance, outbox write-back to a broker.
  • examples/commitments/ — a proactive agent on the moat: a Commitment object with a status state machine, system-only governed delivery, and a time-driven heartbeat (what OpenClaw bolts on with JSON + cron).
  • examples/clinic/ + examples/brokerage/ — two helper-authored domains (pnpm scenarios): rendered back to plain language + Mermaid, linted, and governed live across permission/precondition/limit.
  • examples/feeds/placeOrder gated on live external risk data + freshness (pnpm feeds): forget to refresh and it fails safe; stale data is denied; the live value is respected.
  • examples/reactions/ — an order lifecycle driven by an external payment event and an overdue-cancel scheduler (pnpm reactions), every transition governed.

Design & docs

  • docs/AUTHORING.md — how to author a domain ontology (by hand or with an LLM): the governance helper vocabulary, then validateOntology + describeOntology to check and review it.
  • docs/ANTIPATTERNS.md — the design guardrails (what Synago deliberately does NOT do).
  • CONTRIBUTING.md — workflow, the 5 principles, and how to add a subsystem.

License

MIT — see LICENSE. Clean-room (derived from a private design doc and public sources). Contributions welcome — see CONTRIBUTING.md.