hypswarm 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,31 @@
1
+ name: ci
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ pull_request:
6
+ jobs:
7
+ test:
8
+ runs-on: ${{ matrix.os }}
9
+ strategy:
10
+ fail-fast: false
11
+ matrix:
12
+ os: [ubuntu-latest, windows-latest]
13
+ python: ["3.11", "3.12", "3.13"]
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: actions/checkout@v4
17
+ with:
18
+ repository: voodoomods/hypgraph
19
+ ref: harmony-study # the coordination layer lives here until it merges and releases
20
+ path: hypgraph
21
+ - uses: actions/setup-python@v5
22
+ with:
23
+ python-version: ${{ matrix.python }}
24
+ - run: pip install -e ".[dev]" --no-deps && pip install httpx pytest "mypy==2.4.0" "ruff==0.17.2" fastmcp anthropic
25
+ - run: python -m ruff check src tests --output-format=github
26
+ - run: python -m mypy --strict src/hypswarm
27
+ env:
28
+ MYPYPATH: ${{ github.workspace }}/hypgraph/src
29
+ - run: python -m pytest -q
30
+ env:
31
+ HYPGRAPH_SRC: ${{ github.workspace }}/hypgraph/src
@@ -0,0 +1,33 @@
1
+ # hypswarm.com: publish site/ to GitHub Pages. Runs on push to main once Pages is enabled for the repository
2
+ # (Settings → Pages → Source: GitHub Actions) and the domain's DNS points at GitHub, as hypgraph.com's does.
3
+ name: pages
4
+ on:
5
+ push:
6
+ branches: [main]
7
+ paths: ["site/**", ".github/workflows/pages.yml"]
8
+ workflow_dispatch:
9
+
10
+ permissions:
11
+ contents: read
12
+ pages: write
13
+ id-token: write
14
+
15
+ concurrency:
16
+ group: pages
17
+ cancel-in-progress: true
18
+
19
+ jobs:
20
+ deploy:
21
+ runs-on: ubuntu-latest
22
+ environment:
23
+ name: github-pages
24
+ url: ${{ steps.deploy.outputs.page_url }}
25
+ steps:
26
+ - uses: actions/checkout@v4
27
+ - run: python -c "import re,sys;s=open('site/index.html').read();bad=re.findall(r'(?:href|src)=\"/(?!/)',s);sys.exit('root-absolute paths: %d'%len(bad) if bad else 0)"
28
+ - uses: actions/configure-pages@v5
29
+ - uses: actions/upload-pages-artifact@v3
30
+ with:
31
+ path: site
32
+ - id: deploy
33
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,41 @@
1
+ # Tag v0.1.0a1 → build the sdist and wheel, test the wheel, publish to PyPI with trusted publishing (no API token:
2
+ # the "pypi" environment and a trusted publisher for this repository are configured on pypi.org).
3
+ # Don't tag a release before HypGraph's coordination layer is on PyPI (hypgraph>=0.4): the wheel would not install.
4
+ name: release
5
+ on:
6
+ push:
7
+ tags: ["v*"]
8
+
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: actions/setup-python@v5
15
+ with:
16
+ python-version: "3.12"
17
+ - run: python -m pip install build
18
+ - run: python -m build
19
+ - name: The tag matches the package version
20
+ run: test "v$(python -c 'import re;print(re.search(r"__version__ = \"(.+?)\"", open("src/hypswarm/__init__.py").read())[1])')" = "${GITHUB_REF_NAME}"
21
+ - name: The wheel works on its own
22
+ run: |
23
+ python -m venv /tmp/w && /tmp/w/bin/pip install dist/*.whl
24
+ /tmp/w/bin/hypswarm --version
25
+ - uses: actions/upload-artifact@v4
26
+ with:
27
+ name: dist
28
+ path: dist/
29
+
30
+ publish:
31
+ needs: build
32
+ runs-on: ubuntu-latest
33
+ environment: pypi
34
+ permissions:
35
+ id-token: write
36
+ steps:
37
+ - uses: actions/download-artifact@v4
38
+ with:
39
+ name: dist
40
+ path: dist/
41
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,13 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .pytest_cache/
4
+ .mypy_cache/
5
+ .ruff_cache/
6
+ dist/
7
+ build/
8
+ *.egg-info/
9
+ *.hypgraph
10
+ *.hypgraph-journal
11
+ .claude/
12
+ .env
13
+ .venv/
hypswarm-0.0.1/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
@@ -0,0 +1,41 @@
1
+ Metadata-Version: 2.5
2
+ Name: hypswarm
3
+ Version: 0.0.1
4
+ Summary: Run one agent or a swarm of them on a task, with a HypGraph record as the only shared state. This release reserves the name; the alpha is on GitHub.
5
+ Project-URL: Homepage, https://hypswarm.com
6
+ Project-URL: Source, https://github.com/voodoomods/hypswarm
7
+ Project-URL: Record, https://hypgraph.com
8
+ Author: Nicolas Houghtaling, VoodooMods LLC
9
+ Maintainer: VoodooMods LLC
10
+ License-Expression: Apache-2.0
11
+ License-File: LICENSE
12
+ Keywords: agents,hypgraph,multi-agent,orchestration,research,swarm
13
+ Classifier: Development Status :: 2 - Pre-Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Typing :: Typed
18
+ Requires-Python: >=3.11
19
+ Description-Content-Type: text/markdown
20
+
21
+ <p align="center"><img src="https://raw.githubusercontent.com/voodoomods/hypswarm/main/site/assets/hypswarm.svg" width="72" alt=""></p>
22
+
23
+ <h1 align="center">hypswarm</h1>
24
+ <p align="center"><b>Many agents. One record.</b><br>
25
+ Run one agent or a swarm of them on a research or building task, with a <a href="https://hypgraph.com">HypGraph</a>
26
+ record as the only shared state.<br>
27
+ <a href="https://hypswarm.com">hypswarm.com</a> · <a href="https://github.com/voodoomods/hypswarm">source</a> ·
28
+ <a href="https://hypgraph.com">HypGraph</a></p>
29
+
30
+ ---
31
+
32
+ **This release reserves the name.** The alpha — the scheduler, workers, external seats over MCP, the record server
33
+ mode, the OpenAI-compatible and Anthropic adapters — lives on [GitHub](https://github.com/voodoomods/hypswarm) and
34
+ installs from there until HypGraph's coordination layer is on PyPI:
35
+
36
+ ```bash
37
+ pip install "hypgraph @ git+https://github.com/voodoomods/hypgraph@harmony-study"
38
+ pip install git+https://github.com/voodoomods/hypswarm
39
+ ```
40
+
41
+ Made by Nicolas Houghtaling at [VoodooMods LLC](https://github.com/voodoomods). Apache-2.0.
@@ -0,0 +1,21 @@
1
+ <p align="center"><img src="https://raw.githubusercontent.com/voodoomods/hypswarm/main/site/assets/hypswarm.svg" width="72" alt=""></p>
2
+
3
+ <h1 align="center">hypswarm</h1>
4
+ <p align="center"><b>Many agents. One record.</b><br>
5
+ Run one agent or a swarm of them on a research or building task, with a <a href="https://hypgraph.com">HypGraph</a>
6
+ record as the only shared state.<br>
7
+ <a href="https://hypswarm.com">hypswarm.com</a> · <a href="https://github.com/voodoomods/hypswarm">source</a> ·
8
+ <a href="https://hypgraph.com">HypGraph</a></p>
9
+
10
+ ---
11
+
12
+ **This release reserves the name.** The alpha — the scheduler, workers, external seats over MCP, the record server
13
+ mode, the OpenAI-compatible and Anthropic adapters — lives on [GitHub](https://github.com/voodoomods/hypswarm) and
14
+ installs from there until HypGraph's coordination layer is on PyPI:
15
+
16
+ ```bash
17
+ pip install "hypgraph @ git+https://github.com/voodoomods/hypgraph@harmony-study"
18
+ pip install git+https://github.com/voodoomods/hypswarm
19
+ ```
20
+
21
+ Made by Nicolas Houghtaling at [VoodooMods LLC](https://github.com/voodoomods). Apache-2.0.
@@ -0,0 +1,193 @@
1
+ # hypswarm — design, alpha
2
+
3
+ *Draft 1, 2026-10-24. Not built yet. Written after four harmony pilots (37 runs of agent teams coordinating
4
+ through a HypGraph record), whose logs are the evidence for most choices below.*
5
+
6
+ **One sentence.** hypswarm runs one agent or a swarm of them on a research or building task, with a HypGraph
7
+ record as the only shared state: the record schedules the work, accepts it, stops what became pointless, and
8
+ writes the report; models are called only to do work and to judge exceptions.
9
+
10
+ ---
11
+
12
+ ## 1. What the pilots taught, and what it forces
13
+
14
+ | Observed | Consequence for the design |
15
+ |---|---|
16
+ | Most of what an orchestrator model did was mechanical: what is open, who is on what, is this done, accept it. In pilot 3 those were 25–40 % of its calls. | The scheduler is code, not a model. A model is called only for judgement. |
17
+ | Sub-agents worked past done until the record told them they were done; they returned when it did. | Every tool reply carries the agent's control state. No agent asks whether it is finished. |
18
+ | An order's predicate could be unmeetable with the agent's tools; the lead reworked it three times. | Orders are meetable by construction (D-10): the record decides done-ness from what was written under the lease. |
19
+ | Two workers re-derived the same numbers in one run; the record's lease stopped a third. | Parallel workers are safe only because the record leases targets. Parallelism is a scheduler feature, not a prompt instruction. |
20
+ | The best reports came from the record condition: every number traceable, the trap named. | The report is generated from the record; the model writes interpretation under it and the linter gates it. |
21
+ | A whole run cost cents; the cost was retries and turns, never the checks. | The budget is enforced by the scheduler in calls and dollars, per run and per order, and shown in every reply. |
22
+
23
+ ## 2. Build or borrow
24
+
25
+ **Decision: a thin harness of our own over an OpenAI-compatible chat adapter, with LangChain and Anthropic as
26
+ optional adapters, and MCP as the worker protocol.** Reasons:
27
+
28
+ - The control loop *is* the record. LangGraph and deepagents exist to hold agent state in a graph of their own,
29
+ checkpoint it and route between nodes; here the record is the state and the checkpoint, and routing is the
30
+ scheduler. Building on them means two state machines that disagree. Pegasus runs on deepagents and pays for
31
+ that in middleware stacks and 35,000-token calls.
32
+ - The study runner (`Pegasus/pod/dev/study_runner.py`, condition C) is already a working embryo in ~200 lines
33
+ of its own loop plus `langchain_core`'s message and tool types. Nothing in it needs LangChain's agent
34
+ machinery. The model-facing surface is four tool shapes and one call: `model(messages, tools) -> message`.
35
+ - An OpenAI-compatible adapter covers DeepInfra, OpenAI, NVIDIA NIM, vLLM, Ollama, Together and most gateways
36
+ with one `httpx` client. Anthropic gets its own adapter. A `langchain` adapter wraps any `BaseChatModel` so
37
+ LangChain users bring their models without us depending on LangChain.
38
+ - **MCP is the worker protocol.** The HypGraph MCP server already exposes `my_work`, the record tools and
39
+ `return_work`. A worker is anything that can hold an MCP session and act on a work order: hypswarm's built-in
40
+ worker, a human developer's Claude Code or Cursor session, or a third-party agent. That is how "usable by
41
+ humans and agents" is met without two code paths: a person and an agent take the same order from the same
42
+ board, and the record can't tell them apart except by name.
43
+
44
+ Dependencies of the core: `hypgraph`, `httpx`. Extras: `[anthropic]`, `[langchain]`, `[mcp]` (FastMCP client,
45
+ to drive external workers), `[server]`. Python ≥ 3.10. Stdlib `dataclasses` for config; no pydantic in the core.
46
+
47
+ ## 3. The agent
48
+
49
+ There is one program. "Solo scientist" and "orchestrator with a swarm" are the same program with different
50
+ seats and a worker count.
51
+
52
+ ### 3.1 Seats, not personalities
53
+
54
+ A seat is a declared capability bound to one author name in the record. Prompts stay short; the work order
55
+ carries the task.
56
+
57
+ | Seat | What it does | Model? |
58
+ |---|---|---|
59
+ | **worker** | Takes orders from the board; writes runs, results, claims; returns. Declares `takes` (kinds of work) and `tools` (data tools it may use). | yes |
60
+ | **reviewer** | Takes review orders. Named in the record's `Policy.reviewers`, so its verdicts count. Never reviews its own author's work (the record refuses). | yes |
61
+ | **lead** | Called at exceptions only: an order NOT MET after two reworks, a contested claim, an empty frontier with unsettled questions, and the report's interpretation. | yes, deeper model |
62
+ | **instrument** | Not a model. A job runner (CI, a lab) that files runs as the policy's `instrument`, so its results are lab-recorded rather than agent-reported. | no |
63
+ | **operator** | A person. Approves budgets, answers escalations, resolves objections. Reached through the record (a question node + a notification), never through chat state. | no |
64
+
65
+ A solo scientist is one worker seat that is also a reviewer of nobody (its claims stay unchecked, honestly) plus a
66
+ lead that is the same model; the scheduler still issues it orders from the board, one at a time. A swarm is *k*
67
+ workers and *r* reviewers pulling in parallel.
68
+
69
+ ### 3.2 The worker loop
70
+
71
+ ```
72
+ order = my_work() # the record's text: objective, target, premises, known, predicates with recipes
73
+ loop (≤ turn cap, ≤ order budget):
74
+ reply = model(system=seat prompt, messages=[order, …], tools=data tools + record tools)
75
+ run its tool calls; every record write returns the order's predicate status
76
+ stop when the model calls return_work, or the reply says every predicate is met and the model stops calling tools
77
+ ```
78
+
79
+ The worker holds no state between orders. It can be killed and another worker takes the lease when it expires.
80
+ Its context is the order text plus its own turn history, nothing else; the record is read on demand with `show`.
81
+
82
+ ### 3.3 The scheduler (no model calls)
83
+
84
+ ```
85
+ until every question is settled, or the budget is spent, or the operator stops it:
86
+ board = question_board()
87
+ cancel_moot() # premises that fell
88
+ settle() # returned orders with every predicate met
89
+ for order in returned and not met:
90
+ rework ≤ 2 (what is missing, from check_work) # then escalate to the lead seat
91
+ for question in board where open, no order, a worker is idle:
92
+ issue_work(question → best-fit worker by takes; default predicates)
93
+ for question where answered and unchecked, a reviewer is idle:
94
+ issue_work(answering claim → reviewer, [reviewed]) # one review settles a question
95
+ for experiment on the frontier (planned, unleased), a worker is idle:
96
+ issue_work(experiment → worker)
97
+ wait for a return (asyncio), or a lease to expire
98
+ report: order the lead to write the interpretation under report(); submit only when check_text passes
99
+ ```
100
+
101
+ Best-fit is deterministic (a worker's `takes` against the target's type and the question's words, idle first),
102
+ like Pegasus's dispatcher. Every scheduler action is already an event in the record (orders are task nodes;
103
+ acceptance is a decision), so the run's audit trail is the record itself.
104
+
105
+ ### 3.4 Many angles, one record
106
+
107
+ A swarm attacks a problem from several angles by construction: the lead (or the task author) adds rival
108
+ hypotheses with `alternative_to` and experiments that `tests` them with stated expectations; `next_experiments`
109
+ ranks by how well they separate the hypotheses; workers take different experiments under leases; results that
110
+ share a run or data count as one line of support; a claim built on a withdrawn premise goes AT RISK and the
111
+ orders resting on it are cancelled. None of that is new code; it is what the record already derives. hypswarm's
112
+ job is to keep workers pulling from it.
113
+
114
+ ### 3.5 Building tasks
115
+
116
+ Same program, one convention: the CI runner is the `instrument`. A requirement is a question. A design choice is
117
+ a decision `based_on` the claims that justify it, flagged REVISIT when one falls. A change is a run (`code`
118
+ artifact = the commit sha) that produced a result (tests passed of tests run), filed by CI as lab-recorded.
119
+ "The change makes the tests pass" is a claim with a k/n measurement bound to that result, so the agent can't
120
+ assert it; only the instrument can produce the number. A regression is a withdrawal with a blast radius. No new
121
+ node types.
122
+
123
+ ## 4. Enterprise grade, concretely
124
+
125
+ - **One record server, many stateless workers.** `hypgraph serve --writable` (or the MCP server over HTTP) is
126
+ the single writer; workers talk to it over MCP/HTTP with a bearer per seat, never to the SQLite file. Workers
127
+ scale horizontally and die safely; the record is the checkpoint and the audit log.
128
+ - **Budget as a hard rule.** Per run and per order, in calls and dollars; the scheduler refuses to issue an
129
+ order that can't fit; the worker sees calls remaining in every reply. Spend is read from the host's meter when
130
+ one exists (Pegasus's proxy ledger), else counted from the provider's usage fields.
131
+ - **Provenance of the run itself.** Every run files one `run` node of kind `agent` holding: hypswarm version,
132
+ record version, the seats and their models, prompt hashes, tool versions, seeds, start/finish. A run is
133
+ reproducible from the record and the seeds.
134
+ - **Secrets never in the record.** API keys live in the adapters' environment; the record holds author names and
135
+ hashes. Tool outputs are scrubbed before they are written as notes (the Pegasus scrubber, ported).
136
+ - **Resumable, idempotent.** A restarted run reads the board and continues; orders carry leases with expiry;
137
+ nothing is re-issued that is open, nothing re-done that is settled.
138
+ - **Observable.** Structured logs (one JSON line per scheduler action and model call, with the order code),
139
+ optional OpenTelemetry spans, and `hypswarm status` reading the board. The Atlas gets an *Orders* card.
140
+ - **Typed, tested, versioned.** A typed public API (`hypswarm.run(task, seats, record, budget)`), `py.typed`,
141
+ mypy-clean, a test suite that runs every scheduler path on a stub model in seconds, the same preregistered
142
+ task suite as the harmony study for end-to-end checks, semantic versioning, Apache-2.0.
143
+ - **A CLI people can operate.** `hypswarm run --record study.hypgraph --task task.md --seats seats.toml
144
+ --budget 2.00`, `hypswarm status`, `hypswarm stop`, `hypswarm resume`, `hypswarm report`.
145
+
146
+ ## 5. Measuring it
147
+
148
+ hypswarm joins the harmony study as **condition E, "record-scheduled swarm"**: four workers in parallel, one
149
+ reviewer, a lead called only at exceptions, same task suite, same caps, same subject model, preregistered as a
150
+ deviation before it runs. Against C it isolates two things: how much of the lead's cost the scheduler removes
151
+ (calls per run, lead calls per run), and what parallelism does to wall time at the same spend. Against B it is
152
+ the comparison that matters for the paper. The study already meters every call and labels every unit, so no new
153
+ instrumentation is needed. Prediction, stated now: calls per run near D's (≈ 80), lead calls under 10, wall time
154
+ cut by roughly the worker count on families with independent sub-questions, and no change on F7's cascade,
155
+ which is sequential by nature.
156
+
157
+ ## 6. Build order (alpha)
158
+
159
+ 1. **Scaffold** (`src/hypswarm/`): `seats.py`, `providers/` (openai_compat, anthropic, langchain), `worker.py`,
160
+ `scheduler.py`, `budget.py`, `run.py` (the public API), `cli.py`; tests on a stub provider.
161
+ 2. **Port condition C** from the study runner into it, then make the study harness run condition E through
162
+ hypswarm. Measure (§5).
163
+ 3. **MCP workers**: external agents join a run by holding an MCP session; the scheduler sees them as seats.
164
+ 4. **Operator surface**: `hypswarm status`, the Atlas Orders card, operator questions through the record.
165
+ 5. **Building adapter**: CI as instrument, the commit-as-artifact convention, one worked example repo.
166
+
167
+ Step 2 is the one that produces a number; everything after it is shaped by that number.
168
+
169
+ ## 7. What hypswarm is not
170
+
171
+ Not a chat framework, not a prompt library, not a place where state lives. If a feature needs the agents to
172
+ remember something the record doesn't hold, the record is missing a node type, and that is where the fix goes.
173
+
174
+ ---
175
+
176
+ ## First real-model run (2026-10-24, plumbing, not a study result)
177
+
178
+ `Pegasus/pod/dev/hypswarm_smoke_host.py`: harmony-suite family F1 on seed 0 (the dry-run seed), DeepSeek-V4.1-Flash
179
+ for every seat, three workers + a critic + a lead, the study's sandboxed python tool, run inside the agent
180
+ container through the proxy so every call was metered under its own label.
181
+
182
+ | | hypswarm alpha | condition C in pilots 2–4 (same family, same model) |
183
+ |---|---|---|
184
+ | finished | yes, every question settled | 7 of 8 runs |
185
+ | calls | **59** (lead 4: the report only) | 92–150 (lead 11–26) |
186
+ | metered $ | **0.019** (priced and ledger agree to the cent) | 0.029–0.050 |
187
+ | orders | 8: 4 answers + 4 reviews, 0 reworks, all accepted by the record | 5–12, 1–5 reworks |
188
+ | workers returned on their own | 8 of 8 | about half |
189
+ | score | 4 of 4, no trap | — |
190
+ | wall | 67 s (3 workers in parallel) | 4–11 min |
191
+
192
+ One run on one seed, unpreregistered, so it proves the plumbing and sizes the expectation, nothing more. The
193
+ measured comparison is condition E in the harmony study, preregistered first.
@@ -0,0 +1,34 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.25"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "hypswarm"
7
+ version = "0.0.1"
8
+ description = "Run one agent or a swarm of them on a task, with a HypGraph record as the only shared state. This release reserves the name; the alpha is on GitHub."
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = "Apache-2.0"
12
+ license-files = ["LICENSE"]
13
+ authors = [{ name = "Nicolas Houghtaling" }, { name = "VoodooMods LLC" }]
14
+ maintainers = [{ name = "VoodooMods LLC" }]
15
+ keywords = ["agents", "multi-agent", "research", "hypgraph", "orchestration", "swarm"]
16
+ classifiers = [
17
+ "Development Status :: 2 - Pre-Alpha",
18
+ "Intended Audience :: Developers",
19
+ "Intended Audience :: Science/Research",
20
+ "Programming Language :: Python :: 3",
21
+ "Typing :: Typed",
22
+ ]
23
+ dependencies = []
24
+
25
+ [project.urls]
26
+ Homepage = "https://hypswarm.com"
27
+ Source = "https://github.com/voodoomods/hypswarm"
28
+ Record = "https://hypgraph.com"
29
+
30
+ [project.scripts]
31
+ hypswarm = "hypswarm.cli:main"
32
+
33
+ [tool.hatch.build.targets.wheel]
34
+ packages = ["src/hypswarm"]
@@ -0,0 +1,14 @@
1
+ <!doctype html>
2
+ <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
3
+ <title>Not found — hypswarm</title>
4
+ <script>
5
+ // Served for a missing path at any depth: resolve links from the site root, "/" on hypswarm.com and "/<repo>/"
6
+ // on <owner>.github.io.
7
+ document.write('<base href="' + (location.hostname.endsWith('.github.io') ? '/' + location.pathname.split('/')[1] + '/' : '/') + '">');
8
+ </script>
9
+ <link rel="icon" href="assets/hypswarm.svg" type="image/svg+xml">
10
+ <link rel="stylesheet" href="assets/site.css"></head>
11
+ <body><main class="wrap" style="padding:96px 16px;text-align:center">
12
+ <div class="kicker">404 · no order here</div>
13
+ <h1 class="title" style="font-size:clamp(34px,6vw,64px)">No seat at this address.</h1>
14
+ <p class="lede">The lease on this page ran out. Try <a href="./">the start</a> or <a href="https://hypgraph.com">HypGraph</a>.</p></main></body></html>
@@ -0,0 +1 @@
1
+ hypswarm.com
@@ -0,0 +1,16 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="hypswarm">
2
+ <rect width="64" height="64" rx="14" fill="#0a0d14"/>
3
+ <g fill="none" stroke-width="2.5" stroke-linecap="round">
4
+ <path d="M32 32 L16 18" stroke="#7cf3ff"/>
5
+ <path d="M32 32 L48 18" stroke="#7cf3ff"/>
6
+ <path d="M32 32 L14 42" stroke="#b18cff" stroke-dasharray="3 4"/>
7
+ <path d="M32 32 L50 42" stroke="#b18cff" stroke-dasharray="3 4"/>
8
+ <path d="M32 32 L32 52" stroke="#7cf3ff"/>
9
+ </g>
10
+ <circle cx="32" cy="32" r="7" fill="#4ee08a"/>
11
+ <circle cx="16" cy="18" r="4" fill="#7cf3ff"/>
12
+ <circle cx="48" cy="18" r="4" fill="#7cf3ff"/>
13
+ <circle cx="14" cy="42" r="4" fill="#b18cff"/>
14
+ <circle cx="50" cy="42" r="4" fill="#b18cff"/>
15
+ <circle cx="32" cy="52" r="4" fill="none" stroke="#ff4d5e" stroke-width="2.5"/>
16
+ </svg>
@@ -0,0 +1,207 @@
1
+ /* hypgraph.com — one stylesheet. Dark by default, light via prefers-color-scheme or the toggle (html[data-theme]). */
2
+
3
+ :root {
4
+ --bg: #06080d; --bg2: #0b0f17; --panel: #0f1520; --panel2: #131b29;
5
+ --ink: #e8eef7; --ink2: #a3b0c2; --ink3: #64748b; --line: #1c2533; --line2: #2a3648;
6
+ --accent: #7cf3ff; --violet: #b18cff; --green: #4ee08a; --red: #ff4d5e; --amber: #ffb547;
7
+ --glow: 0 0 0 1px rgba(124, 243, 255, .18), 0 10px 40px rgba(124, 243, 255, .08);
8
+ --mono: ui-monospace, "JetBrains Mono", "SFMono-Regular", "Cascadia Code", Menlo, Consolas, monospace;
9
+ --sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
10
+ --r: 14px; --max: 1160px;
11
+ color-scheme: dark;
12
+ }
13
+ @media (prefers-color-scheme: light) {
14
+ :root:not([data-theme="dark"]) {
15
+ --bg: #f7f8fb; --bg2: #eef1f6; --panel: #ffffff; --panel2: #f3f5f9;
16
+ --ink: #0d1321; --ink2: #475569; --ink3: #8a96a8; --line: #dbe1ea; --line2: #c7d0dd;
17
+ --accent: #0b6bcb; --violet: #6d4bd8; --green: #0a7a3c; --red: #c4182a; --amber: #a35f00;
18
+ --glow: 0 0 0 1px rgba(11, 107, 203, .12), 0 10px 30px rgba(13, 19, 33, .06);
19
+ color-scheme: light;
20
+ }
21
+ }
22
+ :root[data-theme="light"] {
23
+ --bg: #f7f8fb; --bg2: #eef1f6; --panel: #ffffff; --panel2: #f3f5f9;
24
+ --ink: #0d1321; --ink2: #475569; --ink3: #8a96a8; --line: #dbe1ea; --line2: #c7d0dd;
25
+ --accent: #0b6bcb; --violet: #6d4bd8; --green: #0a7a3c; --red: #c4182a; --amber: #a35f00;
26
+ --glow: 0 0 0 1px rgba(11, 107, 203, .12), 0 10px 30px rgba(13, 19, 33, .06);
27
+ color-scheme: light;
28
+ }
29
+
30
+ *, *::before, *::after { box-sizing: border-box; }
31
+ html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
32
+ @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
33
+ body { margin: 0; background: var(--bg); color: var(--ink); font: 16px/1.6 var(--sans); }
34
+ a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 3px; }
35
+ code, pre, kbd { font-family: var(--mono); }
36
+ code { font-size: .9em; background: var(--panel2); border: 1px solid var(--line); border-radius: 6px; padding: 1px 6px; }
37
+ pre { margin: 0; }
38
+ img, svg { max-width: 100%; }
39
+ :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
40
+ .skip { position: absolute; left: -9999px; } .skip:focus { left: 16px; top: 16px; z-index: 99; background: var(--panel); padding: 8px 12px; }
41
+
42
+ .wrap { max-width: var(--max); margin: 0 auto; padding: 0 16px; }
43
+ @media (min-width: 720px) { .wrap { padding: 0 28px; } }
44
+
45
+ /* ── nav ── */
46
+ .nav { position: sticky; top: 0; z-index: 50; backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
47
+ background: color-mix(in srgb, var(--bg) 78%, transparent); border-bottom: 1px solid var(--line); }
48
+ .nav .wrap { display: flex; align-items: center; gap: 18px; height: 58px; }
49
+ .brand { display: flex; align-items: center; gap: 10px; color: var(--ink); text-decoration: none; font-weight: 700;
50
+ letter-spacing: -.01em; font-size: 17px; }
51
+ .brand img { width: 28px; height: 28px; }
52
+ .brand b { font-family: var(--mono); font-weight: 600; color: var(--accent); }
53
+ .nav nav { display: flex; gap: 4px; margin-left: auto; align-items: center; }
54
+ .nav nav a { color: var(--ink2); text-decoration: none; padding: 6px 10px; border-radius: 8px; font-size: 14px; }
55
+ .nav nav a:hover, .nav nav a[aria-current="page"] { color: var(--ink); background: var(--panel2); }
56
+ .iconbtn { background: none; border: 1px solid var(--line2); color: var(--ink2); width: 34px; height: 34px;
57
+ border-radius: 9px; cursor: pointer; display: inline-grid; place-items: center; font-size: 15px; }
58
+ .iconbtn:hover { color: var(--ink); border-color: var(--accent); }
59
+ @media (max-width: 760px) { .nav nav a.hide-sm { display: none; } }
60
+ @media (max-width: 420px) { .nav nav a { padding: 6px 6px; font-size: 13px; } .brand span { display: none; } }
61
+
62
+ /* ── hero ── */
63
+ .hero { position: relative; overflow: hidden; border-bottom: 1px solid var(--line); }
64
+ .hero canvas { position: absolute; inset: 0; width: 100%; height: 100%; opacity: .9; }
65
+ .hero::after { content: ""; position: absolute; inset: 0; pointer-events: none;
66
+ background: radial-gradient(ellipse 70% 60% at 50% 40%, transparent 0%, var(--bg) 85%); }
67
+ .hero .wrap { position: relative; z-index: 2; padding-top: 88px; padding-bottom: 72px; text-align: center; }
68
+ .eyebrow { display: inline-flex; gap: 8px; align-items: center; font-family: var(--mono); font-size: 12px;
69
+ letter-spacing: .14em; text-transform: uppercase; color: var(--ink2); border: 1px solid var(--line2);
70
+ background: color-mix(in srgb, var(--panel) 70%, transparent); padding: 5px 12px; border-radius: 999px; }
71
+ .eyebrow i { width: 7px; height: 7px; border-radius: 50%; background: var(--green); box-shadow: 0 0 10px var(--green); }
72
+ h1.title { font-size: clamp(38px, 7.4vw, 86px); line-height: 1.02; letter-spacing: -.035em; margin: 22px 0 18px;
73
+ font-weight: 800; }
74
+ h1.title .l2 { display: block; background: linear-gradient(92deg, var(--accent), var(--violet) 55%, var(--green));
75
+ -webkit-background-clip: text; background-clip: text; color: transparent; }
76
+ .lede { font-size: clamp(17px, 2.1vw, 21px); color: var(--ink2); max-width: 760px; margin: 0 auto; }
77
+
78
+ /* ── the door ── */
79
+ .door { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; max-width: 920px; margin: 40px auto 0; text-align: left; }
80
+ @media (max-width: 720px) { .door { grid-template-columns: 1fr; } }
81
+ .portal { position: relative; display: block; text-decoration: none; color: var(--ink); background: var(--panel);
82
+ border: 1px solid var(--line2); border-radius: var(--r); padding: 22px 22px 20px; box-shadow: var(--glow);
83
+ transition: transform .18s ease, border-color .18s ease; overflow: hidden; }
84
+ .portal:hover { transform: translateY(-2px); border-color: var(--accent); }
85
+ @media (prefers-reduced-motion: reduce) { .portal { transition: none; } .portal:hover { transform: none; } }
86
+ .portal .who { font-family: var(--mono); font-size: 12px; letter-spacing: .14em; text-transform: uppercase; color: var(--accent); }
87
+ .portal.agent .who { color: var(--violet); }
88
+ .portal h2 { margin: 6px 0 6px; font-size: 26px; letter-spacing: -.02em; }
89
+ .portal p { margin: 0 0 14px; color: var(--ink2); font-size: 15px; }
90
+ .portal .go { font-family: var(--mono); font-size: 14px; color: var(--ink); }
91
+ .portal .go::after { content: " →"; color: var(--accent); }
92
+ .portal pre { font-size: 12.5px; background: var(--bg2); border: 1px solid var(--line); border-radius: 9px; padding: 9px 11px;
93
+ overflow-x: auto; color: var(--ink2); margin-bottom: 12px; }
94
+
95
+ /* ── sections ── */
96
+ section.block { padding: 72px 0; border-bottom: 1px solid var(--line); }
97
+ .kicker { font-family: var(--mono); font-size: 12px; letter-spacing: .16em; text-transform: uppercase; color: var(--accent); }
98
+ h2.h { font-size: clamp(28px, 4vw, 42px); letter-spacing: -.025em; line-height: 1.12; margin: 8px 0 12px; }
99
+ .sub { color: var(--ink2); max-width: 760px; font-size: 17px; margin: 0 0 28px; }
100
+ .grid3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
101
+ .grid2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; }
102
+ .grid4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }
103
+ .grid2 > *, .grid3 > *, .grid4 > *, .door > *, .play > *, .doc > * { min-width: 0; }
104
+ @media (max-width: 960px) { .grid3, .grid4 { grid-template-columns: 1fr 1fr; } }
105
+ @media (max-width: 620px) { .grid3, .grid2, .grid4 { grid-template-columns: 1fr; } }
106
+ .card { background: var(--panel); border: 1px solid var(--line); border-radius: var(--r); padding: 18px 18px 16px; }
107
+ .card h3 { margin: 4px 0 6px; font-size: 17px; letter-spacing: -.01em; }
108
+ .card p { margin: 0; color: var(--ink2); font-size: 15px; }
109
+ .card .n { font-family: var(--mono); font-size: 12px; color: var(--ink3); }
110
+ .card.rule h3::before { content: "◆ "; color: var(--accent); font-size: 12px; vertical-align: 2px; }
111
+
112
+ /* terminal */
113
+ .term { background: #05070b; color: #d7e2f0; border: 1px solid var(--line2); border-radius: var(--r); overflow: hidden;
114
+ box-shadow: var(--glow); }
115
+ :root[data-theme="light"] .term { background: #0d1321; }
116
+ .term .bar { display: flex; gap: 6px; align-items: center; padding: 10px 12px; border-bottom: 1px solid #1c2533; }
117
+ .term .bar i { width: 10px; height: 10px; border-radius: 50%; background: #2a3648; }
118
+ .term .bar span { margin-left: 8px; font: 12px var(--mono); color: #64748b; }
119
+ .term pre { padding: 16px 18px; font-size: 13.5px; line-height: 1.6; white-space: pre-wrap; word-break: break-word; min-height: 320px; }
120
+ .term .p { color: #7cf3ff; } .term .x { color: #ff6b7a; } .term .ok { color: #4ee08a; } .term .dim { color: #64748b; }
121
+ .term .caret { display: inline-block; width: 8px; height: 1.1em; background: #7cf3ff; vertical-align: -2px; animation: blink 1s steps(1) infinite; }
122
+ @keyframes blink { 50% { opacity: 0; } }
123
+ @media (prefers-reduced-motion: reduce) { .term .caret { animation: none; } }
124
+
125
+ /* code blocks with copy */
126
+ .code { position: relative; background: var(--bg2); border: 1px solid var(--line); border-radius: 11px; }
127
+ .code pre { padding: 13px 15px; overflow-x: auto; font-size: 13.5px; line-height: 1.55; color: var(--ink); }
128
+ .code .copy { position: absolute; top: 7px; right: 7px; font: 12px var(--mono); background: var(--panel); color: var(--ink2);
129
+ border: 1px solid var(--line2); border-radius: 7px; padding: 3px 8px; cursor: pointer; }
130
+ .code .copy:hover { color: var(--ink); border-color: var(--accent); }
131
+ .code .lbl { position: absolute; top: -9px; left: 12px; font: 11px var(--mono); background: var(--bg); color: var(--ink3);
132
+ padding: 0 6px; letter-spacing: .08em; text-transform: uppercase; }
133
+ .stack > * + * { margin-top: 14px; }
134
+
135
+ /* atlas frame */
136
+ .atlas-frame { height: 640px; border: 1px solid var(--line2); border-radius: var(--r); overflow: hidden; box-shadow: var(--glow); }
137
+ @media (max-width: 900px) { .atlas-frame { height: 82vh; } }
138
+ .atlas-frame .atlas { --hg-bg: var(--bg2); --hg-bg1: var(--panel); --hg-bg2: var(--panel2); --hg-panel: var(--panel);
139
+ --hg-ink: var(--ink); --hg-ink2: var(--ink2); --hg-ink3: var(--ink3); --hg-line: var(--line); --hg-line2: var(--line2);
140
+ --hg-accent: var(--accent); --hg-light-bg: var(--bg2); --hg-light-bg1: var(--panel); --hg-light-bg2: var(--panel2);
141
+ --hg-light-panel: var(--panel); --hg-light-ink: var(--ink); --hg-light-ink2: var(--ink2); --hg-light-ink3: var(--ink3);
142
+ --hg-light-line: var(--line); --hg-light-line2: var(--line2); --hg-light-accent: var(--accent); }
143
+ .note { font-size: 14px; color: var(--ink3); margin-top: 10px; }
144
+
145
+ /* buttons */
146
+ .btn { display: inline-flex; align-items: center; gap: 8px; font: 600 15px var(--sans); text-decoration: none; cursor: pointer;
147
+ padding: 10px 16px; border-radius: 10px; border: 1px solid var(--line2); color: var(--ink); background: var(--panel); }
148
+ .btn:hover { border-color: var(--accent); }
149
+ .btn.primary { background: var(--accent); color: #031016; border-color: transparent; }
150
+ :root[data-theme="light"] .btn.primary { color: #fff; }
151
+ @media (prefers-color-scheme: light) { :root:not([data-theme="dark"]) .btn.primary { color: #fff; } }
152
+ .btn:disabled { opacity: .5; cursor: default; }
153
+ .row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
154
+
155
+ /* page header for inner pages */
156
+ .phead { padding: 56px 0 28px; border-bottom: 1px solid var(--line); }
157
+ .phead h1 { font-size: clamp(32px, 5vw, 52px); letter-spacing: -.03em; line-height: 1.06; margin: 10px 0 10px; }
158
+ .phead p { color: var(--ink2); font-size: 18px; max-width: 780px; margin: 0; }
159
+ .doc { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: 40px; padding: 36px 0 80px; }
160
+ @media (max-width: 900px) { .doc { grid-template-columns: 1fr; gap: 0; } .toc { display: none; } }
161
+ .toc { position: sticky; top: 76px; align-self: start; font-size: 14px; }
162
+ .toc a { display: block; color: var(--ink2); text-decoration: none; padding: 4px 0 4px 10px; border-left: 2px solid var(--line); }
163
+ .toc a:hover { color: var(--ink); border-left-color: var(--accent); }
164
+ .prose h2 { font-size: 26px; letter-spacing: -.02em; margin: 44px 0 10px; scroll-margin-top: 80px; }
165
+ .prose h2:first-child { margin-top: 0; }
166
+ .prose h3 { font-size: 18px; margin: 26px 0 8px; scroll-margin-top: 80px; }
167
+ .prose p, .prose li { color: var(--ink); max-width: 76ch; }
168
+ .prose ul, .prose ol { padding-left: 22px; }
169
+ .prose table { border-collapse: collapse; width: 100%; font-size: 14px; display: block; overflow-x: auto; }
170
+ .prose th, .prose td { text-align: left; padding: 7px 10px; border-bottom: 1px solid var(--line); vertical-align: top; }
171
+ .prose th { font: 12px var(--mono); letter-spacing: .06em; text-transform: uppercase; color: var(--ink2); }
172
+ .prose blockquote { margin: 14px 0; padding: 10px 14px; border-left: 3px solid var(--accent); background: var(--panel); color: var(--ink2); }
173
+ .callout { border: 1px solid var(--line2); border-left: 3px solid var(--violet); background: var(--panel); border-radius: 10px;
174
+ padding: 14px 16px; margin: 18px 0; }
175
+ .callout b { color: var(--violet); }
176
+
177
+ /* verify */
178
+ .drop { border: 2px dashed var(--line2); border-radius: var(--r); padding: 40px 20px; text-align: center; background: var(--panel);
179
+ cursor: pointer; transition: border-color .15s; }
180
+ .drop.over, .drop:hover { border-color: var(--accent); }
181
+ .vres { margin-top: 18px; }
182
+ .vres .big { font-size: 22px; font-weight: 700; }
183
+ .vres .good { color: var(--green); } .vres .bad { color: var(--red); } .vres .warn { color: var(--amber); }
184
+ .kv { display: grid; grid-template-columns: max-content 1fr; gap: 4px 16px; font-size: 14px; margin-top: 10px; }
185
+ .kv dt { font-family: var(--mono); color: var(--ink3); } .kv dd { margin: 0; font-family: var(--mono); word-break: break-all; }
186
+
187
+ /* playground */
188
+ .play { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
189
+ @media (max-width: 900px) { .play { grid-template-columns: 1fr; } }
190
+ .field { display: flex; flex-direction: column; gap: 5px; margin-bottom: 12px; }
191
+ .field label { font: 12px var(--mono); letter-spacing: .06em; text-transform: uppercase; color: var(--ink2); }
192
+ .field textarea, .field input, .field select { font: 14px var(--sans); color: var(--ink); background: var(--bg2);
193
+ border: 1px solid var(--line2); border-radius: 9px; padding: 9px 11px; width: 100%; }
194
+ .field textarea.mono { font-family: var(--mono); font-size: 13px; }
195
+ .out { background: var(--bg2); border: 1px solid var(--line); border-radius: 11px; padding: 14px 16px; min-height: 120px;
196
+ font: 13.5px/1.55 var(--mono); white-space: pre-wrap; word-break: break-word; }
197
+ .out .x { color: var(--red); } .out .ok { color: var(--green); } .out .dim { color: var(--ink3); }
198
+ .chips { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
199
+ .chip { font: 13px var(--sans); background: var(--panel2); border: 1px solid var(--line2); color: var(--ink2); border-radius: 999px;
200
+ padding: 5px 11px; cursor: pointer; }
201
+ .chip:hover { color: var(--ink); border-color: var(--accent); }
202
+
203
+ /* footer */
204
+ footer { padding: 40px 0 56px; color: var(--ink3); font-size: 14px; }
205
+ footer .wrap { display: flex; gap: 24px; flex-wrap: wrap; justify-content: space-between; }
206
+ footer a { color: var(--ink2); }
207
+ footer .slogan { font-family: var(--mono); color: var(--ink2); }
@@ -0,0 +1,238 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>hypswarm — many agents, one record</title>
7
+ <meta name="description" content="hypswarm runs one agent or a swarm of them on a research or building task with a HypGraph record as the only shared state: the record schedules, accepts, stops and reports; models only do work and judge exceptions.">
8
+ <meta property="og:title" content="hypswarm — many agents, one record">
9
+ <meta property="og:description" content="Run one agent or a swarm of them on a task with a HypGraph record as the only shared state. The record schedules, accepts, stops and reports; models do work and judge exceptions.">
10
+ <meta property="og:type" content="website">
11
+ <meta property="og:url" content="https://hypswarm.com/">
12
+ <meta name="twitter:card" content="summary">
13
+ <link rel="icon" href="assets/hypswarm.svg" type="image/svg+xml">
14
+ <link rel="alternate" type="text/plain" href="llms.txt" title="For language models">
15
+ <link rel="stylesheet" href="assets/site.css">
16
+ <script>try{const t=localStorage.getItem('hg-theme');if(t)document.documentElement.dataset.theme=t}catch(e){}</script>
17
+ <style>
18
+ .seats td:first-child{white-space:nowrap}
19
+ .trace{font-family:var(--mono);font-size:13px;line-height:1.55}
20
+ .trace .k{color:var(--violet)} .trace .ok{color:var(--green)} .trace .dim{opacity:.6}
21
+ .alpha{display:inline-block;border:1px solid var(--line);border-radius:999px;padding:2px 10px;font-size:12px;letter-spacing:.04em;text-transform:uppercase;opacity:.8}
22
+ </style>
23
+ </head>
24
+ <body>
25
+ <a class="skip" href="#main">Skip to content</a>
26
+ <header class="nav"><div class="wrap">
27
+ <a class="brand" href="./"><img src="assets/hypswarm.svg" alt=""><span>hyp<b>swarm</b></span></a>
28
+ <nav aria-label="Site"><a href="#agents">Agents</a><a href="#engineers">Engineers</a><a href="#seats">Seats</a>
29
+ <a href="#status" class="hide-sm">Status</a>
30
+ <a href="https://hypgraph.com" class="hide-sm">HypGraph</a>
31
+ <a href="https://github.com/voodoomods/hypswarm" class="hide-sm">GitHub</a>
32
+ <button class="iconbtn" data-toggle-theme type="button" aria-label="Toggle light and dark">◐</button></nav>
33
+ </div></header>
34
+
35
+ <main id="main">
36
+ <section class="hero">
37
+ <div class="wrap">
38
+ <span class="eyebrow"><i></i> alpha · built on HypGraph · Python 3.11+</span>
39
+ <h1 class="title">Many agents.<span class="l2">One record.</span></h1>
40
+ <p class="lede">hypswarm runs one agent or a swarm of them on a research or building task, with a
41
+ <a href="https://hypgraph.com">HypGraph</a> record as the only shared state. The record schedules the work,
42
+ accepts it against predicates it checks itself, stops what a fallen premise made pointless, and writes the
43
+ report. Models are called to do work and to judge exceptions — nothing else.</p>
44
+
45
+ <div class="door" role="group" aria-label="Choose your way in">
46
+ <a class="portal agent" href="#agents">
47
+ <div class="who">For agents &amp; people</div>
48
+ <h2>Take a seat</h2>
49
+ <p>A seat is a name in the record. Hold it over MCP from Claude Code, Cursor or any client: the scheduler
50
+ issues you orders, the record tells you when each one is done, and it holds you to the same rules as
51
+ every other seat. Machine-readable: <code>/llms.txt</code>.</p>
52
+ <pre>hypgraph --db study.hypgraph --as nicolas mcp
53
+ # my_work → do it → return_work</pre>
54
+ <span class="go">How a seat works</span>
55
+ </a>
56
+ <a class="portal human" href="#engineers">
57
+ <div class="who">For engineers</div>
58
+ <h2>Run a swarm</h2>
59
+ <p>One task, a few seats, a budget. The scheduler makes no model calls; workers hold no state; the record
60
+ is the audit log and it verifies by hash. Any OpenAI-compatible endpoint or Anthropic as the model;
61
+ workers in one process or against a record server.</p>
62
+ <pre>pip install hypswarm
63
+ hypswarm run --task task.toml --seats seats.toml --record study.hypgraph</pre>
64
+ <span class="go">Set it up</span>
65
+ </a>
66
+ </div>
67
+ </div>
68
+ </section>
69
+
70
+ <section class="block">
71
+ <div class="wrap grid2" style="align-items:center">
72
+ <div>
73
+ <div class="kicker">The record is the orchestrator</div>
74
+ <h2 class="h">What a run looks like when nobody has to coordinate.</h2>
75
+ <p class="sub">Four questions about an eval, three workers, a critic, a lead. The scheduler issues an order per
76
+ open question to whichever seat fits, the workers write runs, results and claims into the record, the record
77
+ accepts each order the moment its predicates are met, a critic's review settles each question, and the lead is
78
+ called once: to write the interpretation under the facts. This trace is from a real run on a suite instance
79
+ (the harmony study's dry-run seed, not a study seed).</p>
80
+ <ul class="sub" style="padding-left:20px;margin-top:-10px">
81
+ <li>every order is a node; acceptance is a decision based on the evidence that met it</li>
82
+ <li>a worker's reply after each write says whether its order is done — so it returns</li>
83
+ <li>claims are checked as they're written; the report is linted against the record before it's accepted</li>
84
+ </ul>
85
+ </div>
86
+ <div class="term" aria-label="A scheduler trace from a real hypswarm run">
87
+ <div class="bar"><i></i><i></i><i></i><span>hypswarm run — F1 seed 0</span></div>
88
+ <pre class="trace"><span class="k">dispatch</span> T1 → analyst Q1 What is A's accuracy?
89
+ <span class="k">dispatch</span> T2 → stats Q3 Is A significantly better than B?
90
+ <span class="k">dispatch</span> T3 → engineer Q4 In which subset is A's advantage largest?
91
+ <span class="k">returned</span> T2 stats · 6 calls · returned itself
92
+ <span class="ok">settled </span> T2 → D1 claim_made: CL2
93
+ <span class="k">dispatch</span> T4 → critic review CL2
94
+ <span class="k">returned</span> T1 analyst · 8 calls
95
+ <span class="ok">settled </span> T1 → D2 claim_made: CL1
96
+ <span class="k">dispatch</span> T5 → stats Q2 What is B's accuracy?
97
+ <span class="k">returned</span> T4 critic · 6 calls
98
+ <span class="ok">settled </span> T4 → D3 reviewed: RV1
99
+ <span class="dim">… 8 orders, 0 reworks, 0 escalations, lead: 4 calls (the report)</span>
100
+ <span class="ok">BOARD </span> Q1 SETTLED · Q2 SETTLED · Q3 SETTLED · Q4 SETTLED — 4 of 4
101
+ <span class="ok">report </span> accepted (checked against the record)</pre>
102
+ </div>
103
+ </div>
104
+ </section>
105
+
106
+ <section class="block" id="seats">
107
+ <div class="wrap">
108
+ <div class="kicker">Seats, not personalities</div>
109
+ <h2 class="h">One program, from a solo scientist to a swarm.</h2>
110
+ <p class="sub">A seat is a declared capability bound to an author name in the record. Prompts stay short; the
111
+ work order carries the task. A solo scientist is one worker seat. A swarm is several, pulling in parallel
112
+ under the record's leases, which is what keeps two of them off the same work.</p>
113
+ <div class="grid4">
114
+ <div class="card rule"><h3>worker</h3><p>Takes orders from the board; writes runs, results and claims;
115
+ returns. Declares what it <code>takes</code> so the scheduler can match it to work.</p></div>
116
+ <div class="card rule"><h3>reviewer</h3><p>Takes review orders. Named as a reviewer on the investigation, so
117
+ its verdicts count — never on its own author's work; the record refuses that.</p></div>
118
+ <div class="card rule"><h3>lead</h3><p>Called only at exceptions — an order stuck after two reworks, a contested
119
+ claim, an empty frontier with questions open — and for the report's interpretation.</p></div>
120
+ <div class="card rule"><h3>instrument</h3><p>Not a model. A job runner (CI, a lab) that files runs the record
121
+ marks as lab-recorded, so "the tests pass" is its number, not the agent's.</p></div>
122
+ <div class="card rule"><h3>external</h3><p>No model: a person or another agent holds the name over MCP. The
123
+ scheduler issues it orders like any seat and waits. If the lease runs out, the record returns the order on
124
+ its behalf.</p></div>
125
+ <div class="card rule"><h3>operator</h3><p>A person, reached through the record: approves budgets, answers
126
+ escalations, resolves objections. Never through chat state.</p></div>
127
+ </div>
128
+ </div>
129
+ </section>
130
+
131
+ <section class="block">
132
+ <div class="wrap">
133
+ <div class="kicker">What the record does for the team</div>
134
+ <h2 class="h">Coordination that isn't a prompt.</h2>
135
+ <div class="grid4">
136
+ <div class="card"><div class="n">scheduler</div><h3>No model calls</h3><p>Issue from the question board, settle
137
+ met orders, rework the rest twice, cancel what became moot, bring the lead in only at exceptions. All of it
138
+ is code over the record's derived state.</p></div>
139
+ <div class="card"><div class="n">workers</div><h3>No state</h3><p>A worker's context is its order and its own
140
+ turns. It can be killed; the lease expires and another takes the order. Every reply says whether it's done.</p></div>
141
+ <div class="card"><div class="n">claims</div><h3>Can't be flattered</h3><p>HypGraph's checks run on every
142
+ write: numbers bound to results, no "never" without the count, no "significantly" without the test, and the
143
+ record binds the numbers it already holds before it refuses anything.</p></div>
144
+ <div class="card"><div class="n">budget</div><h3>A rule, not a hope</h3><p>Calls and dollars, per run and per
145
+ order, enforced by the scheduler and shown to every seat in every reply.</p></div>
146
+ <div class="card"><div class="n">audit</div><h3>You didn't write it</h3><p>Orders are task nodes, acceptance is
147
+ a decision, the run files its own provenance. The record <i>is</i> the log, and it verifies by hash.</p></div>
148
+ <div class="card"><div class="n">notices</div><h3>The world can interrupt</h3><p>A file declared corrupt
149
+ withdraws its artifact, registers the fix, and reaches every order issued from then on. Orders resting on the
150
+ fallen premise are cancelled, and nothing else is.</p></div>
151
+ </div>
152
+ </div>
153
+ </section>
154
+
155
+ <section class="block" id="agents">
156
+ <div class="wrap grid2" style="align-items:start">
157
+ <div>
158
+ <div class="kicker">For agents &amp; people</div>
159
+ <h2 class="h">Hold a seat over MCP.</h2>
160
+ <p class="sub">The HypGraph MCP server is the whole interface. <code>my_work</code> shows your open orders —
161
+ objective, target, premises with their standing, what's already been tried, each predicate with how to meet
162
+ it. You register runs, record results, make claims; every reply tells you whether the order is done; you
163
+ return it. The record can't tell a person from an agent except by name.</p>
164
+ <div class="callout"><b>If you are an agent reading this.</b> Call <code>my_work</code>. Do what the order
165
+ says, from the files, with the tools you have. Write what you found as runs, results and claims — a claim's
166
+ numbers must come from a result, and a refusal tells you the honest version. When the reply says every
167
+ predicate is met, call <code>return_work</code> with a note of at most 120 words. Don't work past done.</div>
168
+ </div>
169
+ <div class="stack">
170
+ <div class="code"><span class="lbl">seats.toml</span><pre>[[seats]]
171
+ name = "nicolas"
172
+ role = "worker"
173
+ external = true</pre></div>
174
+ <div class="code"><span class="lbl">your side</span><pre>pip install "hypgraph[mcp]"
175
+ claude mcp add hypgraph -- hypgraph --db study.hypgraph --as nicolas mcp
176
+ # then, in the session: my_work</pre></div>
177
+ </div>
178
+ </div>
179
+ </section>
180
+
181
+ <section class="block" id="engineers">
182
+ <div class="wrap grid2" style="align-items:start">
183
+ <div>
184
+ <div class="kicker">For engineers</div>
185
+ <h2 class="h">A task, some seats, a budget.</h2>
186
+ <p class="sub">The core depends on <code>hypgraph</code> and <code>httpx</code>. The OpenAI-compatible adapter
187
+ covers DeepInfra, OpenAI, NVIDIA NIM, vLLM, Ollama and most gateways; <code>hypswarm[anthropic]</code> adds
188
+ the Messages API. Any object with <code>async complete(messages, tools) -&gt; Reply</code> is a model.</p>
189
+ <p class="sub">Workers can share one process or talk to a record served by <code>hypgraph serve --writable</code>
190
+ — one record server, stateless workers on other processes or machines, and the file still verifies.</p>
191
+ <div class="row"><a class="btn primary" href="https://github.com/voodoomods/hypswarm">Source &amp; README</a>
192
+ <a class="btn" href="https://github.com/voodoomods/hypswarm/blob/main/docs/DESIGN.md">The design</a></div>
193
+ </div>
194
+ <div class="stack">
195
+ <div class="code"><span class="lbl">python</span><pre>from hypswarm import Task, Seat, Budget, run
196
+ from hypswarm.providers import OpenAICompatible
197
+
198
+ task = Task(title="Does A beat B",
199
+ mission="Two models were scored on the same items (items.csv). Find out whether A beats B.",
200
+ questions=[("Q1", "What is A's accuracy?"), ("Q2", "Is A significantly better than B?")],
201
+ files={"items.csv": open("items.csv", "rb").read()})
202
+ seats = [Seat("analyst", "worker", takes=("accuracy", "counts")),
203
+ Seat("stats", "worker", takes=("significant", "test")),
204
+ Seat("critic", "reviewer"), Seat("lead", "lead")]
205
+ model = OpenAICompatible("deepseek-ai/DeepSeek-V4.1-Flash", base_url="https://api.deepinfra.com/v1/openai")
206
+ result = asyncio.run(run(task, seats, model, record="study.hypgraph", budget=Budget(max_calls=150)))
207
+ print(result.report)</pre></div>
208
+ <div class="code"><span class="lbl">record server</span><pre>hypgraph --db study.hypgraph serve --writable --no-browser
209
+ hypswarm run --task task.toml --seats seats.toml --record-url http://127.0.0.1:8765</pre></div>
210
+ </div>
211
+ </div>
212
+ </section>
213
+
214
+ <section class="block" id="status">
215
+ <div class="wrap">
216
+ <div class="kicker">Status</div>
217
+ <h2 class="h">Alpha, and being measured before it's described.</h2>
218
+ <p class="sub"><span class="alpha">alpha 0.1</span>&nbsp; hypswarm grew out of the harness the HypGraph harmony
219
+ study runs agent teams on, and its first measured use is as a condition in that study, preregistered before it
220
+ runs. Until that study reports, this page describes what hypswarm does and not what it saves. What's built:
221
+ the scheduler, workers, external seats over MCP, the record server mode, the OpenAI-compatible and Anthropic
222
+ adapters, budgets, notices, and a test suite that runs every scheduler path on a scripted model in seconds.
223
+ Next: the building adapter, with CI as the instrument.</p>
224
+ </div>
225
+ </section>
226
+ </main>
227
+
228
+ <footer class="foot"><div class="wrap">
229
+ <span>hypswarm is built on <a href="https://hypgraph.com">HypGraph</a>. Apache-2.0.</span>
230
+ <span>Made by Nicolas Houghtaling at <a href="https://github.com/voodoomods">VoodooMods LLC</a>.</span>
231
+ </div></footer>
232
+ <script>
233
+ document.querySelector('[data-toggle-theme]')?.addEventListener('click',()=>{
234
+ const d=document.documentElement,cur=d.dataset.theme||(matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light');
235
+ d.dataset.theme=cur==='dark'?'light':'dark';try{localStorage.setItem('hg-theme',d.dataset.theme)}catch(e){}});
236
+ </script>
237
+ </body>
238
+ </html>
@@ -0,0 +1,26 @@
1
+ # hypswarm
2
+
3
+ > Run one agent or a swarm of them on a research or building task with a HypGraph record (https://hypgraph.com) as the only shared state. The record schedules the work (orders from its question board), accepts it (predicates the record checks), stops what a fallen premise made pointless, and writes the report. Models are called to do work and to judge exceptions, nothing else. Alpha; measured as a preregistered condition in the HypGraph harmony study before any claim about it is made.
4
+
5
+ ## If you are an agent holding a seat
6
+
7
+ A seat is an author name in the record. You hold it through the HypGraph MCP server:
8
+
9
+ hypgraph --db study.hypgraph --as <your-seat-name> mcp
10
+
11
+ - `my_work` lists your open orders: objective, target, its premises with their standing, what has already been tried, each done-when predicate with how to meet it, the budget, the lease.
12
+ - Do the work from the files with the tools you have. Write what you find into the record: `register_run` (a computation and its result values), `add` (a claim with its numbers bound to a result; `answers` the question or `supports` / `challenges` the hypothesis), `review` (if you are a reviewer; never your own author's work).
13
+ - Every reply tells you whether your order is done. When it says every predicate is met, call `return_work` with a note of at most 120 words. Do not work past done.
14
+ - A refused claim says exactly what to fix and gives the honest sentence. Write that.
15
+ - An order you returned is no longer yours; if it comes back, it is a new order with what was missing.
16
+
17
+ ## If you are an engineer
18
+
19
+ pip install hypswarm # core: hypgraph + httpx
20
+ pip install "hypswarm[anthropic]" # + the Anthropic adapter
21
+ hypswarm run --task task.toml --seats seats.toml --record study.hypgraph
22
+ hypswarm run ... --record-url http://127.0.0.1:8765 # against `hypgraph serve --writable`
23
+
24
+ Seats: worker (takes orders), reviewer (verdicts count), lead (exceptions and the report), instrument (a job runner filing lab-recorded runs), external (a person or agent over MCP), operator (a person, through the record). Python API: `run(task, seats, models, record=..., budget=Budget(max_calls, max_usd))`.
25
+
26
+ Source and design: https://github.com/voodoomods/hypswarm (docs/DESIGN.md). Apache-2.0. Made by Nicolas Houghtaling at VoodooMods LLC.
@@ -0,0 +1,3 @@
1
+ User-agent: *
2
+ Allow: /
3
+ Sitemap: https://hypswarm.com/sitemap.xml
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
3
+ <url><loc>https://hypswarm.com/</loc></url>
4
+ <url><loc>https://hypswarm.com/llms.txt</loc></url>
5
+ </urlset>
@@ -0,0 +1,12 @@
1
+ """
2
+ hypswarm — run one agent or a swarm of them on a task, with a HypGraph record as the only shared state.
3
+
4
+ This release only reserves the name. The alpha lives at https://github.com/voodoomods/hypswarm and installs from
5
+ there until HypGraph's coordination layer is on PyPI:
6
+
7
+ pip install "hypgraph @ git+https://github.com/voodoomods/hypgraph@harmony-study"
8
+ pip install git+https://github.com/voodoomods/hypswarm
9
+ """
10
+
11
+ __version__ = "0.0.1"
12
+ __all__ = ["__version__"]
@@ -0,0 +1,21 @@
1
+ """The placeholder's command line: says where the real thing is."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import sys
6
+
7
+ from . import __doc__ as _about
8
+ from . import __version__
9
+
10
+
11
+ def main(argv: list[str] | None = None) -> int:
12
+ args = sys.argv[1:] if argv is None else argv
13
+ if args and args[0] in ("--version", "-V"):
14
+ print(f"hypswarm {__version__} (name reservation; the alpha is at https://github.com/voodoomods/hypswarm)")
15
+ return 0
16
+ print((_about or "").strip())
17
+ return 0
18
+
19
+
20
+ if __name__ == "__main__":
21
+ sys.exit(main())