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
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
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.
- 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.
- 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.
- 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 CLIFull 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.
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.
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.
generalized_q: “which license for a public repo?”
answer: “Apache-2.0” (verbatim)
tier: critical · asked_count: 4
provenance: repo/qid listall-rights-reserved → superseded
Apache-2.0 → active head
history kept · nothing overwrittenOne 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.
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.
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.
| deploy-bot | standard | answer inline |
| billing | critical | phone only |
| license → Apache-2.0 | answered | phone |
| all-rights → superseded | corrected | reply |
| when blocked on you | ×10 | ▁▂▄▆ |
| which license | ×4 | ▁▁▂▃ |
| @signet hello | captured | — |
| ping me on deploys | captured | — |
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.
One fleet’s questions, measured
of owner interruptions an ask-once bank absorbs
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.887Honest 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.
How a question travels
- 01File
An agent posts the question: text, context, blast tier, its own identity.
- 02Scrub
A fail-closed secret scan runs before anything leaves the machine. No scan, no send.
- 03Deliver
The owner's phone gets the card — buttons plus free-text reply.
- 04Answer
Button or reply; either way it lands append-only on the question's ledger.
- 05Resume
The parked agent unblocks with the answer as context. At most once, ever.
- 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.
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:
“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.”
“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.”
“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.”
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.