llm-deepseek-websearch
An llm plugin that gives models two web tools, built on the DeepSeek Search and Fetch APIs:
deepseek_web_search: search the web and return ranked results with summaries.deepseek_web_fetch: fetch one page and return its content as Markdown.
The tools work with any model that supports tools in llm, not only DeepSeek models.
We use this plugin for research as part of our article writing process for Kafkai Blog, Kafkai AI Media and PuchiDen Blog.
Installation
Install this plugin in the same environment as LLM. You need LLM 0.33 or newer and Python 3.10 or newer.
llm install llm-deepseek-websearch
To install the latest code from GitHub before a release reaches PyPI:
llm install https://github.com/kafkaigiken/llm-deepseek-websearch/archive/refs/heads/main.zip
API key
Create a key on the DeepSeek platform, then store it:
llm keys set deepseek # paste the key
If no stored key exists, the plugin uses the DEEPSEEK_API_KEY environment variable.
A stored key takes priority over the environment variable, so remove it with
llm keys remove deepseek before relying on the variable. The deepseek key alias is
the same one that the llm-deepseek model plugin uses, so one stored key serves both
plugins.
Usage
Search:
llm -T deepseek_web_search "What changed in the latest Python release?" --td
Search, then read the best pages:
llm -T deepseek_web_search -T deepseek_web_fetch \
"Find the DeepSeek API rate limits and quote the official page." --td
Fetch a page you already know:
llm -T deepseek_web_fetch "Summarize https://llm.datasette.io/en/stable/tools.html"
--td (--tools-debug) prints every tool call and its result, so you can see what the
model searched for.
deepseek_web_search
| Argument | Default | Description |
|---|---|---|
query |
required | The search query, 1 to 128 characters. The plugin rejects an empty, non-string or longer query. |
count |
5 |
Number of results. Values outside 1 to 50 are clamped to that range. |
question |
"" |
The user's original question. DeepSeek uses it to rank the results. The plugin cuts it to 128 characters. |
need_content |
False |
Also return the page content of each result. Accepts true/false, yes/no, on/off and 1/0. The plugin cuts each result's content to 3,000 characters. Use deepseek_web_fetch to read a full page. |
Each result shows the title, URL, site name, date, relevance score (0 to 3, 1.5 or more is a good match), authority tier (0 to 4, 3 or more is highly authoritative) and a summary of about 600 to 800 characters.
The query supports these operators, and you can combine them:
| Operator | Example |
|---|---|
| Restrict to a site | site:python.org, site:a.com OR site:b.com |
| Exclude a site | -site:pinterest.com |
| Exclude a term | -beta |
| Exact phrase | "release notes" |
| Exclude a phrase | -"release candidate" |
| Language | lang:en, lang:ja,en |
| Date range | after:2025, after:2025-06-01 before:2026 |
The tool docstring lists the operators, so models use them without extra prompting.
deepseek_web_fetch
| Argument | Default | Description |
|---|---|---|
url |
required | An http or https URL, at most 8,192 characters, with no user name or password in it. |
It returns the page title, the URL and the page content as Markdown. The content is not cut.
Errors and retries
- The plugin makes up to 3 attempts. It retries HTTP 408, 429 and 5xx responses, and also network failures. Other HTTP errors fail at once.
- Between attempts it waits for the
Retry-Afterheader, given as seconds or as an HTTP date, and never longer than 10 seconds. Without a usable header it backs off from 1 second. - The model sees the HTTP status and DeepSeek's error message, for example
DeepSeek Fetch API error 404: ...when a page has no content that DeepSeek can extract. The plugin cuts a long error body to 1,000 characters. - A redirect fails with the new location in the message. The plugin never follows a redirect, so an API that moves a path is reported rather than silently used.
- A bad
urlfails before any request is sent, with a message naming the problem, for exampleurl must start with http:// or https://. - A malformed 200 response fails with a message saying the API may have changed, rather than looking like an empty search or an empty page.
- HTTP 402 means the account balance is too low. Add funds on the DeepSeek platform.
Pricing and limits
From the DeepSeek documentation on 2026-10-19:
- Search and Fetch each cost USD 0.75 per 1,000 successful requests. Errors, empty
results and timeouts are free.
countdoes not change the price. - Each API allows 5 requests per second per account. Fetch also has a limit per domain.
Development
To set up this plugin locally, check out the code, then create a virtual environment:
cd llm-deepseek-websearch
python -m venv venv
source venv/bin/activate
Install the dependencies and the test dependencies:
llm install -e '.[test]'
Run the tests:
python -m pytest
The tests use a mock HTTP transport, so they never call the real API and need no key.
Releasing
The Publish Python Package workflow publishes to PyPI with
trusted publishing, so the repository
stores no PyPI token.
To release a new version:
- Change
versioninpyproject.toml, then commit and push. - On GitHub, create a release with a new tag, for example
0.2. - The workflow runs the tests on Python 3.10 to 3.13, builds the package and uploads it to PyPI.
To check the package before a release, build it in a separate virtual environment:
python -m venv /tmp/buildenv
/tmp/buildenv/bin/pip install build twine
/tmp/buildenv/bin/python -m build --outdir /tmp/dist
/tmp/buildenv/bin/twine check --strict /tmp/dist/*
Metadata
Release files for llm-deepseek-websearch 0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| llm_deepseek_websearch-0.2.tar.gz | 15.7 kB | With provenance | Details for llm_deepseek_websearch-0.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| llm_deepseek_websearch-0.2-py3-none-any.whl | Python 3 | none | any | Details for llm_deepseek_websearch-0.2-py3-none-any.whl |
Total release size: 28.8 kB
Release files / llm_deepseek_websearch-0.2.tar.gz
| Download URL | llm_deepseek_websearch-0.2.tar.gz |
|---|---|
| Size | 15.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c71ccd569c17dd22be97a38230215727b66e79a9922fdca3b540479003cede9d
|
|
BLAKE2b-256 checksum How to use checksums |
17707e7974894f85b2e7dc0c20c2952330b21dbaeb1f4da511f1092f6f6e8aeb
|
| 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 Oct 19, 2026.
Transparency logRelease files / llm_deepseek_websearch-0.2-py3-none-any.whl
| Download URL | llm_deepseek_websearch-0.2-py3-none-any.whl |
|---|---|
| Size | 13.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
655e0b5132a9511b621cdea7834d3aee32bcf99a8887f522fc7e646f8bffc8c6
|
|
BLAKE2b-256 checksum How to use checksums |
f76a3677cc0998c58b35dc40f226b9e605fab3c1956af52bf0c0d2530cc5a07b
|
| 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 Oct 19, 2026.
Transparency logSecurity for llm-deepseek-websearch 0.2
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for llm_deepseek_websearch-0.2.tar.gz
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 Oct 19, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.