If you are an agent reading this
my_work. It lists your open orders, each with its
objective, the target's own content, the premises it rests on, what has already been tried, and each done-when
predicate with how to meet it. Do what the order says, from the files, with the tools you have. Write what you find
into the record: register_run for every computation (with the exact code — print every value you
register, with its name), and the claim it supports in the same call. Numbers in a claim come from a result; a
refusal tells you the honest sentence — write that. When the reply says every predicate is met, call
return_work with a note of at most 120 words. Do not work past done. Never review your own work.
Never write "never", "proves", "edge", "optimal" or "passes" unless the record's rule for that word is met —
it will refuse you, and it will say why.Connect
The HypGraph MCP server is the whole interface. One author name per server process; you cannot write as anyone
else, and reserved names (harness, lab, operator) are refused.
pip install "hypgraph[mcp]" claude mcp add hypgraph -- hypgraph --db study.hypgraph --as nicolas mcp # in the session: my_work
hypgraph --db study.hypgraph --as nicolas mcp --record-url http://host:8765 --token "$MY_TOKEN"
The seat must exist in the run's roster with external = true; otherwise the scheduler never issues
you anything. Ask whoever runs the swarm (see for engineers).
Read an order
Everything you need is in the order; you should not need show to start. A review order looks like
this (a trading profile, out-of-sample backtest):
WORK ORDER T4 for risk (reviewer) — issued by harness at 2026-10-25T18:02:11+00:00
OBJECTIVE Review CL2, which answers Q1. The order lists the claim, its measurements and the
results it rests on, and what the instrument's re-run of the author's code confirmed —
recompute only a value it CONTRADICTED. Judge the method and the wording; record a verdict.
TARGET CL2 The strategy returns 8.1% a year out of sample after fees. — active claim · unchecked
statement: The strategy returns 8.1% a year out of sample after fees.
scope: Daily bars 2022–2024 (held out), 10 bp fees, 5 bp slippage.
measurement oos_return = 0.081 ← RS2.oos_return
rests on RS2: Out-of-sample backtest 2022–2024. — oos_return = 0.081; fees = 0.001; slippage = 0.0005; max_dd = -0.14
code of RUN3:
import pandas as pd ...
re-run by RUN4: 4 of 4 registered values confirmed by the output
PREMISES
H1 Mean reversion in the 5-day return persists after 2021. — active hypothesis · 1 line of support
DONE WHEN (checked against the record; only what you write after the order counts)
[reviewed] — an official review of the target's current version
how: review(<target>, verdict, method, notes) — by a reviewer, never the claim's author
LEASE until 2026-10-25T22:02:11+00:00
RETURN Your deliverable is the writes above … then return_work with a note of at most 120 words.| line | what it means for you |
|---|---|
| OBJECTIVE | What to do. For a review, which claim and what to judge. |
| TARGET + its content | The node's statement, measurements, the results it rests on with their values, the code behind them, and whether the instrument reproduced them. |
| PREMISES | What the order rests on, pinned to versions. If one is marked REVISED or fallen, say so in your note rather than building on it. |
| ALREADY KNOWN OR TRIED | Earlier orders on this target and why they ended. Don't repeat a failed approach without saying what is different. |
| DONE WHEN | The predicates the record will check, each with the recipe that meets it. Only writes after the order was issued count. |
A stage order
Under a profile with a workflow (scientific@2, software@2, trading@2,
knowledge@2, optimization@2 — what a profile name means now) the order tells you where the
question stands and lists the gates that move it on, in order. Write them in that order; each reply says which are
MET.
WORK ORDER T1 for quant (worker) — issued by harness at 2026-10-26T03:17:01+00:00
OBJECTIVE Q1 is at stage 'thesised' (2/8) of the trading@2 workflow — no live hypothesis with predictions
answers Q1. Move it through thesised, preregistered, backtested, claimed: Does the thesis have an
edge after costs on the held-out window?
DONE WHEN (checked against the record; only what you write after the order counts)
[hypothesis_stated] — a live hypothesis answers the target's question, with at least one prediction
[preregistered] — an experiment tests a hypothesis on the target with its expected outcome stated, written
before any run that executes it
[backtested] — a result on the target with an out-of-sample measure, a cost measure and the number of
configurations tried (trials)
[claim_made] — a claim that answers, supports, challenges or rests on the targetThe gates are the discipline's, not the prompt's: a hypothesis before the test, the experiment before the run, the
diff or the instance as an artifact with its kind and the run that uses it, a position with
its stop — or kind=no_position. A review stage never comes to you as a worker; it goes to a reviewer on
the node you produced. If a question can't be answered, register what you did find and write a claim
kind=inconclusive derived from it: checked, it settles the question at any stage, and your open order
is cancelled as moot.
Do the work
Three writes cover almost everything a worker does — plus graph_link for a link on its own
(part_of, uses, supersedes).
register_run — a computation, its result, and the claim, in one call
register_run(
name="accuracy of A on items.csv",
code="import pandas as pd\ndf = pd.read_csv('items.csv')\nk = int(df.a.sum()); n = len(df)\nprint('acc_a', k, 'of', n)",
result_summary="Counted A's correct items in items.csv.",
values={"acc_a": {"k": 812, "n": 1000}},
claim="A is right on 812 of 1000 items.", answers="Q1",
scope="The 1000 paired items in items.csv.")Three things that reply tells you: the claim went in with its number bound; your order is done; how much budget is left. Print every value you register, with its name. The instrument re-runs your code in the host's sandbox and checks the output: a value it confirms strengthens your result; one it doesn't find is "not printed" (not held against you); one it finds with a different number is contradicted, and that is what a reviewer will recompute.
graph_add — anything else: a source, a hypothesis, an experiment, a claim on its own
graph_add(type="source", fields={"citation": "Ford, J.K.B. (1991). Vocal traditions among resident killer whales.",
"doi": "10.1139/z91-206", "passage": "…dialects are stable over at least a decade…"})
graph_add(type="claim", fields={"statement": "Resident dialects are stable over at least ten years.",
"scope": "Northern and southern residents, Ford 1991.", "kind": "finding"},
links=[{"rel": "answers", "to": "Q2"}, {"rel": "cites", "to": "S1"}])review — a verdict, by a reviewer, never on your own author's work
review(node="CL2", verdict="checked", method="Read RUN3's code and RUN4's re-run; the OOS window and fees match the scope.",
notes="The claim says what the result says. The 2021 regime change is in H1's premises, not hidden.")Refusals, and what to write instead
Every refusal names a rule, says what it measured, and gives the honest sentence. These are the ones you will meet most. Write the honest version; do not argue with the record.
→ The number isn't in any of your results. Register the computation that produced it, then make the claim from that result. "A is 5 points better" becomes "A is right on 812 of 1000, B on 762 of 1000" — the record derives the 5.
→ Write exactly the honest version. The bound rides up through every claim that rests on yours; "never" would not have.
→ "A is right on 812 of 1000 and B on 800 of 1000; the difference is not significant at 0.05." The record ran the test on your own counts; it will accept that sentence.
→ You already registered this. Make the claim from RS2. If you really re-ran it on purpose (new seed, new
implementation), say so with a replicates link.
Example: scientific profile
seats analyst · stats · critic · lead done when a checked claim answers the question
Order: Answer Q2: Is A significantly better than B? You compute, register the counts with the test, and write the claim the test supports:
register_run(name="paired comparison", code="…print('a', ka, 'of', n); print('b', kb, 'of', n); print('p', p)",
result_summary="Compared A and B on the same 1000 items; two-sided z-test on the paired counts.",
values={"a": {"k": 812, "n": 1000}, "b": {"k": 800, "n": 1000}, "p": {"value": 0.49}},
claim="A is not significantly more accurate than B (812 of 1000 vs 800 of 1000, p = 0.49).", answers="Q2",
scope="The 1000 paired items in items.csv; two-sided test at 0.05.")If you had written "A is significantly better", the record would have refused it with the z-test it ran on your counts. The critic's review settles Q2; the lead writes the interpretation under the facts.
Example: software profile
seats implementer · tester · reviewer · lead stages implemented (diff_registered) → verified (tests_pass_current: the instrument ran the tests on that head) → claimed → reviewed
Order to the tester: Q3 is at stage 'implemented' — register the change, then verify it. The change is an
artifact kind=diff; your run uses it and registers the exact test command as code. The
instrument re-runs it on the same diff; that lab run is what meets tests_pass_current — your own
report of passing never does, and tests on a head a later commit superseded don't either.
graph_add(type="artifact", fields={"sha256": "9f2…", "path": "src/importer.py", "kind": "diff",
"meta": {"base_sha": "4f2a9c1", "head_sha": "b71e0d3", "files": ["src/importer.py"]}},
links=[{"rel": "part_of", "to": "Q3"}])
register_run(name="importer tests", uses=["A5"],
code="import subprocess\nr = subprocess.run(['pytest', '-q', 'tests/test_importer.py'], capture_output=True, text=True)\nprint(r.stdout[-400:])\nprint('passed', r.stdout.count(' passed'), 'of', 12)\nprint('exit_code', r.returncode)",
result_summary="Ran tests/test_importer.py: 12 passed, 0 failed.",
values={"passed": {"k": 12, "n": 12}, "exit_code": {"value": 0}}, outcome="positive",
claim="The importer passes all 12 of 12 tests in tests/test_importer.py, including quoted commas.", answers="Q3",
scope="tests/test_importer.py at head b71e0d3, run by the instrument.")outcome="negative"
and a claim that states the count ("1 of 2 checks pass") — checked, it settles the requirement as a verified
failure, and the record holds why the change did not ship.
Example: trading profile
seats quant · risk · lead stages thesised → preregistered → backtested (backtested: out of sample, after costs, trials declared) → claimed → risk-reviewed → positioned → monitored
Order to the quant: Q1 is at stage 'thesised' — move it through thesised, preregistered, backtested, claimed.
The thesis is a hypothesis; the backtest is an experiment written before the run, naming the windows, the costs
and how many configurations you will try; the result declares trials.
graph_add(type="hypothesis", fields={"statement": "After a five-day drop of 3 % or more, the next five days mean-revert.",
"predictions": ["a positive held-out return after costs"]}, links=[{"rel": "answers", "to": "Q1"}])
graph_add(type="experiment", fields={"aim": "Backtest the thesis held out.", "protocol": "Fit days 0–599; held out 600–999; 10 bp fees, 5 bp slippage; one configuration.",
"success_criteria": "positive held-out return after costs"},
links=[{"rel": "tests", "to": "H1", "data": {"expected": "positive held-out return after costs"}}])
register_run(name="OOS backtest 2022–2024", experiment="X1", code="…print('oos_return', oos_ret); print('fees', fees); print('slippage', slip); print('trials', 1)",
result_summary="Backtested the thesis on the held-out window 2022–2024 with 10 bp fees and 5 bp slippage.",
values={"oos_return": {"value": 0.081}, "fees": {"value": 0.001}, "slippage": {"value": 0.0005}, "max_dd": {"value": -0.14}, "trials": {"value": 1}},
claim="The strategy returns 8.1% a year out of sample after fees, with a 14% maximum drawdown.", answers="Q1",
scope="Daily bars 2022–2024 held out; 10 bp fees, 5 bp slippage; one configuration tried; no leverage.")→ Both are the same rule from two sides: a return without costs is not a result here, and "edge" from the fitting
window is not a claim — nor is an edge whose result doesn't say how many configurations were tried. After the risk
review, the position order asks for a decision based_on the claim: kind="position" with
size, stop, review_date and paper: true — or
kind="no_position" when the thesis is declined. Past its review date with nothing newer, a position is
flagged. There is no live-order path, and nothing you write can create one.
Example: knowledge profile
seats researcher · fact_checker · lead stages sourced (source_quoted: the passage, retrieved, kind) → claimed (sourced) → checked
Order: Q1 is at stage 'sourced' — when was the Peace of Westphalia signed? Add what you read as a source
part_of the question — citation, URL or DOI, the passage that says it, the date you read it, its
kind — then the claim that cites it. Recall is not a source; the record refuses a bare claim and a source without
its passage.
graph_add(type="source", fields={"citation": "Encyclopaedia Britannica, 'Peace of Westphalia'.",
"url": "https://www.britannica.com/event/Peace-of-Westphalia",
"passage": "…signed on October 24, 1648…", "retrieved": "2026-10-25", "kind": "secondary"},
links=[{"rel": "part_of", "to": "Q1"}])
graph_add(type="claim", fields={"statement": "The Peace of Westphalia was signed on 24 October 1648.",
"scope": "The treaties of Osnabrück and Münster, 1648.", "kind": "finding"},
links=[{"rel": "answers", "to": "Q1"}, {"rel": "cites", "to": "S1"}])→ Add the source first. The fact-checker opens it and records the verdict; the final report is linted against the
record, so a sentence that treats an unreviewed claim as settled is refused there too. A source that is later
withdrawn puts every claim citing it at risk. When no source answers the question, register the search as a run
with its result ("read 3 of 3 pages; 0 of 3 mention it") and a claim kind="inconclusive" derived from
it — checked, it settles the question honestly.
Example: optimization profile
seats modeller · solver · verifier · lead stages posed (instance_registered) → modelled → configured → solved (solved) → verified (result_reviewed) → claimed → checked
The instance is an artifact kind=instance part_of the question; the model is a hypothesis;
the solve configuration is an experiment; the run uses the instance. The verifier reviews the result
— recomputing feasibility — before the claim; a solve on an instance that has since changed is stale.
graph_add(type="artifact", fields={"sha256": "c31…", "path": "instances/40-site.json", "kind": "instance"}, links=[{"rel": "part_of", "to": "Q1"}])
register_run(name="CBC solve, 40 sites", uses=["A1"], experiment="X1",
code="…print('objective', obj); print('feasible', feasible); print('gap', gap); print('runtime_s', t)",
result_summary="Solved the 40-site facility model with CBC to a 0.4% MIP gap in 118 s.",
values={"objective": {"value": 412.6, "unit": "k$"}, "feasible": {"value": true}, "gap": {"value": 0.004}, "runtime_s": {"value": 118}},
claim="The best solution found costs 412.6 k$ with a 0.4% optimality gap.", answers="Q1",
scope="The 40-site instance with the stated demand and capacity constraints; CBC, 120 s limit.")→ "Best found, gap 0.4 %" is accepted; "optimal" needs gap = 0 or a bound that meets the objective.
A result with an objective and no feasible is refused before it is even a result.
If you are a reviewer
You hold review orders. The order carries the claim, its measurements, the results it rests on with their values,
the code that produced them, and the instrument's re-run verdict. Judge; don't recompute — recompute only a
value the instrument marked contradicted. Verdicts: checked / pass (it holds),
fail (it doesn't, and why), objection (a specific problem the author must answer),
inconclusive, comment. You cannot review your own author's work, and you cannot write
claims — if the right answer is missing, say so in your notes and return the order; a worker will be asked.
Return, rework, notices
- Return when the reply says every predicate is met:
return_work(note=…), ≤ 120 words — what you did, what you could not. If you stop without returning, the record returns the order on your behalf and the scheduler decides. - Rework. An order that comes back NOT MET returns to you as a new order saying what was missing — at most twice; then the lead judges. If your seat names a deeper model, the rework runs on it.
- Notices. A file declared corrupt is withdrawn in the record and its replacement registered; every order
issued afterwards says so, and
read_filerefuses the withdrawn bytes with the reason. An order resting on a fallen premise is cancelled — check your premises' standing when you resume. - Stage and completion.
stagesays where each question stands in the profile's workflow and which gate is next;completionsays what the profile means by done for the whole investigation and which criteria are met — useful before you tell anyone it's finished.
If you are a person
Everything above applies to you as written: the record can't tell a person from an agent except by name. Hold
your seat from a coding agent (Claude Code, Cursor) with the MCP server, or from the CLI — hypgraph
--db study.hypgraph orders lists orders, hypgraph brief compiles the orchestrator's view. A
token bound to your name is how a served record knows it's you.