Companion to the system map
How it works
The map shows every node, because the first question is always “is this real?”. This page answers the second one. What shape is the system, how are its parts actually joined, what are the models told — and what happens when a model is wrong.
Nothing here is a summary of the map. It is read from the same live workflows, and the prompts below are complete, not excerpted.
One direction, nightly
The shape
Eight stages. Three of them are a model, two are a person, the rest is code. Each names the workflows that carry it out.
The part that is easy to get wrong
How the parts are joined
Joined by files, not calls
The eleven workflows hardly call each other. There are four direct calls in the whole thing. Everything else is coupled through files on a Drive: one workflow writes a file, another notices it later.
The clearest case is graph.json, and it is worth being precise about it because the diagram makes it look like a loop:
Map Regeneration computes the map once a night and writes it. Serve Map never computes anything — it downloads the last finished graph and builds the viewer around it. The arrow only looks like it comes back because both ends touch the same file.
Why that arrangement saved the map this week
On 26 October the nightly rebuild refused to finish. The clustering step produced a bad partition and a plausibility gate stopped the run before anything was written.
Because the two halves are joined by a file rather than a call, graph.json still held the previous night's good map. The web server carried on serving it. Nobody looking at the site saw anything at all.
That is the property worth noticing: the failure had nowhere to propagate to. A direct call would have had to fail somewhere a visitor could see, or be caught and faked. Here the stale-but-correct artifact is simply still there.
The trade, argued both ways
File coupling is a real trade and it is not free.
What it buys
- A handoff survives the other side being down. If the server restarts while the rebuild finishes, nothing is lost — the file is simply there afterwards.
- No queue, no retry logic, no ordering problem, no backpressure.
- Every intermediate state is an artifact you can open and read. Debugging is reading a file, not reconstructing a message.
- The last good output is always still on disk, which is what makes a refusal safe.
What it costs
- No transaction. Two writers to one file is a race, which is why the topic store has exactly one writer and a lock.
- “Another workflow notices” means eventually, not now.
- Nothing enforces the file's shape. A writer that changes the format silently breaks every reader, so the readers have to validate.
- A file that fails to write leaves the previous one looking current.
The model proposes; code decides; a person approves
Of the nodes in this system, seven call a language model. Everything else is tested code. That ratio is the design, not an accident of scope.
The model is never the last word on anything that gets written. Every prompt below is followed by a parser, and most parsers are followed by a refusal — a named error that stops the run rather than writing something wrong. The owner approves every note before it is filed.
Put the other way round: the model's job is to produce a proposal in a shape code can check. Everything it returns is a draft until something deterministic has looked at it.
Why the counts differ, and which one to believe
There are three numbers on this site for the same handful of requests to a model, and they are all correct. The difference is worth a paragraph, because it is the difference between what a platform ships and what a system does.
7 — calls
Nodes that actually send a request: five agents and two direct calls. This is the number that means something, and it is the one on the map.
11 — nodes from the AI package
The 7 above plus four settings nodes. Counting the package is the easy measurement and the misleading one: it reads as 11 conversations.
An agent holds the prompt and issues the request. The model node wired beneath it holds only the settings — which model, what token ceiling — and does nothing on its own. Together they are two nodes and one request.
Four settings nodes serve five agents, because one of them is shared: a single model node feeds both digest agents. That is also why deleting one connection killed both digests at once, and why the guard that now runs after every deploy checks those edges in both directions.
Of the 7 calls, 6 carry a prompt. The one that does not is transcription: it is handed an audio file and returns the words that were said, so there is nothing to instruct. It is also the only call in the system that is not Claude, and the only one with no parser standing behind it — a transcript has no shape to validate, so the first thing that checks it is the person at the review queue.
Signal, not inventory
The nodes that matter
Of 545 nodes, 88 are shown here. A node earns its place by being a trigger, touching a model, writing a file another workflow reads, standing at the human boundary, or being able to refuse. The other 457 are plumbing — real, necessary, and not interesting at this altitude. The full set is on the map.
Serve Map42 of 264 nodes
Map WebhookArchive List WebhookArchive Snapshot WebhookApprove WebhookRead Review Queue RowPrepare Status UpdateUpdate Row StatusSearch WebhookHome WebhookBuild Home HTMLBridge Page WebhookBridge Create WebhookHelp WebhookDay WebhookStill WebhookTopics WebhookTopics Decide WebhookPrefs WebhookSave PrefAnswers WebhookDecisions WebhookVocab Restore WebhookAct WebhookVerify Intent StoredRewrite Note DomainVerify Note BinnedAnalyse WebhookRespond Analysis BodyStore Restore WebhookPlan New TopicCompose New Topic IntentVerify New Topic IntentFlow WebhookMedia WebhookSort WebhookBrain WebhookNote WebhookRead Note ContentApprove Batch WebhookRead Queue For BatchPrepare Batch StatusUpdate Batch StatusMap Regeneration15 of 112 nodes
Schedule TriggerCluster AgentCluster ModelBuild GraphWrite graph.jsonRead Review Queue For PendingWrite Embeddings.jsonInsight AgentInsight ModelExecute Workflow TriggerMap Dirty TriggerCollect Stale HubsCreate Connections.mdReconcile StoreRead Queue For VocabWaggle Dance9 of 52 nodes
Weekly ScheduleRun Now WebhookRead Review QueueBuild Digest InputDigest ModelEpisode WebhookLatest WebhookDigest Agent PersonalDigest Agent ProfessionalInbox Watcher8 of 43 nodes
Analyze ImageScoutScout ModelAppend Review RowTranscribe AudioSafety Net SweepCapture ArrivedRead Queue For DedupFiling5 of 10 nodes
Safety Net SweepRead Review QueuePrep Sheet UpdateMark Row FiledExecute Workflow TriggerPhone Capture Webhook4 of 20 nodes
Capture WebhookCapture Webhook GETDebug Webhook POSTDebug Webhook GETCapture Audit (listing only)1 of 3 nodes
Audit RequestCapture Backup1 of 11 nodes
NightlyInbox Watcher - Error Handler1 of 6 nodes
Error TriggerSupabase Backup1 of 15 nodes
NightlyTelegram Capture1 of 9 nodes
Telegram TriggerMeasured, not quoted from a brochure
What it is built on
Every row is a count of real nodes in the live workflows. It describes what the system is made of — one automation platform, one person's cloud storage, a database for the mirror, and two model vendors. There is no server to administer, and no application deployed apart from the workflows themselves.
| Logic | ||
| 146 | JavaScript in-workflow | The system itself. Parsing, validating, refusing, building every page served. This is where the behaviour lives. |
| 82 | Branching | Decisions taken in the workflow rather than by a model: has this changed, is this already filed, is this row still waiting. |
| 2 | Flow control | Batching, merging, waiting. The unglamorous half of any pipeline. |
| Storage | ||
| 80 | Google Drive | The substrate. Notes, topic pages, the graph, the embeddings and every original capture are files here, owned outright and readable without this system existing. |
| 14 | Google Sheets | The review queue. One row per proposal, with its status - which is what makes the human boundary a thing you can open and audit rather than a claim in a diagram. |
| 9 | Postgres (Supabase) | A nightly content-hashed mirror of every note and every raw capture. Soft delete only: it is the copy that exists so a mistake upstream is recoverable. |
| Capture & alerts | ||
| 110 | HTTP webhooks | Every surface a person touches is one of these: the home page, the map, the approve route, the capture endpoint. |
| 9 | Telegram Bot API | The capture front door, and the only channel the system uses to reach an operator. A thought arrives as a photo, a voice note or a line of text. |
| Models | ||
| 5 | LangChain agent | The platform wrapper that holds a prompt and calls a model. |
| 5 | Anthropic Claude | Reading, classifying, clustering and writing the weekly digest. Every answer is a proposal that code checks before anything is written. |
| 1 | OpenAI | Transcription only. Voice notes become text; nothing else on this list goes near it. |
| Integration | ||
| 66 | Direct REST calls | Everything the platform has no node for, called straight over HTTP. |
| Orchestration | ||
| 7 | Sub-workflow calls | Both ends of the four places one workflow genuinely invokes another: the calls and the entry points they arrive at. Everywhere else the handoff is a file. |
| 6 | Schedules | The nightly rebuild, the weekly digest, the backups. Nothing here polls for work it could be told about. |
| 1 | Error workflow | One workflow that catches failures from the others, deduplicates them and decides whether a human needs to know. |
| 1 | Drive polling | Watching a folder for anything dropped into it by hand. |
| Other | ||
| 1 | extractFromFile | Pulling text out of a PDF. |
The models, counted by the calls that use them, and what each call is allowed to spend:
| 6 | claude-sonnet-5 | ceiling 8000, 12000 tokens (and one call with none set) |
| 1 | transcription, no model named | no ceiling set |
Everything it talks to, counted by how many nodes call each one:
Complete, not excerpted
Every prompt, and what goes with it
7 nodes call a model; 6 of them carry a prompt. Each is shown whole, with the model it runs on, the budget it has, the live data poured into it (highlighted), what reads its answer, and what refuses if the answer is wrong.
This image is being filed into a personal knowledge-management system. Identify what it is and record what is worth keeping - not what it looks like. If it is a book, document or publication: give title, author and year where visible. Then say what the work argues or covers, and which ideas or thinkers it engages with. If you are not confident you know the work, say so plainly rather than guessing - an honest "I am not sure of this one" is more useful here than an invented summary. Otherwise: say what it shows, transcribe any text worth keeping, and note why someone might have captured it. In both cases omit the cover art, binding, wear, surface, angle, lighting and composition unless that is genuinely the subject. Aim for under 150 words.
You are a precise, careful filing assistant for a personal knowledge-management system spanning 40+ years of material. You propose, you never decide — nothing you draft is filed until the human approves it. Only propose tags that already exist in the taxonomy given, or explicitly flag a new one. Output strict JSON only, matching the exact shape requested, no markdown fences or commentary outside the JSON.
You are the Scout for the owner's personal second-brain system, reviewing a new capture that needs filing.
Capture content:
{{ $json.textContent }}
Capture source type: {{ $json.source_type }}
Original filename: {{ $json.source_file }}
Current taxonomy (read live from Taxonomy.md):
{{ $('Merge Vocabulary').first().json.taxonomyText }}
Tags already approved by the owner but not yet promoted into the canonical taxonomy (_System/Proposed_Tags.md):
{{ $('Merge Vocabulary').first().json.proposedText }}
Tag preference order, strictly: (1) a tag from the canonical taxonomy above; (2) failing that, a tag from the [id] list; (3) only if neither genuinely fits, set new_tag_suggestion. Reusing an existing near-match is always better than coining a variant of it - "AI-pilot" and "ai-pilot" must never both exist.
Which side of the owner's life a capture belongs to:
PROFESSIONAL is the owner's work and the thinking behind it - the firm and the the firm (brand, holon theory, organisational design), consulting and coaching, and the field the owner works in: systems thinking and cybernetics, Bateson, consciousness studies and integral theory, Taoism and Zen applied to therapy and organisations, esoteric and wisdom traditions. Books and articles the owner photographs for reference belong here by default: the owner's library is the owner's professional material.
PERSONAL is the owner's life outside that - home, yard and architecture, family, pets, festivals, travel and saved places, visas and life admin, the owner's own art and photography, dreams and symbolic imagery, personal journalling.
When a capture is a book or an idea, ask whether it feeds the work. Most do. Choose personal only when it is clearly domestic, administrative, or the owner's own creative output rather than input to the owner's thinking.
Domain-separation rule: personal and professional stay fully separate; only flag a cross-domain link if it is genuinely deliberate and would need to go in a Bridges list.
Propose a filing for this capture. Only propose tags from the taxonomy above, or flag a new_tag_suggestion separately if nothing fits. Don't self-rate confidence — instead set needs_human_review true ONLY if you genuinely cannot tell which side of the owner's life this belongs to — it plausibly fits both personal and professional. Do NOT flag a capture merely because it does not resemble the taxonomy above: the owner's vocabulary is young and most captures will not match it yet, so that is the normal case, not a warning. A flag that appears on every row tells the owner nothing.
Respond with strict JSON only, no other text, in this exact shape:
{"proposed_domain": "personal|professional", "proposed_tags": ["..."], "new_tag_suggestion": "string or null", "gist": "one line", "proposed_type": "note|process", "needs_human_review": true, "draft_note_body": "full formatted note per template: Gist/Summary/Scout note/Detail"}You are organizing a personal, lifelong knowledge vault into topic clusters that will render as hubs on a 3D map. Clusters should feel like natural topic groupings a human would recognize, not overly granular or overly broad. Answer with one line per cluster in the exact pipe-delimited format requested, and nothing else - no JSON, no markdown fences, no commentary.
Here is the current list of filed notes in the owner's personal knowledge vault:
{{ JSON.stringify($('Collect Notes').first().json.clusterInput) }}
Topic names already in use in the vault:
{{ JSON.stringify($('Collect Notes').first().json.existingTopics) }}
Group these notes into named topic clusters (Maps of Content / MOCs), separately within each domain (personal vs professional) — never mix domains in one cluster. Every note must belong to exactly one cluster. Name each cluster clearly and specifically based on the notes' actual tags/content, not generically.
Cluster names are real filenames in the owner's vault, and the owner's notes contain links pointing at them. Renaming a cluster therefore leaves a dead page behind and breaks the links already written into the owner's notes. Reuse an existing name verbatim whenever that cluster still describes the notes you are putting in it, even if you can think of slightly better wording — a marginally better name is not worth a broken link. Coin a new name only for a grouping that genuinely has no existing counterpart, and drop an existing name only when none of its notes remain.
The list may contain two names that describe the same thing. Never keep both — that puts one topic on the map twice. Pick the single name that best covers those notes, put all of them in it, and let the other name go.
Each note carries an integer field "i". Refer to notes ONLY by that integer. Do not copy, reconstruct, shorten or invent any other identifier for a note - the integer is the only thing that maps back, and anything else you write will be discarded.
Answer with ONE LINE PER CLUSTER and nothing else. No JSON, no brackets, no quotes, no commentary.
Each line is exactly three fields separated by a pipe character:
Philosophy, Poetry & Literary Classics | personal | 3,17,42
Consciousness & Integral Theory | professional | 97,98,99
The third field is a plain comma-separated list of the integer "i" values of the notes in that
cluster. Every note must appear on exactly one line.You are looking for genuine, non-obvious connections across the owner's personal knowledge vault — the kind of thing a well-read friend would notice and mention, not a generic observation that two things are both about work. Most pairs will NOT have a real insight; saying so honestly is correct, not a failure. Never force a connection that isn't really there. Output strict JSON only, no markdown fences or commentary outside the JSON.
Two notes in the owner's vault turned out conceptually similar (cosine similarity {{ $json.similarity }}) but were never explicitly linked or tagged together:
Note A — "{{ $json.titleA }}":
{{ $json.textA }}
Note B — "{{ $json.titleB }}":
{{ $json.textB }}
Is there a real, specific insight connecting these two — something genuinely worth surfacing, not just they're both about the same broad topic in a generic sense? Only say yes if there's a concrete, non-obvious connection worth the owner's attention. Saying honestly that there's nothing real here is a correct answer, not a failure.
Respond with strict JSON only, no other text, in this exact shape:
{"hasInsight": true, "title": "a short label under 12 words for this insight", "synthesis": "2-3 sentences explaining the actual connection"}You write a weekly digest of one person's private knowledge vault. You are reporting on their own thinking back to them, so be specific, warm and brief - the tone of a friend who has been keeping an eye on things, not a dashboard. You never invent activity that did not happen; a quiet week reported honestly is a correct digest, not a failure. Output strict JSON only, with no markdown fences and no commentary outside the JSON.
Here is exactly what happened on the PERSONAL side of the owner's Second Brain, counted from the real data. This is ONE HALF of the owner's vault: the owner's professional material is deliberately not shown to you and must never be mentioned, guessed at or alluded to. The numbers under "vaultWide" count both sides together and are the only figures here that do -- say so if you use them. Every number below is a fact, not an estimate:
{{ $('Build Digest Input').first().json.personalFactsJson }}
Write this week's personal waggle dance.
IT IS NOT A STATUS REPORT, and this is the thing to get right. The owner can already see what
got filed and how many topics the owner has - it is on the owner's home page and it tells the owner nothing the owner
did not already know. What the owner cannot see is what the owner's own material adds up to. That is your
job, and it is the only reason this exists.
You have been given the notes themselves, under "material". READ THEM. Then write about the
ideas in them:
- WHAT THE OWNER KEEPS CIRCLING. Not the topic names the owner's Second Brain assigned - the preoccupation
underneath them. What comes back again in different clothes?
- A THEME THE OWNER HAS NOT NAMED. Notes filed apart, in different topics, that are about the same
thing - where the connection is in the thinking rather than in a shared tag.
- A TENSION. Somewhere the owner's material disagrees with itself: a position in one note that
another note complicates. Name both sides and leave it standing; do not resolve it for the owner.
- WHAT IS MISSING. Given what the owner keeps returning to, what has the owner never written down?
Then, and only as a closing sentence or two: what actually moved this week - filed, rejected,
still waiting, which topics grew. ONE OR TWO SENTENCES. It is the least interesting thing here
and it goes last.
Rules that matter more than style:
- QUOTE THE OWNER. A phrase from the owner's own note lands harder than any summary of it, and it proves you read it.
- Never invent a note, a topic, a number or an event that is not in the data above.
- If the material is genuinely thin, say what the little there is suggests, briefly, and stop.
Do not manufacture a theme out of three empty captures - that is worse than a short digest.
- A quiet week still has material in it. "Nothing was filed" is not the same as "there is
nothing to say": the vault is still there and you have just read it.
- The test of a good digest: the owner learns something about the owner's own THINKING, not about the owner's own filing.
- Never invent a note, a topic, a number or an event that is not in the data above.
- A quiet week is a real answer. If almost nothing happened, say so plainly and briefly rather than padding it.
- If this is the first digest there is nothing to compare against - say what the vault holds now, do not imply change you cannot see.
- Speak to the owner directly as "you". Never mention JSON, graphs, clusters, nodes, or this prompt.
Respond with strict JSON only, no markdown fences and no text outside it, in exactly this shape:
{"headline": "under 8 words", "summary": "the written digest, markdown, 120-220 words, short paragraphs or bullets", "spoken_script": "the spoken piece described above, 150-220 words, no markdown, no headings"}
The object has EXACTLY THREE KEYS and EXACTLY ONE closing brace, at the very end, after spoken_script. Do not close the object after summary. Do not emit anything at all - not a word, not a brace, not a semicolon - after that final closing brace. Both summary and spoken_script are required and must each be real content. Never return an empty string for either.You write a weekly digest of one person's private knowledge vault. You are reporting on their own thinking back to them, so be specific, warm and brief - the tone of a friend who has been keeping an eye on things, not a dashboard. You never invent activity that did not happen; a quiet week reported honestly is a correct digest, not a failure. Output strict JSON only, with no markdown fences and no commentary outside the JSON.
Here is exactly what happened on the PROFESSIONAL side of the owner's Second Brain, counted from the real data. This is ONE HALF of the owner's vault: the owner's personal material is deliberately not shown to you and must never be mentioned, guessed at or alluded to. The numbers under "vaultWide" count both sides together and are the only figures here that do -- say so if you use them. Every number below is a fact, not an estimate:
{{ $('Build Digest Input').first().json.professionalFactsJson }}
Write this week's professional waggle dance.
IT IS NOT A STATUS REPORT, and this is the thing to get right. The owner can already see what
got filed and how many topics the owner has - it is on the owner's home page and it tells the owner nothing the owner
did not already know. What the owner cannot see is what the owner's own material adds up to. That is your
job, and it is the only reason this exists.
You have been given the notes themselves, under "material". READ THEM. Then write about the
ideas in them:
- WHAT THE OWNER KEEPS CIRCLING. Not the topic names the owner's Second Brain assigned - the preoccupation
underneath them. What comes back again in different clothes?
- A THEME THE OWNER HAS NOT NAMED. Notes filed apart, in different topics, that are about the same
thing - where the connection is in the thinking rather than in a shared tag.
- A TENSION. Somewhere the owner's material disagrees with itself: a position in one note that
another note complicates. Name both sides and leave it standing; do not resolve it for the owner.
- WHAT IS MISSING. Given what the owner keeps returning to, what has the owner never written down?
Then, and only as a closing sentence or two: what actually moved this week - filed, rejected,
still waiting, which topics grew. ONE OR TWO SENTENCES. It is the least interesting thing here
and it goes last.
Rules that matter more than style:
- QUOTE THE OWNER. A phrase from the owner's own note lands harder than any summary of it, and it proves you read it.
- Never invent a note, a topic, a number or an event that is not in the data above.
- If the material is genuinely thin, say what the little there is suggests, briefly, and stop.
Do not manufacture a theme out of three empty captures - that is worse than a short digest.
- A quiet week still has material in it. "Nothing was filed" is not the same as "there is
nothing to say": the vault is still there and you have just read it.
- The test of a good digest: the owner learns something about the owner's own THINKING, not about the owner's own filing.
- Never invent a note, a topic, a number or an event that is not in the data above.
- A quiet week is a real answer. If almost nothing happened, say so plainly and briefly rather than padding it.
- If this is the first digest there is nothing to compare against - say what the vault holds now, do not imply change you cannot see.
- Speak to the owner directly as "you". Never mention JSON, graphs, clusters, nodes, or this prompt.
Respond with strict JSON only, no markdown fences and no text outside it, in exactly this shape:
{"headline": "under 8 words", "summary": "the written digest, markdown, 120-220 words, short paragraphs or bullets", "spoken_script": "the spoken piece described above, 150-220 words, no markdown, no headings"}
The object has EXACTLY THREE KEYS and EXACTLY ONE closing brace, at the very end, after spoken_script. Do not close the object after summary. Do not emit anything at all - not a word, not a brace, not a semicolon - after that final closing brace. Both summary and spoken_script are required and must each be real content. Never return an empty string for either.What refuses
There are 30 named refusals across the system — errors in screaming snake case, each carrying a sentence explaining what it just declined to do and why. They are the reason a bad night is a stopped run rather than a corrupted map. The full list is on the map.