ResearchAgent is a Streamlit app that uses Anthropic Claude tool use to research a topic, call local Python tools, and produce a structured markdown report.
The project is intentionally small and interview-friendly: the UI, agent loop, and tool implementations are separated so the function-calling architecture is easy to explain.
- Claude Sonnet 4 tool-use agent loop
- Web search with DuckDuckGo-compatible search packages
- Page fetching and plain-text extraction with
requestsandBeautifulSoup - Internal Claude summarization tool
- In-memory report builder with sections
- Live Streamlit tool-call log
- Markdown report preview and download
- Guardrail synthesis pass if the agent gathers evidence but reaches the iteration limit before saving every section
User enters topic in Streamlit
|
v
app.py creates ResearchAgent
|
v
agent.py sends Claude:
- system prompt
- conversation messages
- tool schemas
|
v
Claude chooses the next action
|
+-------------------------------+
| |
v v
Returns final text Returns tool_use block(s)
| |
v v
Display final report Python executes requested tool
|
+--> web_search(query)
+--> fetch_page(url)
+--> summarize_text(text, focus)
+--> save_to_report(section, content)
|
v
Python returns tool_result
|
v
Claude reasons over results
|
v
Loop repeats, max 10 iterations
Claude does not directly run Python code. Instead, agent.py gives Claude tool schemas that describe the function names, arguments, and purpose of each tool.
When Claude needs outside information or wants to save a section, it returns a tool_use content block. The Python app reads that block, executes the matching local function, and sends the output back as a tool_result block.
That design is useful because the model handles reasoning and planning, while the application keeps control over:
- API keys and credentials
- Network calls
- Timeouts and error handling
- Logging
- Report state
- Tool input validation
- Final formatting and cleanup
Searches DuckDuckGo-style results and returns the top five results with title, URL, and snippet.
Fetches a URL, extracts readable text with BeautifulSoup, removes noisy page elements, and truncates output to 2000 characters.
Makes an internal Claude call to summarize source text into 3-5 focused bullet points.
Saves markdown into an in-memory report dictionary. Valid sections are:
- Overview
- Key Findings
- Different Perspectives
- Conclusion
Example topic:
AI News: May 2026
Representative live log:
[Agent] Iteration 1: asking Claude for next action
[Tool: web_search] query: 'AI news May 2026 artificial intelligence developments'
[Agent] Iteration 2: asking Claude for next action
[Tool: fetch_page] url: 'https://blogs.microsoft.com/on-the-issues/2026/05/07/the-state-of-global-ai-diffusion-in-2026/'
[Agent] Iteration 3: asking Claude for next action
[Tool: fetch_page] url: 'https://www.reuters.com/technology/artificial-intelligence/'
[Agent] Iteration 4: asking Claude for next action
[Tool: summarize_text] focus: 'Major AI developments and policy themes in May 2026'
[Agent] Iteration 5: asking Claude for next action
[Tool: save_to_report] section: 'Overview'
[Agent] Iteration 6: asking Claude for next action
[Tool: save_to_report] section: 'Key Findings'
[Agent] Iteration 7: asking Claude for next action
[Tool: save_to_report] section: 'Different Perspectives'
[Agent] Iteration 8: asking Claude for next action
[Tool: save_to_report] section: 'Conclusion'
[Agent] Iteration 9: asking Claude for next action
[Agent] Claude returned a final answer with no tool calls
What is happening:
- Claude searches for relevant sources.
- Claude chooses promising URLs from the search output.
- Python fetches those pages and returns text.
- Claude summarizes the evidence.
- Claude calls
save_to_reportfor each report section. - Streamlit renders the final markdown and enables report download.
If the model spends too many iterations gathering evidence, agent.py runs a final synthesis step from collected tool results so the user still receives a usable report.
ResearchAgent/
app.py Streamlit UI
agent.py Claude agent loop and orchestration
tools.py Tool implementations
requirements.txt Python dependencies
.env.example Environment variable template
.gitignore Local secrets/cache exclusions
README.md Project documentation
cd ResearchAgent
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt
copy .env.example .envAdd your Anthropic API key to .env:
ANTHROPIC_API_KEY=your_anthropic_api_key_here
streamlit run app.pyIf you want to be explicit about the virtual environment:
.venv\Scripts\python.exe -m streamlit run app.py --server.port 8501Then open:
http://localhost:8501
- The app uses
claude-sonnet-4-20250514. - The agent loop is capped at 10 iterations.
- Reports are stored in memory for the current run.
- Downloaded reports are markdown files.
.envis ignored by Git so API keys are not committed.