|
| 1 | +<div align="center"> |
| 2 | + |
1 | 3 | # meclaw |
2 | 4 |
|
3 | | -[](https://github.com/mmeyerlein/meclaw/actions/workflows/ci.yml) [](https://github.com/mmeyerlein/meclaw/releases) [](#license) |
| 5 | +_Where agents build agents._ |
| 6 | + |
| 7 | +<p align="center"> |
| 8 | + <a href="https://github.com/mmeyerlein/meclaw/actions/workflows/ci.yml"><img src="https://github.com/mmeyerlein/meclaw/actions/workflows/ci.yml/badge.svg" alt="ci"></a> |
| 9 | + <a href="https://github.com/mmeyerlein/meclaw/releases"><img src="https://img.shields.io/github/v/release/mmeyerlein/meclaw" alt="release"></a> |
| 10 | + <a href="#license"><img src="https://img.shields.io/badge/license-MIT%2FApache--2.0-blue" alt="license"></a> |
| 11 | +</p> |
4 | 12 |
|
5 | | -[Docs](docs/README.md) · [Glossary](docs/glossary.md) · [Templates](templates/README.md) · [Examples](examples/README.md) · [Roadmap](ROADMAP.md) · [Contributing](CONTRIBUTING.md) |
| 13 | +</div> |
6 | 14 |
|
7 | | -One Linux binary that runs a tree of agents. Every folder in the tree is an entity: one actor, one |
| 15 | +One Linux binary that runs a tree of agents. Every folder in the tree is a cell: one actor, one |
8 | 16 | `config.json`, one SQLite file, one kernel sandbox (Landlock, network namespace, cgroup v2, |
9 | | -seccomp). Edges between folders are the routes a message may take. The binary ships no agent loop; a |
10 | | -loop is an edge that routes back into an `llm` entity. To change a running system you POST a diff to |
11 | | -one endpoint: validated, applied without a restart, written to a ledger. Agents change the system |
12 | | -through the same endpoint. **meclaw-os** and an **assistant** are grown onto that tree at runtime |
13 | | -from JSON, not deployed. |
| 17 | +seccomp). Edges between folders are the routes a message may take. The binary ships no agent loop; |
| 18 | +a loop is an edge that routes back into an `llm` cell. To change a running system you POST a diff |
| 19 | +to one endpoint: validated, applied without a restart, written to a ledger. Agents change the |
| 20 | +system through the same endpoint. **meclaw-os** and an **assistant** are grown onto that tree at |
| 21 | +runtime from JSON, not deployed. |
| 22 | + |
| 23 | +I built meclaw because I wanted to build agents with agents, and every tool I tried was either a |
| 24 | +pile of Python or a cage; nineteen versions later, this is what was left. |
| 25 | + |
| 26 | +Forty templates ship as JSON declarations and Python scripts, and `templates/` holds no Rust at |
| 27 | +all. Out of them you grow an assistant with sessions of its own, a memory that outlives the context |
| 28 | +window, a display with its own origin and a phone line, into a running colony, without stopping |
| 29 | +it. A colony is what one running tree of cells is called here. |
14 | 30 |
|
15 | | -You can rewire an assistant while it is still answering: the change is a diff of nodes and edges, |
16 | | -and nothing restarts. An agent that wants to change the tree goes through the same endpoint. The |
17 | | -shipped `builder` template drafts such a diff and holds no edge to that endpoint; `submit` is the |
18 | | -one node that does. 40 templates ship as JSON declarations and Python scripts, and `templates/` |
19 | | -contains no Rust. The docs call an entity a cell and the whole tree a colony. |
| 31 | + |
20 | 32 |
|
21 | | -## Start an assistant |
| 33 | +## Get started |
| 34 | + |
| 35 | +Four steps, and the colony in the picture is answering you: install the binary, start an empty |
| 36 | +colony, grow the OS into it while it runs, ask it something. |
22 | 37 |
|
23 | 38 | ```bash |
24 | 39 | # 1 — install meclaw: one static Linux binary (lands in ~/.local/bin) |
25 | 40 | curl -fsSL https://meclaw.ai/install.sh | sh |
26 | 41 | export PATH="$HOME/.local/bin:$PATH" |
| 42 | + |
| 43 | +# 2 — start an empty colony |
27 | 44 | # the templates must match the binary: clone the tag the installer just gave you |
28 | 45 | git clone --depth 1 --branch "v$(meclaw --version | cut -d' ' -f2)" \ |
29 | 46 | https://github.com/mmeyerlein/meclaw && cd meclaw |
30 | | -# one key — replace sk-... with a real one (https://openrouter.ai/keys), or step 3 ends in code=auth |
31 | | -printf 'OPENROUTER_API_KEY=sk-...\nMODEL_BRAIN=openai/gpt-4o-mini\n' > examples/meclaw-os/seed/.env |
| 47 | +# one key — replace sk-... with a real one (https://openrouter.ai/keys), or step 4 ends in code=auth |
| 48 | +printf 'OPENROUTER_API_KEY=sk-...\nMODEL_BRAIN=openai/gpt-5.6-luna\n' > examples/meclaw-os/seed/.env |
32 | 49 | # 7777 is an arbitrary free port: if it is taken, change it in every line below as well. |
33 | 50 | # The very first start reads a 25 MB binary from cold disk and can stay silent for ~40 s; every later start takes well under a second. |
34 | 51 | meclaw --root examples/meclaw-os/seed --templates ./templates --daemon --api 127.0.0.1:7777 |
35 | 52 |
|
36 | | -# 2 — install the OS into the running colony: one POST, nothing restarts |
| 53 | +# 3 — grow the OS into the running colony: one POST, nothing restarts |
37 | 54 | curl -s -X POST 127.0.0.1:7777/colony/mutations \ |
38 | 55 | -H 'Content-Type: application/json' -d @examples/meclaw-os/grow.json |
39 | 56 |
|
40 | | -# 3 — talk to your assistant |
41 | | -curl -s -X POST 127.0.0.1:7777/messages -H 'Content-Type: application/json' \ |
42 | | - -d '{"target": "/door", "headers": {"channel": "chat-1"}, |
43 | | - "body": {"messages": [{"origin": "user", "type": "text", |
44 | | - "text": "Say hello in one short sentence."}]}}' |
45 | | - |
46 | | -# 4 — read the answer: nothing is hidden, the reply is a hop on the record (needs jq) |
47 | | -curl -s '127.0.0.1:7777/colony/trace?limit=200' | jq -r \ |
48 | | - '[.trace[] | select((.headers_json | fromjson | .hop.route) as $r | $r == "answer" or $r == "error")] |
49 | | - | last | if . == null then "no answer yet — the colony is still working; watch it at http://127.0.0.1:7777/ui/" |
50 | | - else .body_payload | fromjson | .messages[0].text end' |
51 | | - |
52 | | -# 5 — watch the colony in the browser: http://127.0.0.1:7777/ui/ |
| 57 | +# 4 — talk to your assistant |
| 58 | +meclaw ask --api 127.0.0.1:7777 --target /door "Say hello in one short sentence." |
53 | 59 | ``` |
54 | 60 |
|
55 | | -`--daemon` runs in the foreground and stops on Ctrl-C, so step 1 keeps its terminal. Run steps 2 to |
56 | | -5 in a second shell. |
| 61 | +`--daemon` runs in the foreground and stops on Ctrl-C, so step 2 keeps its terminal. Run steps 3 |
| 62 | +and 4 in a second shell. The browser view is at `http://127.0.0.1:7777/ui/` while the daemon runs. |
| 63 | + |
| 64 | +## What just happened |
| 65 | + |
| 66 | +Step 1 put one binary on your machine and nothing else. No runtime to install beside it, and no |
| 67 | +database to point it at. |
| 68 | + |
| 69 | +Step 2 booted a colony out of a seed of two files, with no cell in it but the empty root hive. |
| 70 | +Step 3 grew seventeen cells into that colony while it ran, from one JSON file naming four |
| 71 | +templates and four edges, and nothing restarted. `POST /colony/mutations` is also the endpoint |
| 72 | +an agent goes through when it wants to change the tree, which is the whole of what "grown at |
| 73 | +runtime" means here. |
| 74 | + |
| 75 | +Step 4 posted a turn to `/door` and read the answer back. The answer is a hop on the colony's |
| 76 | +own record, so `meclaw ask` reads it out of `GET /colony/trace`, where every other hop of that |
| 77 | +turn is waiting too. The page in the picture is that same record with a nav bar on it. |
| 78 | + |
| 79 | +## Why it is built this way |
| 80 | + |
| 81 | +- meclaw ships no agent loop, because a loop is an edge that routes an answer back into the cell that asked ([the store-backed tool loop](docs/store-backed-tool-loop.md)). |
| 82 | +- The harness lives in the filesystem, so `ls`, `grep`, `diff` and `git` are the tooling and every change to a topology is a diff ([everything is a file](docs/why/everything-is-a-file.md)). |
| 83 | +- meclaw-os ships the organisation, its people, their assistants and their channels as templates under one rule: a level owns what its siblings must share ([an operating system for agents](docs/why/an-os-for-agents.md)). |
| 84 | +- The shipped assistant runs two models, a conversation surface that answers fast and a reasoning core that thinks ([one assistant, two brains](docs/why/two-brains.md)). |
| 85 | +- A conversation can run for weeks because the window was never where the conversation was stored ([memory that outlives the window](docs/why/memory.md)). |
| 86 | +- The builder drafts against a typed catalogue, the template library and its declarations, and `add_templates` teaches a running colony a class it did not have ([ontology](docs/why/ontology.md)). |
| 87 | +- The primitives for self-improvement are here and tested, and no loop closes them unattended ([prepared for self-improvement](docs/why/rsi.md)). |
| 88 | +- You talk to the assistant and it shows you, on a display that belongs to you and not to one of the agents ([you talk, it shows](docs/why/you-talk-it-shows.md)). |
| 89 | +- The security model is the kernel itself, which is what one static Linux binary buys and what a macOS build could not ([why Rust, why Linux only](docs/why/rust-and-linux.md)). |
| 90 | +- argus, affinity, talky and cogny are role names, and each one carries its reason in a line ([names of the shipped roles](docs/glossary.md#names-of-the-shipped-roles)). |
| 91 | + |
| 92 | +## Where it sits among other systems |
| 93 | + |
| 94 | +| System | What meclaw shares | What meclaw does differently | |
| 95 | +|---|---|---| |
| 96 | +| Erlang/OTP | actors, mailbox, supervisor | the topology is a file rather than code; specialised for LLM work | |
| 97 | +| LangGraph | a graph for LLM agent flows | language-agnostic, file-based, persistent | |
| 98 | +| Temporal | durable execution, message log | lightweight, decentralised, a filesystem DSL | |
| 99 | + |
| 100 | +The [system overview](docs/meclaw-overview.md) carries the same table with three more rows: NATS, |
| 101 | +Node-RED, and BPMN with Serverless Workflow. |
| 102 | + |
| 103 | +## Quick links |
| 104 | + |
| 105 | +- [Read the whole system once](docs/meclaw-overview.md): cells, edges, headers, routing, mutations and the lifecycle, in the one document that wins on conflict. |
| 106 | +- [Glossary](docs/glossary.md): the sixteen words the other documents assume. |
| 107 | +- [Find out what each cell type does](docs/cell-types.md) |
| 108 | +- [Write a `config.json` by hand](docs/config.md) |
| 109 | +- [Change a colony while it runs](docs/rewiring.md): the procedure, and the traps that catch everyone once. |
| 110 | +- [Know what is under contract and what is not](docs/stability.md) |
| 111 | +- [Pick a template to start from](templates/README.md): forty of them, each with a README of its own. |
| 112 | +- [Watch a colony refuse an attack](examples/hard-shell/WALKTHROUGH.md): every command in it was recorded from a real terminal. |
| 113 | +- [Measure what a colony costs to run](docs/costs.md) |
| 114 | +- [Find the document that answers your question](docs/README.md): one line per document, and what you can do once you have read it. |
| 115 | +- [Read a whole colony end to end](examples/README.md): from a two-cell one to a four-level stack grown from an empty seed. |
| 116 | +- [Send a patch](CONTRIBUTING.md), [see what is planned](ROADMAP.md), [read what changed in each release](CHANGELOG.md) |
57 | 117 |
|
58 | 118 | ## Where it stands |
59 | 119 |
|
60 | 120 | Linux x86_64 only. The release is a static musl build, and the installer refuses any other platform. |
61 | | -A `code` cell runs `python3` and no other runner. The binary has no SDK and no plugin API. HTTP and |
62 | | -files are the interface. The daemon installs no authentication and no TLS. Put a reverse proxy in |
63 | | -front of it, like any Linux daemon. meclaw is under heavy development, and I would not leave it |
64 | | -unattended in production. The 0.32.0 release gate ran 6875 tests. One measured colony spent 0.32 EUR |
65 | | -on a day of conversation ([docs/costs.md](docs/costs.md)). |
| 121 | +A `code` cell runs `python3` and no other runner. The daemon installs no authentication and no |
| 122 | +TLS; put a reverse proxy in front of it, like any Linux daemon. HTTP and files are the whole |
| 123 | +interface, and there is no SDK to import. meclaw is under heavy development, and I would not |
| 124 | +leave it unattended in production. The 0.33.0 release gate ran 6953 tests. One measured colony |
| 125 | +spent 0.32 EUR on a day of conversation ([docs/costs.md](docs/costs.md)). |
66 | 126 |
|
67 | 127 | ## Stability |
68 | 128 |
|
69 | 129 | Five surfaces are the public contract of this project: the HTTP API, the template DSL, the template |
70 | | -ports, the `web` cell's own origin, and the documented `error_code` strings. The API means the |
71 | | -`/colony/*` routes and `POST /messages`. The DSL means the `template.json` and `config.json` |
72 | | -schemas, including the mutation diff format. The ports are the ingress and exit endpoints a |
73 | | -template's README declares. The `web` origin is the `page.set` route grammar and its two reserved |
74 | | -names; the `error_code` strings are the documented dead-letter, cell-type and `/colony` read codes. |
75 | | -While meclaw is on `0.x`, changes to those five are additive. A change that breaks an existing |
76 | | -topology gets its own Breaking section in [CHANGELOG.md](CHANGELOG.md). Nothing under `crates/` |
77 | | -carries a SemVer guarantee. |
78 | | - |
79 | | -## Docs |
80 | | - |
81 | | -| If you want to | Read | |
82 | | -|---|---| |
83 | | -| read the whole system once | [system overview](docs/meclaw-overview.md) | |
84 | | -| know what a cell type does | [cell types](docs/cell-types.md) | |
85 | | -| write a `config.json` | [config format](docs/config.md) | |
86 | | -| change a colony while it runs | [rewiring](docs/rewiring.md) | |
87 | | -| pick a template | [template catalogue](templates/README.md) | |
88 | | -| read a measured transcript | [hard-shell walkthrough](examples/hard-shell/WALKTHROUGH.md) | |
89 | | -| know why it is built this way | [docs/why/](docs/why/) | |
| 130 | +ports, the `web` cell's own origin, and the documented `error_code` strings. On `0.x` those five |
| 131 | +change additively, and a change that breaks an existing topology gets its own Breaking section in |
| 132 | +[CHANGELOG.md](CHANGELOG.md); what each surface covers is written out in |
| 133 | +[stability](docs/stability.md). |
90 | 134 |
|
91 | 135 | ## License |
92 | 136 |
|
|
0 commit comments