Research agent
Answers from what the search actually returned, and hands back the URLs.
The program, and what it printed
This ran against effGen with gemini:gemini-3.1-flash-lite. The pane under the code is that run’s output, pasted — so where the answer depends on a live API or on the model’s wording, yours will differ. The pane is the shape that run actually had, not a tidied one.
from effgen import Agent, AgentConfig
from effgen.tools.builtin import WebSearch
agent = Agent(AgentConfig(
model="gemini:gemini-3.1-flash-lite",
name="research-agent",
system_prompt="Answer from what the search returned. Do not answer from memory.",
tools=[WebSearch()],
max_iterations=6,
))
response = agent.run("What is the Open-Meteo API, and does it need an API key?")
print(response.text)
print()
print("sources:", len(response.sources))
for url in response.sources[:3]:
print(" ", url)The Open-Meteo API is a service that provides access to historical, current, and forecasted weather data [1, 4]. It is designed to be easy to use and is a popular choice for projects requiring weather information [3, 4]. Regarding authentication, the Open-Meteo API does not require an API key for development or low-volume production use [2, 5]. It allows users to access its services without the need for registration, signup, or credit card information [3, 4]. However, users should review the current terms for heavy commercial workloads [2]. sources: 5 https://freeapihub.com/apis/open-meteo-historical https://apideposu.com/en/blog/build-weather-widget-open-meteo-nextjs https://freeapi.watch/open-meteo/
What it does
A search tool and an instruction not to answer from memory. What makes the result usable is not the prose: it is that response.sources carries the URLs the run retrieved, so you can check the answer against them. In 1.0.0 these are separate fields — .sources is everything the search returned, .citations is what the answer referenced.
What the run shows
- The URLs are the ones the tool returned on this run. Run it tomorrow and they will be different, because the web is.
- WebSearch defaults to a backend that needs no API key, so this example runs with nothing configured.
- The system prompt is what keeps the model on the retrieved text. Without it, a model will happily answer from what it remembers.
The full script
The program above is the short version. The one in the repository at examples/web_retrieval/web_agent.py covers more cases and takes a --model flag. It ships with the package, so it runs from the command line without cloning anything:
effgen examples run web_retrieval/web_agentRead it on GitHub