A new UI, and detailed reports in under 4 minutes
The Next.js app has a new paper design that matches gptr.dev. Settings live in one modal with tabs for Research, MCP, Documents and Backend; a run shows a plain-language feed, and the sources margin slides in once writing starts. The previous UI is still available at /classic.
Detailed reports now finish in 3:27 instead of 9:11. Sections are researched in parallel, and the default writer is now gpt-6-sol, which starts writing within seconds instead of reasoning for close to a minute per section first. Measurements and the model comparison are in #2272.
⚠️ Changes to note
- Default writer model:
SMART_LLMis nowopenai:gpt-6-sol(wasopenai:gpt-5.4). SetSMART_LLMto keep the previous model. - LLM idle timeout: an LLM call that sends nothing for 300 seconds now fails with a clear error instead of hanging the run. Tune it with
LLM_TIMEOUT(0disables it). (#2220) - Docker: the root
.envis no longer copied into images.docker composeloads it at runtime (needs Compose 2.24+); withdocker run, pass--env-file .env. If you ever pushed an image you built locally, rotate the keys that were in your.env. generate_reportnow raises when every LLM attempt fails, instead of returning an empty report. (#2219)
Also in this release
- Prebuilt Docker images for
linux/amd64andlinux/arm64on GHCR:ghcr.io/assafelovic/gpt-researcherandghcr.io/assafelovic/gpt-researcher-frontend-nextjs, tagged with the version andlatest(#1517) - Research observer: an optional lifecycle observer for integrations that want structured progress events (#2232)
- MiniMax regional providers and Flash defaults (#1924), a configurable TypeSafe base URL (#2243), and Deploy on Render with a
render.yamlblueprint (#2184) - Multi-agent plan review feedback from the web UI works again, and the multi-agent writer uses
SMART_TOKEN_LIMITandREASONING_EFFORT(#2272) - Deep research honors reasoning budgets, counts retries and nested researchers in costs, and keeps cited learnings at the word limit (#2260, #2209, #2208)
- MCP search no longer blocks the event loop, and the
max_toolscap is enforced (#2262, #2263) - Configuration:
reasoning_effortfrom JSON config files,DOC_PATH/REPORT_SOURCEenv overrides, UTF-8 config files, and image generation settings are all honored again (#2230, #2248, #2249, #2199, #2246) - Retriever, scraper and document loader fixes across Exa, Google, Bing, Bocha, PubMed Central, arXiv, online documents and Windows text files
- Retriever plugins: a community list with Keenable and Sciverse (#2176, #2225)
53 community pull requests went into this release. Thank you to everyone who contributed.
Install: pip install -U gpt-researcher (0.17.0)
What's Changed
- fix(readme): point star history chart back to official star-history.com by @assafelovic in #2204
- docs: drop STORM references and describe current research approach by @assafelovic in #2205
- fix(config): preserve loaded MCP settings by @imharjot in #2193
- fix(config): stop sharing mutable defaults between Config instances by @assafelovic in #2206
- fix(ci): cap pytest below 9.2 so --forked tests stop crashing by @assafelovic in #2269
- docs: use a single black tile logo in the READMEs by @assafelovic in #2270
- New paper UI, and detailed reports in 3:27 instead of 9:11 by @assafelovic in #2272
- docs(readme): show only the demo GIF by @assafelovic in #2273
- Release 0.17.0: 53 community fixes, Docker secrets fix, GHCR multi-arch images by @assafelovic in #2274
- fix(report): raise error and log failure when generate_report LLM calls fail by @pei711 in #2219
- docs: add Sciverse to community retriever plugins by @gary-Shen in #2225
- fix(config): honor reasoning effort from JSON configuration by @yunyv in #2230
- feat: add an optional research lifecycle observer by @EvanZhao119 in #2232
- docs: fix links broken by the deep_agents branch split and two upstream migrations by @SoulmatelynchVFX in #2236
- fix(deep-research): validate follow-up question shapes before iteration by @WitBlue6 in #2238
- (feat) Custom typesafe base url by @eriktews in #2243
- fix: image generation config read with wrong (uppercase) attribute names - feature unreachable by @Akaliup in #2246
- fix: DOC_PATH and REPORT_SOURCE env overrides ignored by doc path setup by @Akaliup in #2248
- fix(config): read JSON configuration files as UTF-8 by @DZH166 in #2249
- fix(document): detect online document type from URL path by @Elon-Jiang in #2252
- fix(scraper): select the arXiv backend by URL hostname by @DZH166 in #2254
- fix(markdown): decode HTML entities in extracted section text by @DZH166 in #2255
- Preserve configuration and document inputs in detailed subtopic reports by @yunyv in #2256
- docs(mcp): fix broken links in Claude integration documentation by @pei711 in #2258
- fix(deep-research): honor reasoning budgets and track retry costs by @SJ-Xia-Q in #2260
- Clear stale sources after empty deep research runs by @Quinnod345 in #2261
- fix(research): run the blocking MCP retriever search off the event loop by @DZH166 in #2262
- fix(mcp): enforce the max_tools cap when the LLM picks MCP tools by @DZH166 in #2263
- fix(cost): update_cost uses raw unsanitized token counts inconsistent with calculate_cost by @Cmz9111 in #2264
- fix(scraper): get_image_hash returns None on error despite str return type annotation by @Cmz9111 in #2265
- fix(costs): guard estimate_embedding_cost against None and non-str inputs by @pei711 in #2266
- fix(bocha): implement get_api_key error handling and add unit tests by @pei711 in #2267
- fix(bing): apply query_domains and harden payload parsing in BingSearch by @pei711 in #2268
- feat: update MiniMax regional providers and Flash defaults by @octo-patch in #1924
- fix(multi_agents): treat an empty console plan reply as approval, as the web form does by @hesam-shams in #2164
- fix: revalidate PyMuPDFScraper retry output against content-quality checks by @MrSampson in #2167
- fix: ReportGenerator.write_report() must read researcher.websocket live by @MrSampson in #2169
- docs: add a community plugins list to Retriever Plugins by @ilya-bogin-keenable in #2176
- fix(exa): harden find_similar and get_contents against client failures by @RerankerGuo in #2181
- fix(document): harden LangChainDocumentLoader.load against malformed rows by @RerankerGuo in #2183
- feat: add Deploy on Render page and render.yaml by @Ho1yShif in #2184
- docs: document generic MCP connection headers and fix Quick Start syntax by @ct-jaryn in #2185
- chore(deps): update numpy requirement from <2.5.0,>=2.0.0 to >=2.0.0,<2.6.0 by @dependabot[bot] in #2187
- test: stop tests leaking sys.modules stubs; run CI suite without --forked by @Saadanjum0 in #2189
- fix: resolve PubMed IDs before fetching PMC full text by @GoldArowana in #2195
- fix(images): read image_generation_* config keys in the case Config stores them by @Winoren in #2199
- fix(document): keep OnlineDocumentLoader url a string when metadata omits source by @Winoren in #2200
- docs: fix broken README language and evals links by @pratikgx in #2201
- fix(deep-research): keep cited learnings when the context reaches the word limit by @porkedchop in #2208
- fix(deep-research): count strategic LLM calls and nested researchers in costs by @porkedchop in #2209
- fix(scraper): treat the "Client Challenge" interstitial as a block page by @yail259 in #2213
- fix(google): match YouTube exclusions by hostname by @sanjayrohith in #2215
- fix: replace retired Google and Anthropic model defaults by @pcbeingused333 in #2216
- fix: don't send temperature to Claude models that reject it by @pcbeingused333 in #2217
- fix(llm): bound stalled responses with configurable idle timeouts by @Xiaoshaoxinxing in #2220
- docs: sync Chinese README (README-zh_CN.md) with the English README by @yuee3 in #2222
- fix(pubmed_central): keep words whole at inline markup and put each block on its own line by @L4XB in #2224
- fix(scraper): retry HTTP 403 with a transparent user agent by @EvanZhao119 in #2231
- fix(document): load UTF-8 .txt and .html documents on Windows by @tanishqbaweja in #2237
- fix(prompts): preserve config in invalid prompt family fallback by @jixuantang in #2245
- fix(vector-store): skip empty chunk batches by @Elon-Jiang in #2250
New Contributors
- @imharjot made their first contribution in #2193
- @pei711 made their first contribution in #2219
- @gary-Shen made their first contribution in #2225
- @yunyv made their first contribution in #2230
- @EvanZhao119 made their first contribution in #2232
- @SoulmatelynchVFX made their first contribution in #2236
- @WitBlue6 made their first contribution in #2238
- @eriktews made their first contribution in #2243
- @Akaliup made their first contribution in #2246
- @DZH166 made their first contribution in #2249
- @Elon-Jiang made their first contribution in #2252
- @SJ-Xia-Q made their first contribution in #2260
- @Quinnod345 made their first contribution in #2261
- @Cmz9111 made their first contribution in #2264
- @hesam-shams made their first contribution in #2164
- @MrSampson made their first contribution in #2167
- @ilya-bogin-keenable made their first contribution in #2176
- @RerankerGuo made their first contribution in #2181
- @Ho1yShif made their first contribution in #2184
- @ct-jaryn made their first contribution in #2185
- @Saadanjum0 made their first contribution in #2189
- @GoldArowana made their first contribution in #2195
- @Winoren made their first contribution in #2199
- @pratikgx made their first contribution in #2201
- @porkedchop made their first contribution in #2208
- @yail259 made their first contribution in #2213
- @sanjayrohith made their first contribution in #2215
- @pcbeingused333 made their first contribution in #2216
- @Xiaoshaoxinxing made their first contribution in #2220
- @yuee3 made their first contribution in #2222
- @tanishqbaweja made their first contribution in #2237
- @jixuantang made their first contribution in #2245
Full Changelog: v3.7.0...v3.8.0