SIGNΞTopen source · Apache-2.0

Your agents will hit questions only you can answer. Signet parks them, brings you the question, and never asks it twice.

The approval rail for AI-agent fleets — open source, and yours to run. An agent that reaches an owner-tier decision parks instead of guessing; your answer resumes it and folds into an ask-once directives bank the whole fleet checks before ever interrupting you again. Every question and answer lands on an append-only, tiered ledger. Self-host it in three commands.

  • open source, Apache-2.0 — self-host it or have it built for you
  • already running — it carries our own machine’s live traffic
  • install in three commands · agent CLI on npm
01 · the rail

A real run, replayed from the ledger

a real run on the live rail, replayed from the ledger · 2026-07-14 · qid app-signet-nosession-12

timestamps from the ledger · playback compressed

02 · install

Install and run it yourself

This is the whole rail, not a client. Open source under Apache-2.0; you need Node and a Telegram bot you create yourself (~2 min via @BotFather). No Postgres, no cloud account, no AI subscription. Three commands from an empty folder to a question answered on your phone.

your agentfleetYOUR MACHINE · LOCALHOSTembedded databaseAPIphone rail (worker)cardyour phone
No cloud account, no hosted services. The database, the API, and the phone rail all run on your machine — the only thing that ever leaves it is the card to your phone.
  1. 01Clone & initPull the repo, then `signet init` — a ~3-minute wizard validates your Telegram bot, captures your chat id, and writes your .env.You get: A configured install. You bring one thing: a bot token from @BotFather.
  2. 02signet upOne command. Installs deps, starts an embedded database (no Postgres), runs migrations, mints + wires the API key for you, builds, and supervises the API and the phone rail together.You get: The whole rail — database, API, worker — running on your own machine. One Ctrl-C stops all.
  3. 03Ask, from any agentAn agent files a question (`signet ask …`); the card lands on your phone; you tap a button or reply; the agent unblocks with your answer.You get: Your fleet interrupts you only when it must — and the answer folds into an ask-once bank so it never asks that again.
$ git clone https://github.com/dprvda/signet && cd signet$ node cli/signet.mjs init# bot token + owner chat + .env — interactive, ~3 min$ node cli/signet.mjs up# installs, migrates, mints the API key, runs everything# (keeps running — open a SECOND terminal for the next step)$ node cli/signet.mjs ask --repo demo --tier standard \  --q "Ship the beta?" --wait# the card lands on your phone; your answer unblocks the CLI

Full setup incl. deploying the API: docs/SELF-HOSTING.md · source and specs on GitHub.

What you get

Never ask twice
Every answer folds into an ask-once directives bank the whole fleet checks first. On our own fleet, 88.7% of owner-tier questions were repeats a bank absorbs.
Never self-approve
external and critical questions block until a human answers — a server-enforced state machine, not a prompt convention.
Append-only ledger
Every question and answer lands with tier and provenance. Corrections are new rows; nothing is ever overwritten.
No keys to buy
Runs on an embedded database (no Postgres install) and needs no AI subscription — the directive generalizer degrades to verbatim folding.

Already running a rail? Point your agents at it — npm i -g @pravda-systems/signet — or drop in the one-file agent skill (Claude Code, Codex, or any fleet).

Prefer it built for you against your own fleet? Request an implementation.

Your fleet interrupts you only when it must.

03 · the machinery

Under the hood

How it answers without interrupting you, how the bank grows, and how it holds up when a whole fleet leans on one phone.

Checking the bank never reads your answers with AI

Before an agent interrupts you it asks the bank: has a version of this already been answered? That check is a Postgres full-text + trigram lookup — deterministic, indexed, no model. A bank of fifty directives or fifty thousand is the same fast query; nothing “reads them all.” A recorded answer comes back only when its tier covers the question, and a critical question never auto-answers — it rides to your phone with the match attached as a hint. The only place AI touches the bank is off the hot path: the worker reranks candidates asynchronously as a suggestion, never an auto-answer.

try it — canned data, no backend
query
what license do we put on a repo before making it public?
Postgres FTS + trigram · deterministic · no model
bank hit — no card, no interruption
directive: What license should the public repo use?
your recorded answer: All rights reserved (read-only)
the agent proceeds; the hit is recorded with who asked
strings verbatim from the recorded run on the live rail (app-signet-nosession-12)

Measured on our own bank: 100% match precision (it never mis-answers) at 68.4% recall on paraphrased repeats (v1.1) — anything it is unsure of files through to you. Figures trace to docs/METRICS.md.

The bank grows itself — append-only

Every answer folds into a directive automatically. One model call generalizes the question and keeps your exact words where the words are the rule, tagging tier, provenance, and an asked_count. A repeat bumps that count instead of duplicating. Change your mind and a new answer mints a new directive and marks the old one superseded — nothing is ever edited, newest word wins, the full history stays. One-off answers (“send it now”) park as transactional and never pollute matching. No AI key? It folds verbatim.

a folded directive
generalized_q: “which license for a public repo?”
answer: “Apache-2.0” (verbatim)
tier: critical · asked_count: 4
provenance: repo/qid list
a correction (append-only)
all-rights-reserved  → superseded
Apache-2.0  → active head
history kept · nothing overwritten

One owner, every project

Every repo and every agent files to one org rail with one shared bank. An answer you give for one project answers the next project’s agent before it ever reaches you — on our own fleet, 19 of 30 standing directives were asked independently by all ten repos. Cross-repo hits are recorded with which repo asked. You get one phone, one chat, for the whole fleet.

one shared bank19 of 30 directives asked by all ten

Many agents, one bot, no chaos

Dozens of agents can ask at once. Questions sit in a Postgres queue with an atomic claim plus a lease and heartbeat, so a single worker sends each card exactly once — crash or restart, no duplicate cards. Your button or reply routes back to the exact agent parked on that question, even with many cards in flight at the same bot.

MANY AGENTSpostgres queueatomic claim · lease + heartbeatONE WORKER · ONE BOTeach card exactly onceONE PHONEYOUR REPLY → THE EXACT AGENT THAT ASKED
04 · the console

See everything

A private web console ships with it, owner-only. Four windows onto the same live rail your agents talk to: the queue of open questions, the append-only ledger with corrections shown as supersessions, the directives bank with each rule’s asked_count and a hit sparkline (the compounding curve), and your captured notes. Answer standard questions straight from the web; external and critical stay phone-only — enforced on the server, not the screen.

signet console — localhost · owner-only
Queueopen questions
deploy-botstandardanswer inline
billingcriticalphone only
Ledgerevery answer, append-only
license → Apache-2.0answeredphone
all-rights → supersededcorrectedreply
Bankdirectives · asked_count · hits
when blocked on you×10▁▂▄▆
which license×4▁▁▂▃
Notesowner capture net
@signet hellocaptured
ping me on deployscaptured

Self-hosting? The console runs on localhost with a one-time sign-in link — machine possession is the credential, no hosted auth required.

88.7% of owner interruptions are repeats an ask-once bank absorbs.

05 · the evidence

One fleet’s questions, measured

0.0%

of owner interruptions an ask-once bank absorbs

0owner interruptions generated
0standing directives they collapse to
Each mark is one measured owner interruption from our own 10-repo fleet — 265 of them. The gold marks are the 30 standing directives they collapse to; every other mark is a repeat an ask-once bank answers without you.

measured on our own 10-repo fleet’s mined ask history — every figure on this page traces to a row in docs/METRICS.md

asks ≈ sessions × 0.81 absorbed ≈ asks × 0.887

Honest label: 88.7% is what an ask-once bank can absorb in principle, measured on history. The shipping v1.1 matcher catches 68.4% of paraphrased repeats at 100% precision — it never mis-answers; misses file through to the owner.

06 · the protocol

How a question travels

agentRESUMEDSCRUB GATEno scan, no sendowner's phonethe cardbuttons + replySEALEDappend-only ledger rowRESUMETHE BANK · +1
  1. 01File

    An agent posts the question: text, context, blast tier, its own identity.

  2. 02Scrub

    A fail-closed secret scan runs before anything leaves the machine. No scan, no send.

  3. 03Deliver

    The owner's phone gets the card — buttons plus free-text reply.

  4. 04Answer

    Button or reply; either way it lands append-only on the question's ledger.

  5. 05Resume

    The parked agent unblocks with the answer as context. At most once, ever.

  6. 06Compound

    The answer folds into the directives bank. The next agent that asks gets it without you.

standard
naming, scope, design forks. On timeout the agent proceeds on best judgment and the assumption is recorded for overrule.
external
anything that touches a stranger or publishes. Blocks until a human answers. Never self-approves.
critical
money, deletion, credentials, irreversible acts. Blocks. Never self-approves. Loud.

The never-self-approve rule is a server-enforced state machine, not a prompt convention.

07 · the source

Read how it’s built

Signet is built spec-first: the spec corpus and decision log are the product docs, open in the source. A few load-bearing excerpts:

NORTHSTAR §4 — the moat
Every answered question becomes a directive: the generalized question, the owner's verbatim answer, tier, provenance, asked_count. The bank is the org's accumulated management judgment, queryable by any agent.
DECISIONS D-015 — cutover
Signet carries this machine's live HITL traffic. The ask that migrated the rail rode the new rail — approved by the owner on Signet's own card.
METRICS — the binding law
Every number rendered on any surface traces to a verified measurement recorded here with its source, method, and date. A figure not in this file does not ship.
08 · by request

Request an implementation

Signet is open source — self-host it in three commands (above). If you’d rather have it fitted for you, we propose a bespoke implementation against your fleet, by request. Either way your agents speak to it through the @pravda-systems/signet CLI on npm (Apache-2.0). Its first user is our own ten-repo fleet, which it has carried in production since 2026-07-14.

request an implementation