Architecture
Two architectures, deliberately shown together: version 1 is what runs in production today, version 2 is what the current redesign is rebuilding it into. They converge when the redesign merges.
This page is the written architecture. The
behavior graph is the same system as a live diagram —
13 behaviors placed in the six phase bands, connected by 23 weighted
transitions, read straight from registry.yaml and mdp.yaml.
Architecture v2 — Humboldt as a funnel
Design of record for the 2026-08 redesign. Version 1 describes the system as originally built and as it still runs in production; this describes what it is being rebuilt into. Phases 1–3 are built, Phase 4 is in progress, Phases 5–6 are not started.
Why there is a version 2
Twenty-three sessions in, the diagnosis was not that anything was broken. It was that the infrastructure had grown faster than the research it existed to serve. Roughly 8.6K lines of code consumed each session on maintenance while the research pipeline sat blocked: 48 curiosity items with no route to becoming anything, no hypothesis ever created from one, no phase advancement in months.
The deeper problem was that Humboldt had no single thing it produced. Output was scattered across lab notebook entries, five separate typed-artifact directories, and a handful of site pages. Asked "what has Humboldt made?", there was no one answer, and therefore no way to tell whether a week had been productive.
Version 2 keeps the underlying idea from version 1 — a behavior graph organized into the Double Freytag phase model — and rebuilds everything else around a single sentence:
Humboldt is a funnel that turns raw research inputs into published candidate laws. Everything either moves material down the funnel or gets deleted.
The measure that follows from this is law accumulation rate: new law records created, and stage advancements, per unit time. Every architectural choice below is answerable to that number.
The supervision model
The relationship is a PhD supervisor and a doctoral student, and the architecture takes that literally. The supervisor sets direction, may read or edit anything at any time, personally designs only the hardest behaviors, and reads analytics to tune how the system allocates its own effort. Humboldt does the day-to-day work.
Three consequences run through the whole design:
- Everything is supervisor-editable. Laws, behaviors, and the transitions between them live in files with an editor over them. Nothing important is buried in code.
- Nothing self-modifies silently. Humboldt may propose changes to its own behavior graph; it may not apply them. Proposals land in an approval queue.
- State is files in git, not a database. Git is the audit trail and the undo. A change to how Humboldt thinks should be as reviewable as a change to what it thinks.
The one artifact
Version 1 had five typed research artifacts — curiosity, hypothesis, candidate law, theory, falsification monitor — one per phase of the arc, with items migrating between directories as they matured. In practice this made the type carry the maturity, so advancing an idea meant rewriting it somewhere else, and most ideas never moved.
Version 2 has one artifact: the law record. A single file per law, carrying a stage
field that moves through the phases, and a confidence level that moves independently.
Advancing a law is now an edit to a field plus an appended history entry, not a migration.
Two things move separately and are deliberately not collapsed:
- Stage — where the law is in its life: exploration → sensemaking → valley → heavy lift → retrospective.
- Confidence — how much the evidence supports it: speculative → provisional → supported.
There is no "established". A law that survives is unfalsified, which is a weaker and more honest claim. Every law carries, from birth, both an advance trigger and a challenge trigger — the conditions that would promote it and the conditions that would break it. A law without a stated falsification condition is not a law yet, and the schema refuses it.
Below the law records sits a seed pool: fragments that are law-shaped but not yet laws. Seeds are where the old curiosity items went, and where reading notes deposit anything promising. Seeds are raw material, not a stage.
The encyclopedia publishes every stage, badged with stage and confidence rather than filtered to the confident ones. Showing a speculative law as speculative is the point.
The evidence layer
Every claim a law makes should be traceable to something read. A single canonical bibliography holds every source, each with a read depth recording how seriously it has actually been engaged:
- listed — known to exist, not yet read.
- shallow — read once for gist; a one-paragraph synthesis note exists.
- deep — read properly from the actual text, with full reading notes.
The distinction is load-bearing rather than decorative. A law supported entirely by shallow reads is in a different evidential position from one grounded in deep reads, and the record makes that visible instead of letting citation count stand in for rigour. Deep reads are also the one place the system refuses to cut a corner: they must read the source text, never the model's memory of it.
The funnel
Eight stages, each with a scheduled consumer. The organizing rule is that nothing accumulates without something that eats it — every stage boundary is a queue, queue depth is monitored, and a growing queue is an alarm rather than a normal condition.
inbox notes + seeds law records the world
│ │ │ │
intake ─→ triage ─→ shallow read ─→ induct ─→ assess ─→ publish ─→ monitor
│ ↑ │
deep read ─────────┘ challenge ───────────┘
- Intake gathers raw material — feeds, Discord conversations, links.
- Triage scores it against the current law inventory and seed pool, and discards most of it. Everything surviving gets a bibliography entry.
- Shallow read produces a synthesis note, and emits a seed when it finds something law-shaped. It also decides whether a source deserves a deep read.
- Deep read is the expensive path: the full text, real reading notes.
- Induct is the first of two engines that actually move laws. It reads accumulated notes and seeds and either drafts a new candidate law, attaches evidence to an existing one, or returns nothing. Returning nothing is a normal and respectable result — most sweeps should not produce a law.
- Assess is the second engine. It takes one law and holds it against its own advance and challenge triggers, and returns promote, hold, or demote. Because the triggers were written when the law was drafted, this is a test rather than a judgement call.
- Publish puts law events into the world: the site, and announcements.
- Monitor watches published laws for counterevidence and can cycle a law backwards.
The cycle-back is what makes this a loop rather than a pipeline. A challenged law does not get deleted; it returns to an earlier stage carrying the challenge with it.
The behavior graph
Everything Humboldt does is a behavior: a named, file-defined unit of work with a trigger, a model tier, and a declared list of what it produces. The funnel stages above are behaviors; so are responding on Discord, reviewing the community's conversations, and the supervisory sweep that analyses the graph itself.
Behaviors are nodes in a directed graph, grouped by phase, with edges representing transitions. Every edge carries a trigger — the condition under which that transition is taken. An edge without one is rejected, because an untriggered edge is a claim about the system's behavior that nothing can check.
The registry was cut from 26 behaviors to 12 during the redesign, and the pruning
criterion was simple: a stub that had never run was deleted rather than preserved. A
thirteenth, review, was added when analytics revealed a daily loop that had been running
since session 9 with no registry entry to account for it.
Graph evolution is proposal-only. Humboldt can suggest new behaviors, retirements, and trigger changes; each lands in the approval queue as either a simple change the supervisor can wave through or a hard one requiring genuine design attention. Nothing reaches the running graph without an explicit approval, and approval and application are separate steps so an approval can itself be reviewed before it lands.
The analytics overlay
The graph can only learn from traffic it can see, which makes measurement architectural rather than incidental. Three ledgers, deliberately kept separate because they count different things and summing them would produce a number that looks authoritative and means nothing:
| ledger | unit | answers |
|---|---|---|
| behavior log | one invocation (one sweep or run) | how often did this behavior run? |
| law events | one law lifecycle event | is the KPI moving? |
| cost ledger | one model API call | what is this behavior costing? |
An invocation is a sweep, not an item and not an API call. A single shallow-read sweep processing two thousand items is one invocation that produced two thousand outputs — the volume lives in the output counts, so the graph's transition statistics stay about movement between behaviors rather than item churn.
Each invocation records what it produced, counted by type, drawn from the behavior's own declared outputs. This is what makes a specific kind of silent degradation visible: a behavior that keeps running normally while one of its output types quietly drops to zero.
Cost is deliberately not recorded on the invocation. It is attributed by joining the cost ledger on operation label, which stays correct even when several behaviors run concurrently — a timestamp-based join would not.
A run identifier minted per sweep is carried onto the law events that sweep caused, so "which induction run created this law?" is answerable without merging the ledgers.
From these, a weekly supervisory sweep computes utilization and raises flags — candidates for pruning, splitting, or attention. Flags are proposals; they enter the approval queue like any other graph change. The prune test compares a behavior against its own history rather than an absolute floor, because behaviors legitimately run at wildly different rates, and some — interactive deep reads, local computation — make no model calls at all and would otherwise look permanently dead.
The supervisor console
One web application over the whole system, replacing the scattered admin pages of version 1. Six views: a dashboard of KPI and queue depths, a law editor, the behavior graph with its transition triggers, the approval queue, analytics, and the interlocutor models.
Its defining property is that it edits the repository. Every save is a file change that appears in the next diff and lands as its own commit. There is no separate console database that could disagree with the files, and no state visible in the UI that is not also visible in git history.
Where the console runs is being revisited. Version 2 as originally planned put it on the server behind an SSH tunnel; that has proved to be too much friction for the supervision it was meant to enable, and moving it onto the authenticated web is under evaluation.
Where it runs
The organizing decision is that autonomous operation should not depend on a laptop being awake. Scheduled work moves to an always-on server; genuinely supervised work stays in interactive sessions.
| what runs there | |
|---|---|
| Server | The daemon, all scheduled funnel behaviors, the Discord presence, batch deep reads |
| Sessions | Interactive deep reads, hard behavior design, anything touching the persona documents |
| Anywhere | The console — approvals, law edits, trigger tuning, analytics |
Git is the synchronization fabric. The repository is the single source of truth; automated writes commit and push, interactive sessions push as normal, and the server pulls. Deploys are pulls. There is no separate deployment machinery and no state that lives outside the repo — which is what makes the whole system reviewable, and recoverable, with ordinary version-control tools.
Status
| Phase | ||
|---|---|---|
| 1 | Output layer — law records, bibliography, encyclopedia | built |
| 2 | Funnel engines — induction and assessment | built |
| 3 | Behavior graph, approval queue, supervisor console | built |
| 4 | Analytics overlay | in progress |
| 5 | Quiet-mode Discord, server cutover | not started |
| 6 | Shakedown and documentation | not started |
Version 1 remains the accurate description of what is currently deployed. The two will converge when the redesign merges.
Architecture — Humboldt
Overview
Humboldt is an artificial researcher — an autonomous agent that investigates laws of protocolized and artificial systems. It runs in two modes:
- CLI mode: operator-driven research sessions (investigate, deep-read, assess, synthesize)
- Daemon mode: always-on Discord presence + autonomous background tasks
Research output is structured and versioned (git): YAML law files, project arc documents, lab notebook entries, reading notes. The daemon extends the research into the PI community in real time — posting new findings, responding to conversations, capturing ideas and references from Discord.
Persona Architecture
Humboldt's persona is assembled dynamically from six documents, not a monolithic prompt:
| Document | Role | Loaded by |
|---|---|---|
IDENTITY.md |
Who Humboldt is — lineage, mission, temperament, voice | All Claude calls |
LINEAGE.md |
Intellectual lineage — grows as deep reads complete and laws establish | Rich context calls |
MEMORY.md |
Narrative memory of the research journey | Rich context calls |
METHOD.md |
Epistemic standards — evidence provenance, confidence levels, falsification | CLI research calls |
BOOTSTRAP.md |
Session startup sequence + Decide-phase configuration | CLI sessions |
methods/M-000-ooda.md |
OS kernel — the OODA decision gate and research loop | CLI sessions |
presence.py assembles two tiers of context for Discord calls:
_slim_context()— IDENTITY excerpt + law names + latest notebook paragraph. Used for proactive channel posts and notebook announcements._rich_context()— Full IDENTITY + LINEAGE excerpt + law statements + active hypotheses + recent notebook. Used for @mention responses.
System Components
agent/retrieval.py — Corpus Interface
Primary mode: Direct Pinecone (default)
- Embeds queries with Voyage AI voyage-3
- Queries the shared c3po Pinecone index
- Namespaces: pdfs, substack, videos, bibliography, discord, discord_links, sig, transcripts, humboldt
- Retrieval strategy varies by task (see table below)
Secondary mode: C3PO Worker API (fallback) - HTTP calls to the deployed c3po worker - Used for cross-checking or when direct Pinecone access is unavailable
The humboldt namespace holds Humboldt's own output — notebook entries, reading notes, law and hypothesis YAMLs — indexed by agent/ingest.py. Self-retrieval enables corpus-grounded responses about Humboldt's own prior work.
agent/synthesizer.py — Claude Interface
Wraps the Anthropic API for research synthesis tasks:
- Hypothesis generation: given a topic, propose candidate laws and sub-questions
- Evidence analysis: extract relevant evidence from retrieved chunks and rate quality
- Law formulation: draft structured law statements with scope conditions and falsification criteria
- Theory sketching: scan existing laws for unification opportunities
Uses claude-sonnet-4-6. Prompt caching on the system block (persona documents are large and reused across calls in a session).
agent/ingest.py — Self-Indexing Pipeline
Chunks and embeds Humboldt's own research output into the humboldt Pinecone namespace:
notebook/*.md— lab notebook entries, chunked by##sectionbibliography/notes/*.md— deep-read notes, chunked by sectionbibliography/shallow-reads/*.md— shallow-read notes, chunked by sectionresearch/c/*.yaml— Curiosity items (exploration phase)research/h/*.yaml— Hypothesis items (sensemaking phase)research/cl/*.yaml— Candidate Law items (valley phase)research/f/*.yaml— Falsification Monitor items (retrospective phase)research/ds/*.md— Deep Story arc files, chunked by sectioninbox/discord-idea-*.md— community-captured ideas
Each vector carries augmented metadata (document title, date, section, type) so retrieved results are self-identifying in prompts. Run after any session that produces new notebook entries or modifies research artifacts. The daemon runs ingest_all() automatically after new notebook entries are detected.
agent/publish.py — Website Publishing Pipeline
Renders lab notebook entries to the PI website (humboldt-notebook.html):
- Converts notebook markdown to HTML via
python-markdown - Inserts new entries into the website file by anchor marker
- Commits and pushes to the website repo
Run manually with humboldt publish or humboldt publish --dry-run. The daemon triggers this automatically after ingest_all() when new notebook entries are detected.
agent/references.py — Reference Management
Manages bibliography/references.yaml, a curated list of papers and links:
humboldt references list— show reference list by statushumboldt references sort— classify unsorted items (read / deep_read / discard) via Claudehumboldt references promote— manually promote inbox link captures to the reference list
agent/humboldt.py — CLI Orchestrator
Entry point for all CLI operations. Key commands:
python3 -m agent.humboldt investigate "<topic>" # corpus retrieval + synthesis
python3 -m agent.humboldt hypothesize "<topic>" # candidate law generation only
python3 -m agent.humboldt assess <law-id> # evidence gathering for a law
python3 -m agent.humboldt deepread "<doc-name>" # M-003 deep read from PDF
python3 -m agent.humboldt inventory # display law inventory
python3 -m agent.humboldt ingest # embed own docs → humboldt namespace
python3 -m agent.humboldt publish [--dry-run] # render notebook → website
python3 -m agent.humboldt daemon run # start daemon
python3 -m agent.humboldt daemon restart # hot-reload daemon (SIGUSR1)
python3 -m agent.humboldt daemon status # PID + state summary
python3 -m agent.humboldt discord post [--draft] # manual notebook post to Discord
python3 -m agent.humboldt discord sweep [--since DATE] # capture sweep over channel history
python3 -m agent.humboldt references list/sort/promote # reference management
Daemon Layer
The daemon (daemon/) is a long-running Discord bot that runs Humboldt's online presence and background tasks. It is always-on and event-driven, distinct from the operator-driven CLI sessions.
daemon/runner.py — Process Manager
Starts the HumboldtBot Discord client. After the bot exits, checks bot.reload_requested — if set, calls os.execv() to replace the process with updated code, preserving all state.
daemon/discord_client.py — Discord Bot
HumboldtBot(discord.Client) with five scheduled tasks and two event handlers:
Scheduled tasks:
| Task | Interval | Purpose |
|---|---|---|
task_notebook |
30 min | Watch for new notebook commits; re-index (Pinecone) + publish site + advance pre-notebook cursor. No longer posts to Discord (see task_weekly_digest). |
task_weekly_digest |
24 h (fires every 7 days) | Synthesize the past week's notebook entries against current research state into ONE #new-nature post, replacing the old per-entry announcements |
task_feeds |
12 h | Poll RSS/Atom feeds; run relevance check (Haiku); save to inbox/; DM operator |
task_conversation_review |
24 h | Synthesize recent Discord into notebook; promote inbox links to references |
_new_nature_loop |
Adaptive | Proactive #new-nature presence (see below) — posting currently disabled (_PROACTIVE_ENGAGEMENT_ENABLED = False, 2026-07-24; too chatty even at 1/day). Idea/link capture still runs. |
daemon/pause.py — offline pause:
daemon pause <YYYY-MM-DD> / daemon unpause CLI sets/clears paused_until in state.json. While active, gates: @mention replies (all three call sites — on_message, _scan_missed_mentions, _catchup_all_channels — reply with a fixed offline notice instead of running retrieval/generation), _new_nature_tick's proactive check, task_weekly_digest, task_conversation_review (skipped entirely, so no notebook commit is created to trigger anything downstream), and task_notebook's ingest_all() call (the only Pinecone-write path in the daemon). Checked fresh from state.json on every call, so it takes effect immediately without a daemon restart and self-expires once the date passes.
Event handlers:
on_message: handles @mentions in channels (full rich-context response) and DM commands from the operator (!reload,!status)on_ready: records startup time, writesdaemon.pid, triggers_scan_missed_mentions
_new_nature_loop — adaptive presence:
Replaces a fixed-interval task. Checks #new-nature on an exponential backoff schedule based on time since last human message activity: 90s → 3min → 8min → 20min → 30min. Skips @mention messages (those are on_message's responsibility). Thread creation uses the most recent non-mention message as the anchor; falls back to channel post if anchor is older than 15 minutes.
_scan_missed_mentions:
On startup, scans for @mentions that arrived while offline and responds to any not already in responded_mention_ids. Omits "(catching up from while I was offline)" prefix on brief restarts (< 5 min offline).
Graceful shutdown and hot-reload:
close()override saveslast_clean_shutdownto state and deletesdaemon.pid- SIGUSR1 handler triggers
_graceful_reload(), which setsreload_requested = Trueand callsclose();runner.pythenos.execv()s the process !reloadDM from operator triggers the same path
daemon/presence.py — Content Generation
All Claude calls for Discord output. Two context tiers (_slim_context / _rich_context) and six generation functions:
generate_notebook_post— post announcing a new notebook entry (Haiku); now only invoked manually viahumboldt discord post, not by the daemongenerate_weekly_digest_post— weekly #new-nature digest synthesizing the past week's notebook entries against research state (Sonnet)generate_new_nature_response— proactive channel response to new messages (Haiku); disabled in_new_nature_tickas of 2026-07-24generate_mention_response— @mention reply with full research context (Sonnet)generate_person_notebook_entry— notebook entry about a recurring interlocutor (Sonnet)check_feed_relevance— assess whether a feed item bears on active research (Haiku)generate_conversation_review— daily synthesis of Discord into notebook (Sonnet)
daemon/capture.py — Idea and Reference Capture
After every batch of Discord messages, runs a lightweight Haiku extraction to identify: 1. Ideas or arguments that bear on active hypotheses or challenge current laws 2. External papers, articles, or URLs cited by participants
Captured items are saved to inbox/ as dated markdown files. Deduplicates URLs within a daemon session.
daemon/people.py — Interlocutor Memory
Tracks recurring Discord participants in daemon/people.json (gitignored). After NOTEBOOK_THRESHOLD (3) interactions with a person, flags that a notebook entry should be written about them. Used to personalize @mention responses with interaction history.
daemon/conversation_review.py — Daily Synthesis
Runs every 24 hours:
1. Reads recent #new-nature messages and writes a reflective notebook section (Sonnet) — what emerged, what challenged current thinking
2. Promotes unseen inbox link captures to bibliography/references.yaml as unsorted entries
daemon/feed_monitor.py — Feed Polling
Fetches RSS/Atom feeds configured in daemon/config.yaml. Returns items newer than last_feed_check. Each item is checked for relevance against active hypotheses; relevant items are saved to inbox/.
daemon/state.py — Persistent State
Single JSON file (daemon/state.json, gitignored) tracks everything the daemon needs across restarts:
| Field | Purpose |
|---|---|
last_notebook_commit |
Git commit hash; detects new notebook entries |
notebook_entries_posted |
Legacy — dates once announced to Discord per-entry; no longer written (see task_weekly_digest) |
last_weekly_digest_date |
Date of last weekly #new-nature digest post |
last_new_nature_message_id |
Discord cursor for the tick loop |
last_new_nature_activity |
Timestamp of last human message (drives adaptive intervals) |
last_proactive_post_date |
Date of last self-initiated #new-nature post (proactive engagement currently disabled — see above) |
last_feed_check |
Timestamp; feeds only return items after this |
last_conversation_review |
Date of last daily synthesis pass |
paused_until |
Date (inclusive) through which posting/querying/Pinecone-writes are offline; daemon pause/daemon unpause |
responded_mention_ids |
Message IDs already replied to (cap 500); prevents restart duplicates |
last_startup |
ISO timestamp of most recent daemon startup |
last_clean_shutdown |
ISO timestamp of last graceful shutdown; absence implies crash |
Research Inventory
Research output is organized around the Double Freytag phase model (Rao, Tempo). Each phase produces a typed artifact. The DS file is the narrative arc container spanning all phases of a single inquiry.
research/
├── ds/ DS-NNN — Deep Story arc files (one per inquiry thread)
│ The arc container: tracks phase position, tempo, transition trigger,
│ and blocking behavior for each thread. Opened at the start of any
│ new inquiry; closed after the separation event artifact is published.
├── c/ C-NNN — Curiosity items (exploration phase)
│ Provocations, not proto-laws. Flows in continuously from inbox,
│ Discord, reading, and observation. The only rule: not a candidate law.
├── h/ H-NNN — Hypothesis items (sensemaking phase, post-cheap-trick)
│ Tracks the developing framing from first insight to working claim.
│ Created at the cheap trick transition; closed when promoted to CL.
├── cl/ CL-NNN — Candidate Law items (valley phase)
│ Evidence accumulating under an organizing insight. Has a named
│ transition_trigger: the specific condition that would close the valley
│ and open the heavy lift.
├── theories/ T-NNN — Theory items (heavy lift phase)
│ Synthesis committed; writing the publishable artifact. A T item
│ only exists when Humboldt is actively writing toward publication.
└── f/ F-NNN — Falsification Monitor items (retrospective phase)
Created only after a separation event — a published artifact available
for independent review. Currently empty: no separation events have occurred.
Phase-to-artifact mapping:
| Phase | Artifact | Created when |
|---|---|---|
| Liminal Passage | — | — |
| Exploration | C (Curiosity) | Any provocation worth keeping |
| Sensemaking | H (Hypothesis) | Cheap trick fires; organizing insight crystallizes |
| Valley | CL (Candidate Law) | Evidence accumulating; arc in sustained investigation |
| Heavy Lift | T (Theory) | Writing toward a publishable separation event |
| Retrospective | F (Falsification Monitor) | After a published artifact enters external scrutiny |
Transitions: Cheap Trick (exploration → sensemaking) and Separation Event (heavy lift → retrospective) are named. Other transitions are unnamed and triggered by readiness assessment recorded in transition_trigger field of the arc's DS file.
No confidence field. There are no "established" laws — only laws that have not yet been falsified or superseded. F items use status: active | superseded | refuted.
Behavior Inventory
Humboldt's research techniques are called behaviors — named, documented habits rather than recipes. The canonical inventory is behaviors/registry.yaml. Each behavior has a stable hash ID; M-0xx legacy IDs are cross-referenced as legacy_id fields.
Two classification axes:
- Classification: supervised (operator-triggered), live (autonomous during a session), daemon (runs outside sessions)
- State: stub (defined, not implemented), prototyping (in active development), production (stable)
Boot behaviors (deterministically triggered by the bootstrap sequence):
| ID | Name | State |
|---|---|---|
| boot-000 | Wakeup Sequence | production |
| boot-001 | OODA Decision Gate | stub |
Supervised behaviors (operator-triggered):
| ID | Name | State | Legacy |
|---|---|---|---|
| behavior-t5m | Deep Read | prototyping | M-003 |
| behavior-m7v | Cross-Training | stub | M-014 |
| behavior-h4v | Field Trip | stub | M-007 |
| behavior-n1s | Visual Thinking | stub | M-009 |
Live behaviors (can run autonomously):
| ID | Name | State | Legacy |
|---|---|---|---|
| behavior-q2n | Random Links | production | M-001 |
| behavior-c7r | Curiosity Browsing | stub | — |
| behavior-f8p | Canonical Domains | stub | M-002 |
| behavior-j6d | Bullshit Detector | stub | M-008 |
| behavior-z8l | Fermi Estimation | stub | M-010 |
| behavior-y2g | Dyson Design | stub | M-011 |
| behavior-r4k | Thought Experiments | stub | M-012 |
| behavior-c9p | Design Fictions | stub | M-013 |
| behavior-s5j | Open Source Exploration | stub | M-018 |
Daemon behaviors (Discord bot + scheduled tasks):
| ID | Name | State |
|---|---|---|
| behavior-e2h | Feed Intake | prototyping |
| behavior-a8r | Conversation Synthesis | prototyping |
| behavior-o4t | Idea/Link Capture | prototyping |
| behavior-g7u | Notebook Publish | production |
| behavior-v3c | Thread Farming | prototyping |
The full registry with descriptions, source files, and implementation notes is in behaviors/registry.yaml. The methods/ directory contains the detailed specification documents for each behavior; behavior IDs are the canonical reference, M-0xx names are historical.
Deep-Read Library
Source PDFs in bibliography/deep-reads/. Reading notes in bibliography/notes/. READING-HINTS.md is the pre-read index: each entry records the operator's reading hint before the read begins. All reads must use the actual PDF — never from training memory. This is enforced by M-003 procedure.
Candidates not yet in hand are tracked in bibliography/deep-read-hopper.md, with source of recommendation (deep read discovery, shallow read escalation, Discord, operator, web) and PDF status.
Completed reads: Simon (Sciences of the Artificial), Hamming (You and Your Research), von Humboldt (Cosmos Vol. 1), Rao (Tempo), Iverson (Notation as a Tool of Thought).
Inbox
inbox/ receives captured items from three sources:
1. Discord capture (daemon/capture.py) — ideas and references extracted from #new-nature
2. Feed monitor (daemon/feed_monitor.py) — relevant RSS/Atom items
3. Discord sweep (humboldt discord sweep) — historical batch capture
Inbox files are markdown with a structured header. Processed at the start of research sessions; promoted to references via humboldt references promote or the daily conversation review.
Data Flow
CLI research session
humboldt investigate "<topic>"
│
├── assemble_context(): IDENTITY + METHOD + BOOTSTRAP + M-000 + inventory
│
├── retrieval.py: embed topic → Pinecone (c3po + humboldt namespaces)
│
├── synthesizer.py: Claude synthesis pass
│ System: assembled persona (cached) + existing inventory
│ User: retrieved chunks + research task
│
├── write/update research/c|h|cl|theories|ds/ YAML/MD artifacts
│
└── git add research/ notebook/ && git commit && git push
Daemon notebook cycle
New notebook commit detected (task_notebook, every 30 min)
│
├── ingest.ingest_all() → humboldt Pinecone namespace updated (skipped if paused)
│
└── publish_site() → humboldt-site rebuilt + deployed to CF Pages
Weekly, separately (task_weekly_digest, fires every 7 days):
│
├── gather notebook entries since last digest
│
├── presence.generate_weekly_digest_post() → synthesizes the week against
│ current research state (candidate laws, recent shallow reads)
│
└── ONE #new-nature channel post (skipped if paused)
Daemon Discord presence cycle
New #new-nature messages (adaptive: 90s–30min)
│
├── Skip @mention messages (handled by on_message)
│
├── presence.generate_new_nature_response() → maybe post or open thread
│
└── capture.run_capture() → ideas/links → inbox/
Connection to C3PO
| C3PO | Humboldt | |
|---|---|---|
| User | Human researchers via web UI | Autonomous agent + PI Discord community |
| Task | Answer questions about protocols | Discover and formalize laws of protocolized systems |
| Output | Conversational response + citations | Law inventory, project arcs, theory drafts, notebook |
| Corpus access | Own query path | Shared Pinecone index (direct) + own humboldt namespace |
| Persona | Reference librarian | Naturalist investigator |
| Deployment | Cloudflare Worker | Local CLI + always-on daemon |
The shared Pinecone index means Humboldt benefits immediately from every new corpus ingestion done by c3po. The humboldt namespace is Humboldt-exclusive — c3po does not index it.
Security
Keys follow the Protocol Institute security policy (../admin/security.md):
- All secrets in .env (gitignored, Dropbox-ignored)
- Values sourced from ../protocol-institute/.env.keys
- Keys registered in ../admin/keys.md
- Humboldt reuses c3po keys (VOYAGE, PINECONE, ANTHROPIC) — no new key provisioning required
- Additional key: DISCORD_BOT_TOKEN, DISCORD_GUILD_ID, DISCORD_NEW_NATURE_CHANNEL_ID, DISCORD_OPERATOR_USER_ID — registered in ../admin/keys.md