FoundationAgents/MetaGPT · error · ValueError
To use serper search engine, make sure you provide the `api_
Error message
To use serper search engine, make sure you provide the `api_key` when constructing an object. You can obtain an API key from https://serper.dev/.
What it means
ValueError from SerperWrapper's model_validator (mode='before'): constructor values contain neither api_key nor the deprecated serper_api_key alias. Serper.dev requires an API key, so instantiation fails fast before any HTTP call. The legacy alias is accepted with a DeprecationWarning.
Source
Thrown at metagpt/tools/search_engine_serper.py:33
class SerperWrapper(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True)
api_key: str
url: str = "https://google.serper.dev/search"
payload: dict = Field(default_factory=lambda: {"page": 1, "num": 10})
aiosession: Optional[aiohttp.ClientSession] = None
proxy: Optional[str] = None
@model_validator(mode="before")
@classmethod
def validate_serper(cls, values: dict) -> dict:
if "serper_api_key" in values:
values.setdefault("api_key", values["serper_api_key"])
warnings.warn("`serper_api_key` is deprecated, use `api_key` instead", DeprecationWarning, stacklevel=2)
if "api_key" not in values:
raise ValueError(
"To use serper search engine, make sure you provide the `api_key` when constructing an object. You can obtain "
"an API key from https://serper.dev/."
)
return values
async def run(self, query: str, max_results: int = 8, as_string: bool = True, **kwargs: Any) -> str:
"""Run query through Serper and parse result async."""
if isinstance(query, str):
return self._process_response((await self.results([query], max_results))[0], as_string=as_string)
else:
results = [self._process_response(res, as_string) for res in await self.results(query, max_results)]
return "\n".join(results) if as_string else results
async def results(self, queries: list[str], max_results: int = 8) -> dict:
"""Use aiohttp to run query through Serper and return the results async."""
payloads = self.get_payloads(queries, max_results)View on GitHub (pinned to 11cdf466d0)
Solutions
- Pass the key: SerperWrapper(api_key=os.environ['SERPER_API_KEY'])
- Or set api_key under the search engine config in your MetaGPT yaml
- Legacy serper_api_key field still works if present in old configs
Example fix
# before engine = SerperWrapper() # ValueError # after engine = SerperWrapper(api_key=os.environ["SERPER_API_KEY"])
Defensive patterns
Strategy: validation
Validate before calling
import os
api_key = os.environ.get("SERPER_API_KEY")
if not api_key:
raise SystemExit("set SERPER_API_KEY before constructing SerperWrapper") Try / catch
try:
engine = SerperWrapper(api_key=k)
except ValueError as e:
raise ConfigError(str(e)) Prevention
- Preflight-check SERPER_API_KEY at startup
- Migrate legacy serper_api_key config fields to api_key
- Cache the constructed wrapper instead of rebuilding per request
When it happens
Trigger: SerperWrapper() with no args; MetaGPT config selects the serper engine without an api_key; key expected from env var that isn't set in the runtime shell.
Common situations: Switching SearchEngine to serper without configuring SERPER_API_KEY; .env omitted from deployment; config migrated to new field names incompletely.
Related errors
- To use google search engine, make sure you provide the `api_
- To use google search engine, make sure you provide the `cse_
- To use serpapi search engine, make sure you provide the `api
- Got error from SerpAPI: {res['error']}
- Got error from SerpAPI: {res['error']}
AI-assisted analysis of FoundationAgents/MetaGPT@11cdf466d0 (2026-08-14).
Data as JSON: /api/errors/2d9ea33b3a5d12c9.
Report an issue: GitHub.