Zhipu GLM web search provider: registers as `glm` on the ctx.web seam and runs the native web_search server tool through GLM's Anthropic-compatible API (Coding Plan billing).
Install
# from npm (prebuilt)
dsh plugin --profile web add dsh-web-search-glm
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:Noemm/dsh-web-search-glm
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
Zhipu GLM-backed search provider for the dsh (ctx.web) seam. It executes the native web_search_20250305 server tool through GLM's Anthropic-compatible endpoint and maps GLM's web_search_prime result blocks to normalized search sources.
How it works
The outgoing request is shaped exactly like the official @deepseek-ai/dsh-web-search-deepseek provider's: POST {baseURL}/messages carrying the web_search_20250305 server tool (bounded by max_uses), the anthropic-version header, redirect: "error", and full AbortSignal support.
The difference is entirely in the response mapping. Instead of Anthropic-standard web_search_tool_result blocks, GLM returns its own pair of blocks:
server_tool_useblocks namedweb_search_prime, paired withtool_resultblocks whosecontentis a stringified Python-repr list of search results.
The provider pairs server_tool_use with tool_result by id (multiple searches in one response are merged), parses the content (JSON.parse first, then a small hand-written Python-repr tokenizer), maps each {title, link, content} entry to {url, title, snippet}, and dedupes by url.
If the response contains no usable structured search results, the search fails with WEB_PROVIDER_ERROR — there is no scraping or prose fallback, matching the official provider's semantics. On non-2xx responses the server-side error message is passed through verbatim (still WEB_PROVIDER_ERROR). Other codes: WEB_PROVIDER_CREDENTIAL_MISSING when no API key resolves, WEB_ABORTED on cancellation.
Observed endpoint behavior (live test, 2026-08-27): GLM does not reject nonsense queries — it still executes the web search and returns ~10 sources, so the "no results" branch is rarely taken; this is endpoint behavior, not something the provider configures. Searches on this endpoint were billed under the GLM Coding Plan, like chat traffic.
Install
From the dsh plugin marketplace (once the package is listed):
dsh plugin --profile <profile> add dsh-web-search-glm
Or from a local checkout:
dsh plugin --profile <profile> add /path/to/dsh-web-search-glm
Either way, you must explicitly select the provider. dsh-web reads its selection from the web row's config — the dsh-base bundle pins deepseek-official, and a web: section in ~/.dsh/settings.yaml has no effect there. Override it in your profile's own patch layer, ~/.dsh/profiles/<profile>/cordis.patch.yml (applied after every bundle layer):
# ~/.dsh/profiles/web/cordis.patch.yml
- id: web
config:
searchProvider: glm
A patch replaces the targeted row's whole config — restate every key the base row owns (today just searchProvider).
Exporting DSH_WEB_SEARCH_PROVIDER=glm in the launching environment works too.
Without this, if the official @deepseek-ai/dsh-web-search-deepseek provider is also installed and available, more than one search provider is simultaneously available() and dsh-web throws WEB_PROVIDER_AMBIGUOUS rather than guessing.
Configuration
Settings live in the web-search-glm section of ~/.dsh/settings.yaml:
| Key | Default | Description |
|---|---|---|
apiKey |
— | Literal API key (secret). Prefer the apiKeyEnv credential reference. |
apiKeyEnv |
ZAI_API_KEY |
Credential reference name. Keep it in sync with the apiKeyEnv of the zai provider in your dsh settings so both read one stored key. |
baseURL |
https://open.bigmodel.cn/api/anthropic/v1 |
Anthropic-compatible endpoint; /messages is appended by the provider. The overseas deployment can point to https://api.z.ai/api/anthropic/v1. |
model |
glm-5.3 |
Model that executes the native web search. Verified live — see Model notes. |
apiVersion |
2023-06-01 |
Value of the anthropic-version header. |
maxTokens |
4096 |
Upper bound on generated tokens for the Messages request. |
maxUses |
5 |
Maximum web_search server-tool uses per request. |
Example:
# ~/.dsh/settings.yaml — plugin options (provider selection lives in the
# profile patch, see Install):
web-search-glm:
apiKeyEnv: ZAI_API_KEY
# baseURL: https://api.z.ai/api/anthropic/v1 # overseas endpoint
# model: glm-5.3-flash # verified alternative, see Model notes
Credential resolution chain. The key is resolved per search, in order: a literal apiKey set in the web-search-glm section → the credentials service via the apiKeyEnv reference → a launch-environment variable of the same name. If nothing resolves, the search fails with WEB_PROVIDER_CREDENTIAL_MISSING.
Endpoint environment fallback. If the web-search-glm section does not set baseURL, the launching environment's GLM_SEARCH_BASE_URL is consulted before the built-in default. The variable is deliberately distinct from any chat-completions base-URL variable — search speaks the Anthropic-compatible Messages API under its own address (mirroring upstream DEEPSEEK_SEARCH_BASE_URL).
Model notes
glm-5.3(default) — verified live on 2026-08-27: english and chinese queries each returned 10 sources through the native web search.glm-5.3-flash— verified live on 2026-08-27: all four smoke cases (english / chinese / nonsense / bad-key) behaved identically toglm-5.3, with real searches executed (english and chinese each returned 10 sources). A working alternative — setmodel: glm-5.3-flashto use it.glm-5-flash— does not exist on this endpoint. Every request is rejected by the server with[1214][modelCode:不存在](surfaced asWEB_PROVIDER_ERROR). Do not use this name.
The package default stays glm-5.3; it is not changed merely because the flash variant is available.
Compatibility
- Targets the dsh plugin seam protocol of
dsh >= 0.1.1-rc.2(peer dependencies@deepseek-ai/dsh-*^0.1.1-rc.2). - MIT License — see LICENSE.
Development
npm test— parser unit tests on the built-innode:testrunner; no extra dev dependencies. Fixtures are real captured GLM responses undertest/fixtures/.npm run capture— one-off live capture that refreshestest/fixtures/(scripts/capture.mjs). NeedsZAI_API_KEY(falls back toANTHROPIC_AUTH_TOKEN).npm run smoke— live-endpoint smoke run of four cases (english / chinese / nonsense / bad-key):node scripts/smoke.mjs [model]. NeedsZAI_API_KEY(falls back toANTHROPIC_AUTH_TOKEN).
The live scripts intentionally live in scripts/, not test/ — Node 26's node --test auto-discovery would execute them during npm test — and they are not shipped in the published npm package.
Links
More in this category
Tencent/BrowserSkill#dsh-plugin-browserskill★ 8736
BrowserSkill bridge for controlling visible Chrome and Edge Agent Windows from DeepSeek Harness, with native browser tools, accessibility and VOM observations, screenshots, owned multi-session control, and a live Web UI overlay.
omdsh-dev/dsh-browser#packages/browser/bridge-browser★ 809
Chrome sidebar extension that lets DSH operate your browser directly, no vision capabilities required.
liustack/modsearch★ 659
Web search bridge for text-only agents: ask the web or X, get structured JSON evidence (search, fetch, citations).
DDDMUC/dsh-free-search★ 378
Free, keyless web search for DSH: 7 engines (DuckDuckGo/Bing/SearXNG free + Exa/Perplexity/DeepSeek paid), auto-failover, settings-page UI with API key inputs and official links, web_fetch, and an engine test tool.
wqty123/dsh-browser★ 109
Shared real browser for DSH: a native Electron window the human can watch and take over, driven by the agent over CDP with 20 browser_* tools (open/snapshot/execute/fill/screenshot/download/auth), per-task session isolation, cookie persistence, CAPTCHA detection; self-hosts on plain dsh web without a desktop shell.
Tabbit-Browser/dsh-tabbit★ 107
Gives DeepSeek Harness control of the Tabbit Browser: auto-loads the tabbit-browser skill on install, detects official Tabbit and Tabbit Browser releases (>= 1.9.0), checks the tabbit-cli persistent runtime, diagnoses the per-platform DSH sandbox mode needed to call the CLI, and downloads the region-matched official installer via a background job when no qualifying version is present.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.