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.
- hypswarm-0.0.1/.github/workflows/ci.yml +31 -0
- hypswarm-0.0.1/.github/workflows/pages.yml +33 -0
- hypswarm-0.0.1/.github/workflows/release.yml +41 -0
- hypswarm-0.0.1/.gitignore +13 -0
- hypswarm-0.0.1/LICENSE +201 -0
- hypswarm-0.0.1/PKG-INFO +41 -0
- hypswarm-0.0.1/README.md +21 -0
- hypswarm-0.0.1/docs/DESIGN.md +193 -0
- hypswarm-0.0.1/pyproject.toml +34 -0
- hypswarm-0.0.1/site/404.html +14 -0
- hypswarm-0.0.1/site/CNAME +1 -0
- hypswarm-0.0.1/site/assets/hypswarm.svg +16 -0
- hypswarm-0.0.1/site/assets/site.css +207 -0
- hypswarm-0.0.1/site/index.html +238 -0
- hypswarm-0.0.1/site/llms.txt +26 -0
- hypswarm-0.0.1/site/robots.txt +3 -0
- hypswarm-0.0.1/site/sitemap.xml +5 -0
- hypswarm-0.0.1/src/hypswarm/__init__.py +12 -0
- hypswarm-0.0.1/src/hypswarm/cli.py +21 -0
|
@@ -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
|
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.
|
hypswarm-0.0.1/PKG-INFO
ADDED
|
@@ -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.
|
hypswarm-0.0.1/README.md
ADDED
|
@@ -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 & 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 & 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) -> 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 & 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> 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,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())
|