Conversation
Phase C groundwork: an opt-in derived image (whizzard-hermes-search, FROM the hermes image) that bakes the web-search client libs so a CONTAINED cell — which has no PyPI egress (only its backend endpoint is allowlisted) — can run web_search without lazy-installing at first use. firecrawl-py (contained-rung default, single endpoint) + ddgs (keyless open-rung alternative). Containment stays at the network layer: a firecrawl cell can't reach DuckDuckGo even though ddgs is present. New WHIZZARD_HERMES_SEARCH_IMAGE constant + package-data entry. Image builds clean; both clients import (firecrawl-py 4.32.1, ddgs 9.14.4). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PRQ6JeWxpD9zrYcPz6VFTS
A profile with web_search != off now launches the search-enabled cell image (whizzard-hermes-search) instead of the base Hermes image — the firecrawl/ddgs clients live only in that opt-in layer (least-privilege). Only applies when no explicit --image is given; mirrors the existing Hermes-adapter image coupling. Dry-run test locks both directions (search profile -> search image; off -> base image). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PRQ6JeWxpD9zrYcPz6VFTS
…er_plain The containment core for contained web search (D-194 Phase C). A SECOND instance of the vetted credential-broker proxy, pinned to api.firecrawl.dev — so each proxy stays single-upstream (the 'no code path forwards elsewhere' invariant holds per broker). This is the Fork-1 'reuse the broker' choice done as a second instance, not a dual-upstream router. - whizzard/search_broker.py: start/stop a Firecrawl broker that joins the cell's existing internal net (from the model broker) + its own egress net. Resolves FIRECRAWL_API_KEY host-side (fail-closed with a clear message pointing at firecrawl.dev or keyless ddgs); key bind-mounted read-only, never a run arg. - proxy.py: new 'bearer_plain' auth scheme (Authorization: Bearer, no Anthropic beta header) for non-Anthropic upstreams like Firecrawl. Unit-tested (docker mocked): Firecrawl pinning, bearer_plain, cell-net join, own egress, key-never-in-argv, fail-closed on missing key, rollback on start failure, and teardown that removes the container + egress but NOT the internal net (the model broker owns it). Verified firecrawl-py takes a custom api_url so the cell can point at the broker. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PRQ6JeWxpD9zrYcPz6VFTS
First session-handoff entry. Captures Phase C progress (image, launch image- selection, search broker + bearer_plain all committed), the launch-integration next task, rejected approaches, and the resume protocol — including the post-C setup-wizard UX pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PRQ6JeWxpD9zrYcPz6VFTS
Bring contained web search online end-to-end. When a Hermes profile sets web_search="firecrawl", _perform_launch starts the search broker (a second broker instance pinned to api.firecrawl.dev) on the model broker's internal net, points the cell's firecrawl backend at it via FIRECRAWL_API_URL + a placeholder key, and tears it down before the model broker. - adapters/hermes.py: SearchContext + FIRECRAWL_* env injection; hybrid NO_PROXY now exempts BOTH the model and search broker hosts so the cell reaches them directly instead of via the OneCLI gateway. - cli/_launch.py: validate web_search=firecrawl requires mediated/hybrid (fail loud, not a silent no-search launch); start/teardown ordering; dry-run fidelity (reports the FIRECRAWL_* argv). - broker.py: reaper sweeps a crash-orphaned search broker + its egress net + key dir before removing the shared internal net. - tests: adapter env/NO_PROXY, dry-run image+argv selection, validation. make check green (873 passed). Live smoke (real FIRECRAWL_API_KEY) still pending — confirms Hermes's firecrawl backend reads FIRECRAWL_API_URL/KEY. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PRQ6JeWxpD9zrYcPz6VFTS
…README (D-194 Phase C) Completes the two web-search rungs and their user-facing surfaces. - config: WEB_SEARCH_MODES gains "ddgs" (keyless, open-rung). off|firecrawl|ddgs. - _launch.py: split firecrawl (needs broker → mediated/hybrid) from ddgs (un-brokerable → needs open egress); each validated fail-loud. Launch banner now surfaces the posture: firecrawl = contained (key-required); ddgs = keyless with an EXPANDED-SECURITY-SURFACE warning. - cli/hermes.py: `whiz hermes image build --search` builds the search-enabled cell image (firecrawl + ddgs clients) from Dockerfile.hermes-search, so the base image stays lean and there's a real command to point users at. (Wizard prompting to offer it remains the deferred post-C UX pass.) - README: "Web search" section — the two rungs, their trade-offs, the build step. - decisions: D-194 Phase C note (broker firecrawl + open ddgs; live smoke pending). make check green (877 passed); decisions validator clean (194). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PRQ6JeWxpD9zrYcPz6VFTS
…web reach Addresses known_issues alignment finding 6 — the "contained" web-search rung restricts the cell to one network host, but Firecrawl server-side-fetches any URL the agent names, so it bounds where the cell connects, not what it can read. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PRQ6JeWxpD9zrYcPz6VFTS
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.
What
Makes web search work inside Whizzard Hermes cells, model/provider-agnostic and without opening a hole in the sandbox. Two rungs, off by default:
firecrawl(contained, recommended) — routed through a second broker instance (reuse of the D-184 credential-broker proxy, pinned toapi.firecrawl.dev, newbearer_plainauth scheme). The cell holds only a placeholderFIRECRAWL_API_KEY; the broker holds the real key and is the cell's single route out. Requires a mediated/hybrid net (validated, fail-loud).ddgs(open, keyless) — no signup, but fans out directly to many search hosts via TLS impersonation (un-brokerable), so it requires open egress. Launch surfaces an expanded-security-surface notice.Delivery: host-authored read-only managed-scope config sets
web.backend(D-194 linchpin); a--searchcell image carries the firecrawl/ddgs clients so the base image stays lean.Key changes
config.py—web_searchfield,WEB_SEARCH_MODES = off|firecrawl|ddgs.adapters/hermes.py— managed-scope authoring;SearchContext+FIRECRAWL_*env; hybridNO_PROXYexempts both brokers.search_broker.py(new) — the firecrawl broker (second proxy instance).broker/proxy.py—bearer_plainscheme (Authorization: Bearer, no Anthropic beta header).cli/_launch.py— start/teardown ordering, per-rung network validation, launch-banner notices, dry-run fidelity.broker.py— reaper sweeps crash-orphaned search brokers.cli/hermes.py—whiz hermes image build --search.Also folds in the Phase A Hermes 0.19 bump and Phase B managed-scope linchpin (already reviewed/merged to main; included here as branch history).
Verification
make checkgreen — 877 passed, lint + typecheck clean.FIRECRAWL_API_KEY— confirms Hermes's firecrawl backend readsFIRECRAWL_API_URL/_KEY(the one runtime assumption unit tests can't cover). Recommend running before merge.🤖 Generated with Claude Code
https://claude.ai/code/session_01PRQ6JeWxpD9zrYcPz6VFTS