Repository navigation
humd: a peer's attendant serves a bloom here, when this humd trusts it - #96
Merged
Merged
Conversation
WIRE.md said a reach goes to an attendant "here or on a peer", but humd
handed a bloom only its own attendants' tools and never sent a reach to
a peer's. Now it does, behind a trust gate of its own.
- A bloom is handed, each name once: `bash`, this humd's attendants',
the forager's own, then those of attendants on live peers, when this
humd trusts remote attendants and knows the peer bee's hive.
- A reach goes to an attendant here, then back to the forager when it
offered the name, then to the peer whose attendant serves it, by the
route `bash` already takes to a builder elsewhere, now `reach_peer`.
- `humd.trustRemoteAttendants` / `HUM_TRUST_REMOTE_ATTENDANTS`, off by
default as remote nurses are: the peer sees each reach's input, and
its tool descriptions reach every model here.
- `from` now means a peer sent it: a peer's reach with no origin is
dropped, since nothing could answer it, and a local reach loses any
`from`, so an attendant can refuse a peer's blooms.
- sim: `Trust { nurses, attendants }`, and `peer_attendants` for the
trusted, untrusted and never-taught cases.
adiled
added a commit
that referenced
this pull request
Oct 25, 2026
A reach from a peer humd carries the peer's `from` (#96), and web2 refuses it unless web2.json says `servePeers: true`: what web2 is signed in to is this machine's, lent to a peer's blooms only when a person says so. With the peer's humd trusting remote attendants, that is the two opt-ins a peer's bloom needs.
adiled
added a commit
that referenced
this pull request
Oct 25, 2026
A reach from a peer humd carries the peer's `from` (#96), and web2 refuses it unless web2.json says `servePeers: true`: what web2 is signed in to is this machine's, lent to a peer's blooms only when a person says so. With the peer's humd trusting remote attendants, that is the two opt-ins a peer's bloom needs.
adiled
added a commit
that referenced
this pull request
Oct 25, 2026
web2 is an attendant serving one fixed tool, `wrepl`. A reach carries one command line, and every OpenAPI spec and MCP server web2.json names answers it as if it were a CLI. The thrum sees a tendril like any other: OpenAPI, MCP and OAuth stop at this hive, and a harness that takes tools only over MCP gets `wrepl` as one tool among `bash` and the forager's own.
```
help
github help pulls
github pulls/list rust-lang rust --state open --jq '.[].title'
sentry search-issues --query 'is:unresolved'
```
**wrepl**
- `help` lists the services, `<service> help [group | words]` a service's commands, and `<service> <command> --help` a command's flags.
- Flags come from each command's input schema, typed by it: `--name value`, `--name=value`, `--flag` / `--no-flag`, a flag repeated for an array. Words with no flag fill the required inputs in order. Spelling is forgiven across kebab, snake and camel case.
- `--json '{…}'` gives the whole input, flags laid over it winning; `--jq '<filter>'` narrows a JSON result (jaq).
- A mistake answers with what would have worked: did-you-mean for services, commands and flags, the missing required flags, the type a value should be.
- An answer past `maxOutput` (32 KiB) keeps its start and its end, as `bash` does.
**Services**
- OpenAPI 3 from a URL or a file beside web2.json, JSON or YAML: each operation a command named by its `operationId`, grouped by its first tag, its parameters and JSON body fields as flags, local `$ref`s followed. The commands made from a spec are kept for a day, or until `web2 refresh`.
- MCP over stdio or streamable HTTP, through rmcp 3.7: one connection per server, opened at first use, closed when idle, opened again when it drops, relisted when the server says its tools changed.
- An `mcpServers` block pasted from any harness works as it is. `web2 import` copies in the servers Claude Code, Claude Desktop, Cursor, VS Code and Codex already know here.
- web2.json is read again whenever it changes; a service added there is reached on the next call.
**Reading and writing**
- A service only reads until web2.json says otherwise: `writes`, `allow` (write commands by name or glob, `read-*`), `deny`.
- An OpenAPI operation reads when its method is GET, HEAD or OPTIONS. An MCP tool reads only when its annotations say `readOnlyHint: true`, as the MCP spec has it.
- A refused call answers with the key that would turn it on, and a service's help counts what is off.
- `web2 allow`, `web2 deny` and `web2 review` (each command that is off, turned on or left, one by one) edit web2.json in place, keeping its order, and refuse a change that would break it.
**Signing in**
- Tokens live in `secrets/credentials.json` in web2's state directory, mode 0600 in a 0700 directory, never in an environment, a log or an answer. `"env": "VAR"` reads one from web2's environment instead.
- `web2 login <service>`: a token at a prompt that does not show it, or `--token-stdin`; an OpenAPI `oauth` app through the authorization code flow with PKCE and a callback on 127.0.0.1, renewed before it expires; an MCP server's own OAuth, by its discovery and client registration, through rmcp.
- A spec that names a scheme, with nothing stored, is called without credentials, so anonymous reads still answer; a 401 or 403 says how to sign in.
**Not offered**
- No sampling, elicitation or roots. A tool that asks for input mid-call (`input_required`), or turns into a task, answers that wrepl does not follow it.
- Legacy SSE MCP servers and Swagger 2.0 are refused with what to do instead.
**The hive**
- Its own workspace, depending on thrum-core, hum-thrum and hum-paths only; humd is a dev-dependency, for the bee test.
- Orchfile, `build` and `install` as the bash hive has them. Nothing goes on the PATH; the install prints where `web2` is. `web2` alone is the same REPL a bloom reaches, for a person at this machine.
- One row in the hives catalogue.
**Peers**
- A peer's bloom reaches web2 only when both sides say so: the peer's humd trusts remote attendants (#96), and this web2.json says `servePeers: true`. Otherwise a peer's reach, which carries its `from`, is refused, saying so: what web2 is signed in to is this machine's.
**Known limit, with its own change to follow**
- The tokens are as safe as the user web2 runs as, and `bash` on a builder runs as that user. They sit in `secrets/` so the builder (soon `shell`) can keep its shells out of hum's secrets, bee keys included.
**Verified**
- `cargo test`: 37 unit, 6 end to end against the real binary (an OpenAPI mock, an MCP server over stdio, one over HTTP with a bearer), 1 through a real humd: forager → humd → a nurse reaching `wrepl` → humd → `web2 serve` → an MCP server, and back, a config change mid-run included.
- An OpenAPI OAuth sign-in and renewal against a mock token endpoint, the PKCE verifier checked against its challenge.
- An MCP server's OAuth end to end against an authorization server shaped as the spec has it (protected resource and server metadata, client registration, PKCE, the issuer), then a call with the stored token.
- `web2 allow` / `deny` / `review` against a real config, globs included.
- `cargo clippy --all-targets -D warnings`, `./build` (release, `--locked`), tools/speech.py.
- Live: the Swagger Petstore (a relative server URL), GitHub's REST spec (1,242 commands; an anonymous `repos/get` in under a second), DeepWiki's MCP over HTTP.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
humd: a peer's attendant serves a bloom here, when this humd trusts it
WIRE.md already said a reach goes "to an attendant serving it here or on a peer", but humd handed a bloom only its own attendants' tools and never sent a reach to a peer's. Now it does, behind a trust gate of its own, the way remote nurses are.
What a bloom is handed
bashwhen the bloom builds, this humd's attendants', the forager's own, then the tools of attendants on live peers.Where a reach goes
bashto the builder where the bloom builds; any other name to an attendant here, then back to the forager when it offered the name, then to the peer whose attendant serves it.bashalready takes to a builder elsewhere, now shared (reach_peer); the result comes back the way it does forbash.Trust, off by default
humd.trustRemoteAttendantsin hum.json, orHUM_TRUST_REMOTE_ATTENDANTS, mirroringtrustRemoteNurses: the peer sees each reach's input, and its tool descriptions reach every model here.fromnow means a peer sent it: a reach from the ensemble with no origin is dropped, since nothing could answer it, and a local reach loses anyfrombefore it reaches an attendant. An attendant can then serve its own humd's blooms and refuse a peer's, which web2 does unless its config saysservePeers.sim
Trust { nurses, attendants }andspawn_humd_trusting;spawn_humd_not_trusting_remote_attendantsbeside the nurses' one.peer_attendants: a peer's tool is offered and its reach answered from the peer, input and all; without the trust it is neither offered nor reached; nor for a hive this humd was never taught.Docs
Verified
cargo test --locked -p ensemble -p sim -p humd -p hum -p humctl -p hum-pathscodegen --check, tools/speech.py, tools/paths.py, the CI clippy line.