Skip to main content

gossamer — High-Performance LLM Web Researcher

A hybrid LLM web researcher combining a Rust parsing core (PyO3) with Oxide extractors for documents and a Python orchestration layer for caching, rate limiting, budgets, tool routing, and multi-provider search.

Python PyPI Rust License Tests

Docs: Quick reference · Architecture · Changelog


Architecture

LLM Agent / User
       │  MCP (mcp_server.py) · CLI (cli.py) · skills/SKILL.md
       ▼
WebResearcherToolbox (agent_tools.py) — facade, no logic
       │  TOOL_REGISTRY (config.py): one source of truth
       ▼
Collaborators (Python: HTTP, keys, rate limits, orchestration)
fetch · search · crawl · document · discovery · 38 domain adapters
       │  JSON strings down, JSON strings up
       ▼
_core (Rust): all response parsers, HTML metadata (in-core meta_oxide
crate), SSRF/robots, budgets, guard, citations, tokens, scoring

Python decides, Rust parses. Details: Architecture.


Features

  • Zero API Keys: DuckDuckGo plus 20+ keyless domain adapters (OpenAlex, Eurostat, Bundesbank, HUDOC, …)
  • Multi-Provider Search: Google, Bing, Exa alongside DuckDuckGo with failover or merged results
  • Domain Providers: research_by_category classifies queries (incl. German/EU terms like Leitzins, BVerfG, HICP) into scholarly / legal / patent / financial / geo — keyless-first
  • Patent Providers: EPO OPS, KIPRIS, PatentsView, Lens (all key-gated, fail fast with the exact variable name; Lens aggregates WO/EP/DE/CN/US, trial is non-commercial/academic) + keyless Google Patents number lookup
  • Documents: PDF/DOCX/XLSX/PPTX plus TXT/MD/CSV/JSON/XML/feeds; tables render as markdown by default; store=True, include_images=True saves PDF figures
  • Crawl: bounded relevance-ranked BFS (BM25 idfs + thesaurus + anchor context); documents collected, never fetched
  • Citations: BibTeX / CSL-JSON / APA / MLA from search results, no extra network calls
  • HTML Metadata: 13 formats via the in-core meta_oxide crate — no separate install, no PyPI blocker
  • Guard (optional, off): JailGuard ONNX detector — annotate / redact / block
  • Production-Ready: TTL + size-cap caching, per-domain rate limits, robots/SSRF compliance, retries, observability

Quick Start

Prerequisites

  • Rust 1.82+ (rustup), Python 3.10+, maturin

Build & Install

git clone https://github.com/opticsWolf/gossamer && cd gossamer
pip install -r requirements.txt
maturin develop --release
# Optional: headless-browser rendering for JS-heavy pages
# (`use_smart="browser"`). Windows/macOS only — no Linux wheels exist,
# so this stays an extra (never a hard dependency) and static fetch
# remains the default.
pip install -e ".[browser]"

Basic Usage

from gossamer import ToolboxConfig, WebResearcherToolbox

tools = WebResearcherToolbox(ToolboxConfig(
    cache_dir="./cache",
    max_tokens=4000,
    model_name="gpt-4o",
))

results = tools.web_search("latest AI research papers", max_results=5, search_only=True)
content = tools.inspect_html_page("https://arxiv.org/abs/1234.5678")
pdf = tools.extract_document("https://example.com/paper.pdf")
with_figs = tools.extract_document("https://example.com/paper.pdf",
                                    store=True, include_images=True)
report = tools.research_by_category("EZB Leitzins", max_results=5)

Async Usage

results = await tools.search_web_async("rust programming")

What "async" means here (thread pool). The *_async wrappers offload the shared blocking implementation to Python's default thread-pool executor (loop.run_in_executor(None, …)), keeping the event loop responsive — but the underlying network I/O is still synchronous. Use them inside asyncio apps to avoid blocking the loop; call the sync methods otherwise. Full model: Architecture.

Tools (twelve MCP tools, everywhere)

MCP tools, CLI commands (gossamer …), and execute_tool(name, args) are the same surface, param-for-param: web_search, inspect_html_page, batch_inspect_pages, download_file, locate_pdf, extract_document, discover_resources, crawl, manage_cache, research_by_category, export_citations, check_sources. download_file saves an opaque remote file without requiring extraction; caller-supplied fallback_urls are tried sequentially with normal robots/SSRF checks, and resume=true continues a partial file with Range/If-Range (restart when the server ignores Range). Use extract_document when you also want parsed text. locate_pdf resolves a DOI to OpenAlex OA PDF/landing-page candidates (plus Unpaywall v2 when GOSSAMER_UNPAYWALL_EMAIL is configured) without downloading them. The CLI adds gossamer categories (routing table; not an MCP tool). Parameters: Quick reference.

tools.get_llm_definitions()  # OpenAI-compatible function definitions
tools.execute_tool("inspect_html_page", {"url": "https://example.com"})

Domain Providers (research_by_category)

Category Providers (first = default)
scholarly OpenAlex (default), Crossref, arXiv, Zenodo, Semantic Scholar (opt-in; key recommended for rate limits)
legal CourtListener, eCFR, Federal Register, Open Legal Data, HUDOC (ECtHR), GovInfo
patent EPO OPS, KIPRIS, PatentsView, Lens 🔑 + keyless Google Patents lookup
financial Yahoo, Frankfurter (FX), Eurostat, Bundesbank, BIS, CoinGecko, AlphaVantage 🔑
geo Open-Meteo, Overpass
general DuckDuckGo (Google/Bing/Exa 🔑 opt-in)

Euro terms route automatically (EZB, Leitzins, HICP, EGMR, BVerfG, DSGVO, …). For precise OpenAlex queries, gossamer research QUERY --provider openalex --filter 'type:article' --select 'id,title,doi' --title 'gradient index' --author 'Smith' passes provider-native controls; those options are rejected for other providers. --title/--author map to the verified title.search/raw_author_name.search filters and combine with --filter. Explicit scholarly multi-search is opt-in via gossamer research QUERY --providers openalex arxiv; it merges by DOI/arXiv ID, preserves each source record, and never fans out by default.

Paper collection: research → check --mode status → optional locate-pdf DOI → download URL -o FILE --expect-format pdf → extract FILE → cite DOI (or cite FILE.pdf [--from-pdf] for a DOI detected from the file). Supplied mirror URLs are checked independently; gossamer respects robots/SSRF policy and does not bypass bot walls. The skill has the full recipe.


Configuration

Env wins over file, always. Keys: GOSSAMER_* env > legacy STITCH_* > keystore ($GOSSAMER_KEYSTORE > gossamer.json:keystore > ~/.gossamer/keys.json) > gossamer.json "keys". Config file: explicit > $GOSSAMER_CONFIG > ./gossamer.json > ~/.gossamer/config.json.

python -m gossamer.keystore --init          # 0600 template, fill it in
python -m gossamer.keystore --init-config   # gossamer.json template
python -m gossamer.keystore --check         # validate, never prints secrets
{ "max_tokens": 4000, "model_name": "gpt-4o", "fetch_mode": "auto" }

OpenAlex works without a key for casual use. Set GOSSAMER_OPENALEX_KEY (in the keystore or environment) for the higher daily budget. If you want to identify your client by email, set GOSSAMER_OPENALEX_EMAIL; it is sent as mailto and in the request headers. No placeholder email is sent when unset. Semantic Scholar is also callable without a key, but keyless requests share a pool and may receive 429s; set GOSSAMER_SEMANTICSCHOLAR_API_KEY for its individual one-request-per-second allowance.


Harness Integration (pi, Codex, Claude Code)

Same stdio server everywhere (python -m gossamer.mcp_server); keys stay in the keystore, never in client configs. Shallowest first: direct CLI (gossamer search|research|inspect|download|locate-pdf|extract|…, 1:1 with MCP) → MCP (directTools) → skills/gossamer/SKILL.md.

pi (mcp.json, then reload):

{ "mcpServers": { "gossamer": {
  "command": "D:/User/Documents/Python/gossamer/.venv/Scripts/python.exe",
  "args": ["-m", "gossamer.mcp_server"],
  "env": { "GOSSAMER_CACHE_DIR": "D:/User/Documents/Python/gossamer/.gossamer_cache",
            "GOSSAMER_LOG_LEVEL": "WARNING" },
  "directTools": true } } }

Codex (~/.codex/config.toml):

[mcp_servers.gossamer]
command = "D:/User/Documents/Python/gossamer/.venv/Scripts/python.exe"
args = ["-m", "gossamer.mcp_server"]
startup_timeout_sec = 30

Claude Code:

claude mcp add gossamer -- D:/User/Documents/Python/gossamer/.venv/Scripts/python.exe -m gossamer.mcp_server

Keep crawls modest (max_pages ≤ 15) — long runs outlast harness timeouts.


Running Tests

Hermetic by default (no network, SSRF on):

.venv/Scripts/python.exe -m pytest -q -n auto --ignore=tests/test_live_smoke.py
GOSSAMER_LIVE=1 pytest tests/test_live_smoke.py   # opt-in endpoint-drift check

Subset markers (-m area_search|area_fetch|area_crawl|…) are assigned by filename in tests/conftest.py. Details: Architecture.

License

Dual-licensed under MIT OR Apache-2.0 — zero copyleft, zero JVM.

Release files for gossamer-web 0.9.25

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gossamer-web 0.9.25
File Size Uploaded
gossamer_web-0.9.25.tar.gz 1.2 MB Details

Built distributions (wheels)

Table of built distributions (wheels) for gossamer-web 0.9.25
File Interpreter ABI Platform
gossamer_web-0.9.25-cp38-abi3-win_amd64.whl CPython 3.8 abi3 Windows x86-64 Details
gossamer_web-0.9.25-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.8 abi3 Linux glibc 2.17+ x86-64 Details
gossamer_web-0.9.25-cp38-abi3-macosx_11_0_arm64.whl CPython 3.8 abi3 macOS 11.0+ ARM64 Details

Total release size: 24.7 MB

Release files / gossamer_web-0.9.25.tar.gz

Download URL gossamer_web-0.9.25.tar.gz
Size 1.2 MB
Tags Source
SHA-256 checksum
How to use checksums
993c2806b6d915ffe776f207937d883810201022672c711cb13618a926f74871
BLAKE2b-256 checksum
How to use checksums
fb1c8a74e916a9d4377291ec0b195a31f45283865dab715dd912904aef5ba624
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / gossamer_web-0.9.25-cp38-abi3-win_amd64.whl

Download URL gossamer_web-0.9.25-cp38-abi3-win_amd64.whl
Size 8.0 MB
Tags CPython 3.8 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
eb0890a95bafcd9e20168e5523bb00e2319685974ca8dd3c9dadc1060d4d8259
BLAKE2b-256 checksum
How to use checksums
e0c43f3d88137fe3d2fbd8d147945d1e877220fea662e5e3b31138da81122daf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / gossamer_web-0.9.25-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL gossamer_web-0.9.25-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 7.9 MB
Tags CPython 3.8 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
49ee4dbf3cb472acbe6710ae5433133f7a84a2d71827c63f65eeb43a37af6a5c
BLAKE2b-256 checksum
How to use checksums
e04e80efeeee0069968eb07e42596df56ae1a2da384eb6194162d1ac1a30b73f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / gossamer_web-0.9.25-cp38-abi3-macosx_11_0_arm64.whl

Download URL gossamer_web-0.9.25-cp38-abi3-macosx_11_0_arm64.whl
Size 7.6 MB
Tags CPython 3.8 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
428176d425e62f3f983f8c0c05ae56357dabcbc89b918d834a550b355c6d9d60
BLAKE2b-256 checksum
How to use checksums
521c1c24e620dd6f0178f4d38fb6c4502be6e88f09bcda02d18425795db641a9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.9.25 This release

4 release files

0.9.6

4 release files

0.9.5

4 release files

0.9.3

4 release files

0.9.2

4 release files

0.9.0

4 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page