hypotree

by tygryso

Not rated
GitHub

About

Memory that forgets. A persistent, self-revising belief state for agentic R&D. Prunes dead branches and deduces answers without spending probes.

Details

Author
tygryso
Categories
AI, Knowledge Base, Other

Setup

Install hypotree in your MCP client (Claude Desktop, Cursor, Windsurf, and others).

Repository: https://github.com/tygryso/hypotree

Follow the installation instructions in the repository README, then restart your MCP client.

A persistent, self-revisinghypothesis DAGfor agentic R&D — exposed as anMCP server.

Current agent memory is passive: vector stores and scratchpads accumulate facts but never revise them. Hypotree structures the agent's working knowledge as adirected acyclic graphof hypotheses backed by SQLite-WAL. When an experiment fails, the engine walks the dependency edges and retracts what rested on it. When a premise collapses, every dependent subtree is pruned automatically.

- Write-back belief revision— an ATMS-style engine (de Kleer, 1986) that propagates evidence failures upstream through the dependency graph.
- Cascading prune— invalidating a parent hypothesis instantly transitions its entire subtree toPRUNED. No tokens spent on dead branches.
- Exclusion-group inference— confirming one member of a mutually exclusive group retires the rest asEXHAUSTEDwithout probing them.
- Deduction by elimination— last-man-standing: when all but one alternative in an exclusion group are refuted, the survivor isVERIFIEDwithout a probe.
- Backward pruning over a complete question— the dual of the above: wheneverycandidate answer to a question is ruled out on its own evidence, nothing that assumes one of them can be satisfied, so those branches arePRUNEDand the navigator names the question that ran out.
- The closed-world assumption is declared, not assumed.Both inferences above are sound only if the listed answers areallthe answers.exclusion_closed=Falsesays they are not — "which learning rate?" always admits another — and the engine then withholds both. And when a deduction itdiddraw turns out to rest on an incomplete list, it iswithdrawnrather than defended: the node goes back on the frontier and one probe settles which premise was wrong.
- Thompson Sampling navigation— Beta-distribution sampling over the open frontier, giving bounded worst-case regret (no catastrophic lock-in).
- Conflict resolution via differential ablation— when an integration test fails but every component passes alone, the engine rebuilds the failing combination one swap at a time to pinpoint the culprit.
- A derivation trail, not just a stategenerate_learning_pathnarrates what was settled, in order, separating what an experiment paid for from what the engine inferred for free, and calling out beliefs that were later withdrawn.
- Persistent across sessions, models, agents, users, and projects— the belief state is a SQLite database, not a context window.

Everything here is on by default and covered by the pre-registered benchmark.

Off by default, and staying off until a full evaluation with a live model has scored them. Behaviour with the flag absent is bit-identical to a build that has never heard of the feature.

Why the saving exists, since it is not obvious: the last surviving answer to a closed question isdeduced rather than probed, so whichever answer you never reach is never paid for. Ordering cheapest-first puts the expensive answer in that free slot. Probecountbarely moves — the winner's position is uniform, so any order settles a question in the same expected number of probes — while probecostfalls a long way.

A belief state that revises itself is hard to appreciate from a status column.The dashboard runs by default, beside the MCP server, so the graph is already there the first time you look for it:

That is a real run. Nodes arrive as the agent creates them and glow at their actual chance of being dispatched next; confirmed answers turn green and their rivals retire without ever being probed; a refuted premise takes its subtree with it. The bar along the bottom is the run's own activity — drag it and the whole graph rewinds to what was believed at that moment, narrative included.

Nothing on that page writes evidence. If a belief moved, an experiment moved it.

# From PyPI uvx hypotree # or pip install hypotree # From source git clone https://github.com/tygryso/hypotree.git cd hypotree uv sync

Requires:Python 3.10+ ·Runs on:Linux, macOS, Windows

Check the install without wiring up a client — the server speaks JSON-RPC on stdin, so starting it in a terminal otherwise looks like a hang:

hypotree --version # or: uvx hypotree --version hypotree --info # which belief state am I connected to, and where is it?

Add hypotree to your MCP client config (Cursor, Cline, Claude Desktop, etc.):

{ "mcpServers": { "hypotree": { "command": "uvx", "args": ["hypotree"], "env": { "HYPOTREE_WORKSPACE_ID": "my-project" } } } }

The agent creates a tree withparent_idswiring combinations to their premises andexclusion_groupdeclaring competing answers to one question:

# Agent calls over MCP: create_hypotheses(hypotheses=[ {"node_id": "catalyst_A", "statement": "Pd/C catalyst works", "exclusion_group": "catalyst"}, {"node_id": "catalyst_B", "statement": "Pt catalyst works", "exclusion_group": "catalyst"}, {"node_id": "catalyst_C", "statement": "Ni catalyst works", "exclusion_group": "catalyst"}, # Enumerable question → closed by default, so eliminating two confirms the third. # For "which learning rate?" pass exclusion_closed=False: there is always another, # and the engine then refuses to deduce a survivor it cannot justify. {"node_id": "yield_target", "statement": "reach 90% yield", "is_goal": True, "target_metric": 0.9, "parent_ids": ["catalyst_A"]}, ])

3. Record evidence and let the engine infer

# Probe catalyst_A → fails outright, catalyst_B → fails outright. # Two experiments, one call: record_evidence(results=[ {"node_id": "catalyst_A", "success": 0.0}, {"node_id": "catalyst_B", "success": 0.0}, ]) # Engine: catalyst_A, catalyst_B → INVALIDATED; anything depending on them → PRUNED # catalyst_C → VERIFIED by elimination — no probe spent
generate_learning_path() # → markdown briefing + counters: # probes_spent = 2, conclusions = 3, conclusions_without_a_probe = 1

Additionally, you can start the server with these flags:

hypotree # MCP server + dashboard on 127.0.0.1:7331 hypotree --dashboard-port 8080 # start probing from a port you choose hypotree --no-dashboard # MCP server only, no socket opened hypotree --no-mcp # dashboard alone, against an existing belief state hypotree --experimental-cost-aware # rank by value per unit of probe cost (see Experimental features)

It binds127.0.0.1only and mints a session token at startup; the URL, token included, goes to stderr (stdout is the JSON-RPC channel). Ask the agent for it instead —get_workspace_inforeturnsdashboard_url, and so does thehypotree://dashboardresource. If no port in the range is free the MCP server still starts and says so: a viewer must never be able to take the server down.

--no-mcpopens the database read-only, so it is safe to point at a workspace an agent is actively writing — and it needs no client configured to try.

- A live graph.Nodes are laid out server-side withnetworkxand rendered as SVG withd3-zoomfor hardware-accelerated pan and zoom. Untested nodes glow at their real chance of being dispatched next; in-progress nodes pulse;pruned branches desaturate instead of disappearing, because the point being shown is that they were considered and cut.
- New nodes fade in.When the agent creates a hypothesis, it arrives as a ghost and resolves — you watch the search grow without touching the page.
- An activity timeline.status_historyis bi-temporal, so any past instant is aWHEREclause. The bar chart is the shape of the run — where the bursts were, where it stalled — and the handle travels along it. Drag back to see what was believed then, or press play and watch the whole investigation replay.
- Provenance on every card.What each belief cost: the score, the depth, the commit, thesource_ref, any files the experiment left behind, when it was created and when it settled. The graph is a ledger, not a drawing.
- The learning path as typeset markdown, ready to paste into a report — and it rewinds with the graph, so a rewound picture is never captioned with conclusions it has not reached.
- Pin and suspend.Redirect the search without faking evidence — directives change what isoffered, never what is believed.

Everything is vendored (Vue 3, d3 micromodules, marked — 276 KB total). No CDN, no npm, no build step: it works on a plane and in an air-gapped network.

The API is JSON and every/api/call needs the token. Everything is a read except one route — pin and suspend are scheduling instructions, and they never touch a posterior:

p_selectis the real thing, not a proxy: Thompson Sampling picks the argmax of one draw per candidate, so the number is how often each candidate wins that draw.

The server ships three MCPprompts. Clients that support them (Cursor, Claude Desktop, Cline) surface them as slash commands, so a human can steer the loop without retyping the protocol — and, more usefully, without the agent paraphrasing it.

/hypotree-inittakes an optionaltaskargument. Exact invocation depends on the client (Cursor and Claude Desktop namespace prompts under the server, e.g./hypotree:hypotree-init).

Three MCPresources, pulled on demand rather than carried in context:

Agent rules — how your agent learns to use this

The operating contract reaches the model through four channels. You do not have to wire any of them up; they are listed so you know what is already in context and what is not.
- Server instructions.MCP hands a server-levelinstructionsblock to the client duringinitialize, and every major client puts it in front of the model. Hypotree uses it for four rules: one hypothesis per node, mark the goal withis_goal=Trueand wire it to the work, record against the node you actually tested, and report what you were leased. Nothing to configure.
- Tool descriptions.Each tool description carries the one rule that tool is misused without — that a goal never accepts evidence, that a lease reserves a node until you report it, that confirming one member of an exclusion group retires the rest. These are the only text guaranteed to be in context at the moment a tool is chosen.
- Resources.The full guide ishypotree://guide. An agent that hits something surprising can read it without you pasting 23 KB into a system prompt.hypotree://dashboardhands over the live link.
- Your project rules file— optional, and the only part you touch. If you want the agent to reach for hypotree
unpromptedon multi-day work, add the block below.

Optional:.cursorrules/AGENTS.md/CLAUDE.md

## Long-running R&D: use hypotree For any task that spans more than one session, branches into competing approaches, or where an early assumption could turn out wrong later, keep the belief state in hypotree rather than in the conversation. - Before starting, call generate_learning_path. Something may already be settled, and re-deriving it costs an experiment you do not have to run. - Create the objective with is_goal=True and wire hypotheses to it with parent_ids. Progress is then derived, not asserted. - Competing answers to one question share an exclusion_group. Confirming one retires the rest without testing them — this is where most of the saving is. If the list could always grow ("which learning rate?"), add exclusion_closed: false so the engine does not deduce a survivor it cannot justify. - Ask get_next_targets for work and record every result you were handed. A target is leased to you; anything you hold and never report is work nobody can do. Probed several things in one turn? Report them in one call with record_evidence(results=[...]). - Record against the node whose statement you actually tested. A composition's failure filed against a premise destroys a confirmation that is still true. - When get_next_targets returns DONE, read the reason. Only all_goals_met and empty_frontier mean stop; the rest are instructions. dead_question means one of your questions ran out of candidate answers — add the one you have not thought of to the same exclusion_group.
┌─────────────────────────────────────────┐ │ MCP Client (agent) │ │ Cursor / Cline / Claude Desktop │ └──────────────┬──────────────────────────┘ │ MCP protocol (stdio/HTTP) ┌──────────────▼──────────────────────────┐ │ hypotree MCP Server │ │ ┌─────────────────────────────────┐ │ │ │ Engine (20 tools) │ │ │ │ • Write-back propagation │ │ │ │ • Cascading prune │ │ │ │ • Exclusion-group inference │ │ │ │ • Differential ablation │ │ │ │ • Thompson Sampling navigator │ │ │ └──────────┬──────────────────────┘ │ └─────────────┼───────────────────────────┘ │ ┌─────────────▼───────────────────────────┐ │ SQLite-WAL │ │ • Bi-temporal history │ │ • Belief state + evidence + conflicts │ │ • Keyed by workspace_id │ └─────────────────────────────────────────┘

Hypotree is validated by apre-registered adversarial benchmarkusingqwen3.6:27b-q8_0andgemma4:31b-it-q4_K_M*. The benchmark is a set of 30 seeded combinatorial R&D problems, each with 3125 combinations (5 axes × 5 values). Each arm is run on all seeds, and the gate criteria are scored against the pre-registered thresholds.

Three arms across 30 seeded combinatorial R&D problems:

- Arm A— LLM agent with a manual Markdown scratchpad (ergonomic floor)
- Arm F— LLM agent with perfect-recall auto-transcript (steel-man baseline)
- Arm B— LLM agent on the full hypotree DAG belief state

The moat is inferential, not mnemonic.Arm F remembered every raw fact it ever saw —zeroduplicate probes across the whole run — and still lost 30/0/0, because hypotree closes questions it never has to ask:329 exclusion inferences, 37 answers deduced without a probe, 12 values eliminated by a swap that fell short. None of those is something you can look up.

# Pre-flight: confirm the engine solves every seed (no GPU) uv run python -m eval.runner.engine_selfplay # Pre-flight: score the cost-aware falsifier on a cost-weighted tariff (no GPU) uv run python -m eval.cost_gate # Full gate: 30 seeds × 3 arms ./eval.sh --run-iteration <X> --llm-model <model>

The eval harness lives ineval/and includes the frozen landscape generators, the agent runner, and the gate scorer. Run artifacts are gitignored (eval/runs/).

eval.shis bash — on Windows, run it under WSL or Git Bash. The Python parts of the harness (engine_selfplay,runner,analyse_gate,seed_reader) are cross-platform and can be driven directly.

The belief-state database is isolated by workspace. Four resolution layers, highest priority first:
- HYPOTREE_WORKSPACE_IDenv var— an explicit name. Use this for global MCP configs, where the server's working directory is not your project.
- hypotree.yaml— copyhypotree.yaml.templateto your project root:

workspace_id: my-project-name

Layer 4 is where nearly every "my belief state is empty" report comes from. Runhypotree --info, or have the agent callget_workspace_info, to see which layer actually fired:

$ hypotree --info { "workspace_id": "d94da5f61c664f94", "resolved_from": "git_remote", "database": "/home/you/.local/share/mcp_hypotree/d94da5f61c664f94/state.db", "database_exists": true, "warnings": [] }

Workspace names are lowercase[a-z0-9._~-], up to 128 characters.

XDG_DATA_HOMEoverrides on every platform, Windows included — that is how you run isolated instances side by side.

Keep it on a local disk.SQLite runs in WAL mode, which needs shared memory that network shares and most mapped drives do not provide. PointingXDG_DATA_HOMEat a UNC path or a mounted share will fail or corrupt the database.hypotree --infowarns when it detects one.

- Everything buteval.shruns natively; the evaluation harness is a bash script and needs WSL or Git Bash.
- Git is optional. Without it onPATH, layers 3 and 4 both fall through to the path hash — pin the workspace with layer 1 or 2 instead.

# Install in dev mode uv sync # Run tests uv run pytest tests/ -x -q # Lint + format uv run ruff check src/ tests/ eval/ uv run ruff format src/ tests/ eval/ # Type check uv run mypy src/hypotree/

- GitHub:github.com/tygryso/hypotree
- Changelog:
CHANGELOG.md— version history with gate results
- Agent guide:
src/hypotree/AGENT_GUIDE.md— the full contract, also served live as thehypotree://guideMCP resource

AI Reasoning Cache & Consensus Layer with 50+ reasoning objects across 14 domains. Cache hit/miss with token savings, failure risk check before execution, cross-model verification, and citation tracking. 11 MCP tools via Streamable HTTP.

A field station for AI agents: free durable memory, an agent message board, a peer Q&A oracle, a daily question, and an open CC0 census of non-human web traffic. Remote MCP server — nothing to install.

Persistent memory for AI assistants and coding agents across ChatGPT, Claude, Cursor, and other MCP-compatible tools.

Local Work Model for AI agents that learns from real outcomes.

Auditable, self-improving knowledge & memory for AI agents over MCP — citation-enforced answers and a replayable why-trace, self-hosted on Postgres.

One shared, versioned memory for your AI agents across Claude Code, Cursor, Kiro and Grok, with a source on every answer and full history.

One shared context every AI tool your team uses reads and writes over MCP, so Claude Code, Cursor and ChatGPT stay current together.

Your company's brain, connected to Claude, ChatGPT, Gemini, Cursor, and VS Code. Turn your team's email history into shared memory that any AI assistant can query with natural language.

Operational memory for AI agents that persists across sessions and tools.

No reviews yet — be the first

Sign in to leave a review

Use Google, GitHub, or an email account so ratings stay tied to real people.

Email sign in

No reviews posted yet.