Skip to main content

Note → Action

You write things down and then never come back to them. This flow is the one that comes back to them for you.

Notes land in your vault the way they always do. Something reads each new one, decides whether it is worth acting on, and if it is, does the work it can do unattended — then hands you back the part only you can answer.

The worked example here is a business idea, because it is the case where the gap between "I had a thought" and "I know whether it's any good" is widest. The shape is the same for any kind of note you want chased down.

The four moves

1. Notes arrive

Nothing changes about how you capture. You write in your editor, on your phone, or by talking at it — it syncs to Nextcloud like it already does. The notes routine pulls the vault down and compiles it into per-directory markdown with an index, which is the form a model can actually read without being handed forty thousand files.

2. Triage — is there anything here?

This is the step that makes the flow worth having, and the step that has to be stingy. Most notes are a grocery list or a meeting time. note-triage asks the gateway one cheap question per new note: is there a real idea in this, or not?

Only new and changed notes are considered — the routine hashes the vault each run and diffs against the last one, so a note is judged when you write it and again when you meaningfully edit it, never on a loop.

Being conservative here is the whole game. A triage step that fires on everything produces a folder of unread reports, which is the problem you started with.

3. Do what can be done unattended

Only for the notes that passed. The routine chains follow-up work — each step is another message in the same queue, so a long job is just a sequence of small ones and you can watch it progress:

  • Market research — who is already doing this, what they charge, where the gap is. Firecrawl turns the pages it finds into something the model can read.
  • A draft plan — the shape of the thing, rough costs, what would have to be true for it to work, and the first three steps.
  • What's already yours — whether anything else in your vault bears on it. Your own past notes are the context no external tool has.

4. Come back with the right questions

The output is not a report you have to read. It is the two or three things the work could not resolve — the questions where your answer changes the conclusion:

You'd need to know whether the licensing applies to resale — do you? And is this a weekend project or the thing you leave your job for? The plan branches hard on that one.

Those get written beside the original note, so the answer lands where the thought started. Answer them and the next run picks up from there.

Why the questions matter more than the plan

An AI can produce a plausible business plan for anything. What it cannot do is know which assumption you are actually uncertain about. Ending on the open questions is what keeps this from being a machine for generating documents nobody reads.

The four routines

The flow is four routines and one cron file. Nothing else — and each one is replaceable on its own, which is the part worth understanding.

RoutineDoesSwap it when
notesPulls the vault down from Nextcloud into /data/notesYour notes live somewhere else
note-triageDiffs the vault, judges each new note, checks it against the ledger, chains the next stepNever — this is the spine
note-develop(default) Researches and drafts one documentYou want the fan-out instead
idea-workup(alternative) Hands the idea to three hermes departmentsYou want one document instead

Setting it up, step by step

1. Pick the quest

./existential.sh quest # pick "Note Triage"

That copies note-triage.md from cron.example/ into cron/. It does not enable anything yet — a routine on disk is invisible until it is listed.

2. Enable the routines

In services/decree/decree/config.yml:

note-triage:
enabled: true
note-develop:
enabled: true

Or, for the department fan-out described below, these instead:

note-triage:
enabled: true
idea-workup:
enabled: true
hermes-dept:
enabled: true
Why edit config.yml and not config.exist.yml

config.exist.yml is the tracked template; config.yml is what your daemon actually reads and is gitignored, so it is yours to edit. A rendered file is never re-rendered.

3. Confirm the hermes profiles exist — fan-out path only

docker exec hermes-agent ls /opt/data/profiles

ai/hermes/entrypoint.sh provisions every profile in ai/hermes/profiles/ on boot, so research and sales should already be there; if not, docker compose up -d hermes-agent. Each department is served at /p/<name>/v1 with its own tools and its own API key — a profile does not borrow the default profile's credential, so an unprovisioned one returns 401.

4. Restart, then watch it do nothing

docker compose restart decree
The first run does nothing, on purpose

It records your vault as seen without triaging. Turning this on with a 5,000-note vault should not fire 5,000 model calls. To scan the backlog once:

docker exec decree decree run --routine note-triage --param TRIAGE_BOOTSTRAP=true

5. Check it before trusting it

docker exec decree decree routine note-triage # the routine's own pre-check
docker exec decree decree run --routine note-triage --param TRIAGE_DRY_RUN=true

A dry run prints a verdict per note and chains nothing. Read a few days of that output before you let it queue real work — and note that a dry run never writes to the ledger, so tuning the criteria cannot poison the "is this new?" check.

Prerequisites

  • Notes landing in /data/notes — activate the Notes Sync quest, or point NOTES_DIR at a vault you already sync
  • Hermes running, or set TRIAGE_API_URL=http://ollama:11434/v1 to talk to Ollama directly (triage and dedupe work fine this way; the departments do not — they are hermes profiles)

Swap the judgment

TRIAGE_CRITERIA is one line of cron frontmatter and it is the entire feature:

TRIAGE_CRITERIA: "a business idea — something the author could plausibly build, sell, or start"

Point it at research questions, writing prompts, house projects, anything. This is the setting that decides what the flow is for.

If it fires too often — the expected first failure — the fix is always to make it narrower and more concrete. "A business idea" is vague; "a product someone would pay for that I could build a first version of in a month" is not.

Is it new? The idea ledger

A good idea gets written down more than once. Triage keeps an append-only ledger at /data/note-triage/ideas.tsv — one line per idea it has already put through, in the words it used to summarize it. When a note passes the criteria, one more cheap call asks whether it is materially the same as something on that list. Duplicates stop there.

2026-08-14T09:11:04Z A tool-rental service for the neighborhood, booked from a phone
2026-08-22T17:40:55Z A newsletter that summarizes local council minutes

The ledger is plain TSV — read it, prune it, or delete a line to let an idea through again.

SettingDefaultDoes
TRIAGE_LEDGERtrueSet false to chain every pass, duplicates included
TRIAGE_LEDGER_MAX100How many past ideas the check sees, most recent first

It fails open: a gateway blip or an unparseable answer means "new". A duplicate workup wastes a run; a dropped one loses the idea for good.

Swap the work

TRIAGE_ROUTINE names what gets chained when a note passes. Two ship.

note-develop — one document

The default. One call, one file: what the idea is, what can be worked out, and the two-to-four questions only you can answer. Works with nothing but a chat model — no profiles, no departments. Output lands in /data/note-triage/output, and is copied beside the original note when NOTE_OUTPUT_RCLONE_DEST is set.

idea-workup — three departments, three answers

TRIAGE_ROUTINE: idea-workup

This one does no model work itself. It writes three outbox messages, each addressed to the department whose hermes profile owns the right tools:

QuestionDepartmentWhy that profile
Who else is already doing this?researchThe only department with web access — search, web, plus Firecrawl and OpenViking
How big is the market?researchSame tools; a separate message so it lands as its own document
What is my value proposition?salesOwns pricing, positioning and customer-facing writing

Each answer arrives as its own file in workspace/ai/:

workspace/ai/tool-rental-competition.md
workspace/ai/tool-rental-tam.md
workspace/ai/tool-rental-value-prop.md

with its own ntfy notification, so you can read the competition answer while the market sizing is still running.

Why three messages and not one prompt

A profile's cost is its tool schemas — the default hermes profile carries every tool at roughly 40,000 prompt tokens per call, while a narrow one costs a fraction of that. Sending each question to the department that already has the right tools is cheaper and better answered than one agent holding everything. It also means each question retries, logs and appears in Grafana on its own. See Routing to Departments.

Writing a third one

TRIAGE_ROUTINE is just a routine name. Write your own, list it in config.yml, and point the cron file at it — the triage half never changes. It receives note_path and note_reason as environment variables. Writing a Routine is the full contract.

Swap the input

Nothing above cares that the trigger was a cron scan of a notes vault. Triage takes text and a name; every input below reduces to the same message. Only the first step changes.

<anything> ──▶ message ──▶ note-triage ──▶ ledger ──▶ idea-workup ──▶ departments

Email

gmail-sync polls Gmail on a cron and archives messages into services/decree/decree/emails/. Point NOTES_DIR at that directory and the same triage runs over your inbox — the criteria becomes "a customer complaint worth escalating" or whatever you actually want caught. See Gmail.

A file you dropped somewhere

Anything written through MinIO fires an object event → the webhook → minio-router, which matches your file processor on a path regex and an optional content gate:

PATTERN="minio:workspace/.*\.md$"
CRITERIA="a business idea"

The processor writes an outbox message and triage takes it from there. No restart — the router reads the processor directory per event. See File Change Processing.

A sensor, or something you said out loud

Home Assistant does not get read by this stack — it reaches out. An automation POSTs the decree webhook, which turns the request body into an inbox message. A doorbell, a temperature threshold, or a voice command all arrive the same way. The HAwake flow is the worked example.

A message on your phone

telegram-ingest polls a bot for new messages and rclones attachments into storage — where, being an object write, they become the file trigger above. See Telegram.

Cost and pacing

Decree runs one message at a time, and the department timeout (AGENT_TIMEOUT) defaults to 900 seconds. A three-question fan-out can therefore take the better part of an hour. It is not stuck — check automations/runs/ or the Grafana Decree Overview dashboard, where each question appears as its own run.

The per-note cost of triage itself is deliberately small: one short call to judge, one more to check the ledger, and only for notes that are new or changed since the last run and longer than TRIAGE_MIN_CHARS. TRIAGE_MAX_NOTES caps how many are examined per run so an import cannot run away with your GPU.

Settings reference

SettingDefaultDoes
TRIAGE_CRITERIAa business ideaThe judgment. The whole point of the flow
TRIAGE_ROUTINEnote-developWhat to chain on a pass — idea-workup, or your own
TRIAGE_DRY_RUNfalseLog every verdict, chain nothing, write no ledger entries
TRIAGE_LEDGERtrueThe "is this idea new?" check
TRIAGE_LEDGER_MAX100How many past ideas that check sees
TRIAGE_MAX_NOTES20Ceiling per run
TRIAGE_MIN_CHARS120Below this a note is skipped without a model call
TRIAGE_MODEL(gateway default)Pin a specific model
TRIAGE_API_URLhttp://hermes-agent:8642/v1Point at Ollama to skip hermes for triage
NOTE_OUTPUT_RCLONE_DEST(unset)Where note-develop's draft is copied, e.g. nextcloud:Notes
FIRECRAWL_URL(unset)Set to http://firecrawl:3002 for note-develop web research

All of it is cron frontmatter. No code changes.

Don't point the output at your vault cache

/data/notes is an rclone sync cache — it is made to match Nextcloud on every notes run, so anything written there is deleted. That is why drafts land in /data/note-triage/output and are copied back to the vault over rclone instead.

What ships and what you write

PartStatus
Vault sync and compilationShips. The notes routine
Detecting new and changed notesShips. note-triage hashes the vault and diffs against the last run
The triage call and the chainShips. note-triage → outbox message → next routine
Knowing an idea is already evaluatedShips. The ledger at /data/note-triage/ideas.tsv
Research, draft, open questionsShips. note-develop, with Firecrawl research when configured
Competition, market size, value propositionShips. idea-workuphermes-dept (research and sales)
Indexing notes for retrievalShips. OpenViking watches directories and keeps them queryable
Notifying youShips. notify → ntfy, or telegram-notify
What counts as worth acting onYours. One line of prompt, and the whole point of the flow

The judgment is deliberately a setting rather than a decision made for you — what counts as an idea worth chasing is specific to you, and a stock answer would get it wrong in a way that is worse than not running at all.