A modular Python AI agent that:
- Detects user intent (general question, launch/date calculation, latest news)
- Retrieves web context with Tavily
- Builds intent-aware prompts
- Streams responses from Google Gemini
- Extracts dates from snippets and computes day differences for launch/date questions
- Preserves conversational context to resolve follow-up references like "it"
web-search-agent/
main.py
README.md
.env
requirements.txt
config/
settings.py
agent/
web_agent.py
services/
context_service.py
intent_service.py
llm_service.py
search_service.py
utils/
date_utils.py
formatter.py
models/
schemas.py
prompts/
prompts.py
- Python 3.10+
- Internet access (for Tavily and Gemini APIs)
From your workspace root:
cd web-search-agentpip install -r requirements.txtCreate/update .env in web-search-agent:
GOOGLE_API_KEY=your_google_api_key
TAVILY_API_KEY=your_tavily_api_key
GOOGLE_MODEL=gemini-2.5-flashNotes:
GOOGLE_MODELis optional; default isgemini-2.5-flash.- If the configured model is unavailable, the app falls back to
gemini-2.0-flash.
Run from inside web-search-agent:
python main.pyYou will see:
Web Search Agent (type 'exit' to quit)
Then ask multiple questions interactively.
Example:
User Query: nuclear bomb was invented how many days ago?
User Query: can you predict when it can be used in the future?
The second query can resolve it from conversation context.
From requirements.txt:
google-generativeai>=0.8.0- Gemini client SDK for text generation and streaming tokens.
python-dotenv>=1.0.1- Loads
.envconfiguration into process environment.
- Loads
requests>=2.32.0- HTTP client used for Tavily API calls.
main.py- CLI loop and interaction lifecycle.
agent/web_agent.py- Orchestrates the end-to-end pipeline.
services/*intent_service.py: rule-based intent detection.context_service.py: conversational entity tracking and pronoun resolution.search_service.py: Tavily API integration.llm_service.py: Gemini streaming generation and model fallback.
utils/*formatter.py: builds prompt context and source output format.date_utils.py: date regex extraction and day-difference computation.
prompts/prompts.py- intent-specific prompt templates and instructions.
models/schemas.py- typed data models shared across modules.
config/settings.py- strict environment-backed settings loading.
- Read user query.
- Resolve ambiguous references using previous turn entity (if needed).
- Detect intent.
- Search web with Tavily.
- Build context from source title, URL, snippet.
- Build intent-aware prompt.
- Stream Gemini answer token-by-token.
- For launch/date intent, compute and append day-difference summary.
- Print formatted sources.
- Decision: Regex/rule patterns in
IntentService. - Why: Fast, deterministic, no extra API cost, easy to debug.
- Trade-off: Lower recall on unusual phrasing; requires manual pattern updates.
- Decision: Keep orchestration in
WebAgent. - Why: Simpler control flow and easier interview explanation.
- Trade-off: As features grow, orchestration can become crowded.
- Decision: Store last extracted entity in memory for pronoun resolution.
- Why: Improves follow-up query quality with minimal complexity.
- Trade-off: Memory is session-local only; not persisted across restarts.
- Decision: Use system local date (
date.today()). - Why: Matches user expectation in CLI and avoids timezone confusion.
- Trade-off: Results can differ across machines in different timezones.
- Decision: Retrieval-augmented generation with source grounding.
- Why: Better factuality than pure LLM answers and supports citations.
- Trade-off: Accuracy depends on search result quality and snippet completeness.
- Decision: Fallback model on
NotFoundand extractive summary on quota exhaustion. - Why: Keeps the app usable under API instability/limits.
- Trade-off: Fallback response quality may be lower than normal generation.
- Ensure your current directory is
web-search-agentbefore running install. - Verify Python/pip point to the same interpreter.
- Confirm
.envexists inweb-search-agent. - Required keys:
GOOGLE_API_KEYTAVILY_API_KEY
- Keep
GOOGLE_MODEL=gemini-2.5-flashor another valid model. - The app automatically attempts
gemini-2.0-flashfallback.
- Check network connectivity.
- Verify Tavily key validity and quota.