description, kind
| description | kind |
|---|---|
| The DeepSeek-backed search provider for ctx.web: how deployments mount native DeepSeek web search through the Anthropic-compatible Messages API, with per-search credential resolution. | package-reference |
@deepseek-ai/dsh-web-search-deepseek
English | 中文
Summary
With dsh-web-search-deepseek, the harness searches the web through DeepSeek's native search using an existing DEEPSEEK_API_KEY. Choose it when a deployment wants DeepSeek native search and accepts that one search costs a full model turn in latency and tokens, because DeepSeek exposes no dedicated search endpoint. Results come from the structured search blocks DeepSeek returns, never from scraping text out of a reply. A missing credential fails the call with a structured error; a response without a search-result block fails loudly rather than degrading. The model-facing web_search tool lives in dsh-tool-web.
Table of Contents
- Use this package
- Understand the implementation
- Further Exploration
- Model Experience
- Known Limitations and Deferred Work
- Dev Note
Use this package
Mount the provider in a composition that already loads the web service; it registers as the deepseek-official search provider, so ctx.web.search() resolves it automatically when it is the only usable search backend — or pin it with searchProvider: deepseek-official.
When to choose it
Choose this backend when a deployment wants DeepSeek's native server-side web search and already holds a DEEPSEEK_API_KEY — the provider reuses that credential reference. One search is heavier than a dedicated retrieval endpoint: DeepSeek runs the search inside a full model turn, so expect one Messages call's latency and generated tokens per search, with up to maxUses server-side searches per request. Avoid it when per-search cost or latency dominates.
Minimal configuration
Load the web service and the provider; the key resolves from ctx.credentials when that service is mounted, otherwise from the process environment. The search endpoint uses the Anthropic-compatible base (https://api.deepseek.com/anthropic/v1), distinct from the chat-completions base the LLM adapter uses — never reuse $DEEPSEEK_BASE_URL.
- name: '@deepseek-ai/dsh-web'
- name: '@deepseek-ai/dsh-web-search-deepseek'
config:
apiKeyEnv: DEEPSEEK_API_KEY
baseURL: https://gateway.internal/anthropic/v1
| Field | Default | Meaning |
|---|---|---|
apiKey |
omitted | Literal DeepSeek API key; prefer apiKeyEnv so no secret enters configuration. A non-empty literal wins |
apiKeyEnv |
DEEPSEEK_API_KEY |
Credential reference resolved for each search through ctx.credentials, or from the process environment when that service is absent. A missing value fails the call as WEB_PROVIDER_CREDENTIAL_MISSING |
baseURL |
https://api.deepseek.com/anthropic/v1 |
Anthropic-compatible endpoint base; /messages is appended. Falls back to $DEEPSEEK_SEARCH_BASE_URL; an unparseable value makes the provider unavailable |
model |
deepseek-v4-flash |
Anthropic-format model name |
apiVersion |
2023-06-01 |
anthropic-version header value |
maxTokens |
4096 |
Positive-integer upper bound on generated tokens for the Messages request |
maxUses |
5 |
Positive-integer maximum web_search server-tool uses per request |
The generated configuration catalog is the exhaustive source for every accepted field and its JSDoc. The entry above is the base layer of the provider's Settings section; a user layer over it reaches the next search, because the provider projects the section per call rather than capturing it at registration.
What a search returns
content is always omitted: DeepSeek's provider prose is not trusted as an answer. sources[] comes from web_search_result items inside web_search_tool_result blocks — url, title, and publishedAt from page_age — with snippets joined from URL-keyed cited_text entries where an excerpt exists. Results are deduplicated by URL, and because DeepSeek exposes no result-count knob, the service enforces maxResults by truncating and flagging.
Request logging
A search running under an initiating agent appends the log-only web/deepseek-search-llm-request session event immediately before dispatch. It carries the resolved endpoint, API version, and the exact secret-free JSON body sent to DeepSeek; headers and credentials are excluded. Credential failures and cancellations before dispatch create no event, while later HTTP or response failures leave the attempted request durable.
Failures and recovery
Failures throw WebError with a machine-routable code: a missing credential is WEB_PROVIDER_CREDENTIAL_MISSING, caller cancellation is WEB_ABORTED, and provider or transport failures — including a response with no web_search_tool_result block — are WEB_PROVIDER_ERROR. HTTP redirects are rejected before the Location target is contacted. The model-facing web_search tool surfaces failure text to the model under its own error wrapper.
Understand the implementation
Implementation internals — click to expand
This section explains the design decisions behind the provider; the observable behavior is fully covered in Use this package.
Design philosophy
The provider is built on two commitments:
- Structured blocks only. DeepSeek runs the search server-side and returns structured
web_search_tool_resultblocks; the provider parses those blocks and never scrapes URLs out of model prose. In strict mode, a response with no such block throwsWEB_PROVIDER_ERRORinstead of degrading. - One credential, resolved per search. The provider reuses the
DEEPSEEK_API_KEYreference (no new secret) but not$DEEPSEEK_BASE_URL, because search speaks the Anthropic-compatible Messages API. A mounted credentials service is authoritative; without one the provider falls back to the launching process environment. Resolving per call means a key stored or rotated in the Web Models page reaches the next search without a restart.
Source map
| File | Role |
|---|---|
src/index.ts |
Plugin entry: config schema, Settings section installation, per-search option projection |
src/provider.ts |
The DeepSeekSearchProvider: Messages request dispatch, block parsing, citation joining, credential resolution |
src/types.ts |
Anthropic wire types for the search response |
src/invariant.ts |
Invariant companion (no runtime invariant; contracts are enforced at the service) |
Request flow
Each search projects the current Settings section into provider options — endpoint, model, key reference, limits — then resolves the credential reference through ctx.credentials (or the environment), appends the log-only session event, and dispatches the Messages request with the native web_search server tool. The response's web_search_tool_result blocks become sources[]; cited_text entries from text blocks are joined to their URLs as snippets; results are deduplicated by URL; and the service enforces the requested source bound on the way back.
Further Exploration
Read these pages when the package-level contract is not enough. They move from the shared vocabulary to the service, the model-facing tools, and the design rationale.
- Web subsystem — the exhaustive search request/result vocabulary and error codes.
- Web package map — the six-package family and each role.
- dsh-web — the web service this provider registers into.
- dsh-tool-web — the model-facing
web_searchtool that renders this provider's sources. - Generated configuration catalog — every accepted config field and its source declaration.
- Web capability seam decision — why search and fetch share one provider-selection service.
Model Experience
Auxiliary DeepSeek search request
What the model sees
A separate DeepSeek model receives exactly Perform a web search for the query: <query> as its user text and one native web_search server-tool definition. This request is not part of the conversation model's context.
Token effect
Separate provider input and output tokens are incurred for each search; maxTokens caps generated output and maxUses caps native search uses.
KV Cache effect
Independent of the conversation request cache. The auxiliary instruction and native tool definition can form a stable prefix, but each changed query or model route prevents reuse from its first difference.
Conversation tool result, indirectly
What the model sees
Through dsh-tool-web, the conversation model sees deduplicated URLs, titles, dates, and citation snippets from structured search blocks; provider prose is not trusted as an answer. This provider's exact failures include the actionable missing-credential message, DeepSeek search credential resolution failed: <error>, DeepSeek search aborted, DeepSeek search request failed: <error>, DeepSeek returned no web_search_tool_result blocks; the request may not have triggered native web search, and DeepSeek returned an unprocessable response body: <error>; HTTP failures preserve the provider message. The consumer owns the error wrapper.
Token effect
Zero direct conversation tokens from registration. Result tokens scale with returned sources and snippets, then the service enforces the requested source bound.
KV Cache effect
Append-only; newly visible content follows the reusable request prefix and does not invalidate existing KV-cache entries.
Known Limitations and Deferred Work
These limits define when the provider is expensive or incomplete. They are current package constraints.
- One search costs a full Messages model turn — latency plus generated tokens, with up to
maxUsesserver-side searches; DeepSeek exposes no dedicated retrieval endpoint. - Dynamic credential availability resolves inside the operation — the synchronous availability check can establish that a resolver exists but cannot query an asynchronous credential store, so a selected keyless provider fails the search with
WEB_PROVIDER_CREDENTIAL_MISSING; the stableweb_searchschema stays registered. - Over-returned sources still cost tokens — with no result-count knob on the wire,
maxResultsis enforced only post-hoc by service truncation. - Uncited results carry no
snippet— a source gains one only when a text-block citation (cited_text) matches its URL.
Dev Note
Working context for maintainers — click to expand
This Dev Note is working context for maintainers: open questions and undecided directions. It is explicitly non-authoritative — shipped behavior, limits, and rationale live in the sections above and the linked Agent Notes.
Future: dedicated retrieval endpoint
A native DeepSeek search endpoint that avoids the full model turn would remove the dominant cost; until DeepSeek exposes one, this provider stays a Messages-call adapter.