AIClaw is a self-hosted AI agent platform, and one of the recurring problems in agent products is how to give an agent fresh web information without turning the whole search path into a black box.
In AIClaw v1.10.5, the project added configurable web search engines and made that flow visible in both agent setup and execution logs. This is a concrete feature in the current repository, not a roadmap idea: the backend added search-engine models, storage, handlers, and a web_search tool implementation, while the web console added a new Search Engine page and agent-side selection for external search.
The problem
There are really two different "web search" cases in agent systems:
- The model itself supports built-in search.
- The model does not, or you want to route search through your own provider and credentials.
Those are not operationally equivalent. Built-in search is convenient, but external search gives you explicit provider choice, saved credentials, per-agent configuration, and a clearer execution boundary.
AIClaw now supports both modes.
Two search modes in one agent config
The current README describes the behavior clearly:
- Built-in mode sends
extra_body: {"enable_search": true}to models whose capability profile supports web search. - External mode exposes a
web_searchtool and routes the call through a selected search engine configuration.
That matters because the agent prompt and runtime behavior stay aligned with the actual path:
- In built-in mode, AIClaw records a
web_searchexecution step showing that model-native search was enabled for the LLM request. - In external mode, AIClaw only exposes the
web_searchtool when that mode is active, and the tool call is resolved through the selected search engine config.
This separation is visible in the current backend code around internal/agent/run.go, internal/agent/prompt.go, and internal/agent/executor.go.
What the new feature actually adds
The feature is broader than "call one API". The repository now includes:
- A new search-engine configuration model with
provider,name,base_url,api_key, andenabledfields. - Storage and CRUD handlers for search engine configs.
- A new web console page for Search Engine management.
- Agent form support for choosing built-in vs external web search and binding an enabled search engine.
- A
web_searchtool handler that reads the selectedsearch_engine_idfrom runtime context. - Tests for request shaping, result normalization, provider-specific behavior, limits, and missing-config handling.
Supported external providers in the current codebase are:
- Tavily
- SerpAPI
- Aliyun IQS
Why this design is useful
The best part of this implementation is that it does not pretend all search is the same.
If your chosen model already supports native search, AIClaw can use that path directly. If you need a controlled external path, AIClaw lets you configure search as a first-class resource and then attach that resource to the agent.
That gives you a few practical advantages:
- You can keep provider API keys on the server side instead of pushing them into prompts or ad hoc scripts.
- You can save multiple search configs, enable or disable them independently, and test them before using them in a live agent run.
- You can see search activity in chat progress and execution logs, including input, output, duration, and errors.
- You can keep the agent contract explicit: use built-in search for supported models, or use an external
web_searchtool with a selected engine.
For teams running local or self-hosted agents, that operational clarity matters more than a generic "AI can browse the web" checkbox.
How the external path works
The current implementation routes external search through a dedicated handler in internal/tools/websearch/search.go.
A few details stand out:
- Search requests are rejected if the query is empty.
- Disabled configs are not usable for live execution.
- Missing API keys fail fast.
- Result limits are normalized and capped.
- Response size is bounded.
- Snippets are cleaned and truncated before being returned to the agent.
Provider handling is explicit rather than abstract hand-waving:
- Tavily uses a JSON POST body.
- SerpAPI uses query parameters for organic results.
- Aliyun IQS uses Bearer authentication and the
LiteAdvancedengine.
That kind of provider-specific normalization is exactly what turns a feature from demo-worthy to production-usable.
The web console flow
The UI side is also practical.
The new Search Engine page lets you:
- Create multiple configs
- Toggle them enabled or disabled
- Test saved configs from the list
- Test a config directly inside the create/edit dialog before saving
Then, in the agent form, you can:
- Enable web search
- Choose
builtinorexternal - Select one of the enabled search engines when using external mode
This avoids one common agent-platform failure mode: features exist in backend code, but the operator workflow is awkward enough that nobody uses them correctly.
Observability is the real feature
The technical headline is configurable web search, but the deeper value is observability.
AIClaw does not just say "search happened." It models search as an execution step:
- built-in search is recorded as a
web_searchstep attached to the LLM request - external search appears as a tool call with provider-backed results
That makes debugging much easier. When an answer is wrong, you can inspect whether the issue came from:
- no search being enabled
- the wrong mode being selected
- a disabled or missing external config
- poor upstream results
- or model reasoning after the search results were returned
That is a better operational story than hiding everything behind a generic browse capability.
A practical example
Imagine an AIClaw agent that tracks "latest Go release notes" or "today's AI infrastructure news".
With built-in mode:
- choose a model with native search support
- enable web search
- let AIClaw send
enable_search=true
With external mode:
- configure Tavily, SerpAPI, or Aliyun IQS in the Search Engine page
- enable the config
- bind that config to the agent
- let the agent call
web_searchwhen the question is time-sensitive
In both cases, the execution path is inspectable afterward.
What I like about this release
This feature is a good example of product discipline in an agent codebase:
- it added backend data structures
- it added runtime wiring
- it added UI workflow
- it added tests
- and it documented the behavioral contract in the README
That is the difference between "we support search" and "operators can actually run this in a controlled way."
If you are building self-hosted agents, configurable web search is not just about freshness. It is about choosing where search happens, how credentials are managed, and how much of the execution trail remains visible after the run.
Top comments (0)