Aibytec

Build a Personal AI Research Assistant with Claude API and Python in 30 Minutes

🤖 Agentic AI ⏱ 12 min read 📅 March 23, 2026 BEGINNER FRIENDLY

Build a Personal AI Research Assistant
with Claude API and Python
in 30 Minutes

Stop copy-pasting from ten browser tabs. Build an AI agent that reads, summarises, and synthesises research for you — fully in Python, no frameworks required.

🐍Pure Python
Claude API (Sonnet 4)
🧠Conversation Memory
🕐30 Minutes to Deploy

Every professional researcher, student, and developer wastes hours every week doing the same thing: opening dozens of tabs, reading the same introductory paragraphs, manually piecing together summaries. It is tedious, slow, and completely solvable with a few dozen lines of Python.

In this tutorial you will build a Personal AI Research Assistant — a Python agent powered by the Claude API that fetches web content, summarises findings, maintains conversation memory, and produces a clean final report.

"The difference between a basic API call and a real AI agent is memory, structure, and purpose."

What You Will Build

Web Content Reader
Fetches and parses any URL for research input
AI Summariser
Claude distils key insights from long-form content
Conversation Memory
Remembers your session so follow-up questions work
Multi-Source Synthesis
Combines findings from multiple sources into one report
Save to File
Export your final research report as a .txt file
CLI Interface
Run from terminal — no web framework needed
BEFORE WE START

Prerequisites & Setup

You need Python 3.9+ and a free Anthropic API key. No GPU, no cloud server, no database.

🐍
Python 3.9+
Check: python --version
🔑
Anthropic API Key
Free at console.anthropic.com
📦
pip packages
anthropic · requests · bs4
⏱️
30 minutes
From zero to working assistant

Install the dependencies:

terminal
pip install anthropic requests beautifulsoup4

Set your API key as an environment variable:

terminal
# macOS / Linux export ANTHROPIC_API_KEY='your-key-here'# Windows (Command Prompt) set ANTHROPIC_API_KEY=your-key-here

💡 Pro tip: Store your key in a .env file and use python-dotenv so it never gets committed to GitHub.

01

Project Structure

~2 minutes

Create a new folder and file:

terminal
mkdir ai-research-assistant cd ai-research-assistant touch research_assistant.py

Final folder structure:

ai-research-assistant/ ├── research_assistant.py # main file ├── .env # API key (never commit) └── reports/ # saved research reports
02

Build the Web Content Reader

~5 minutes

This module fetches a webpage and strips HTML noise, leaving only readable text for Claude. We use requests to download and BeautifulSoup to parse.

🔍

Why BeautifulSoup?

Raw HTML contains nav menus, ads, and scripts — none useful for research. BeautifulSoup extracts only paragraph text, giving Claude clean input and saving API tokens.

research_assistant.py — Part 1: Web Reader
import os import requests from bs4 import BeautifulSoup import anthropic# Initialise the Claude client client = anthropic.Anthropic( api_key=os.environ.get("ANTHROPIC_API_KEY") )def fetch_webpage_content(url: str, max_chars: int = 8000) -> str: """Fetch a URL and return clean paragraph text only.""" try: headers = {'User-Agent': 'Mozilla/5.0 (ResearchBot/1.0)'} response = requests.get(url, headers=headers, timeout=10) response.raise_for_status()soup = BeautifulSoup(response.text, 'html.parser')# Remove noise: scripts, styles, nav, ads for tag in soup(['script', 'style', 'nav', 'footer', 'header', 'aside']): tag.decompose()# Extract paragraph text paragraphs = soup.find_all('p') text = ' '.join( p.get_text(strip=True) for p in paragraphs if p.get_text(strip=True) )# Trim to token-friendly length return text[:max_chars] + ("... [truncated]" if len(text) > max_chars else "")except Exception as e: return f"Error fetching {url}: {str(e)}"

📌 Key concept: We cap at 8,000 characters to keep API costs low. Adjust max_chars based on the detail level you need.

03

Build the AI Summariser

~5 minutes

We pass the cleaned text and the research question to Claude, which returns a structured, focused summary. Prompt engineering is critical here.

🧠 Prompt Engineering Principle

Always give Claude a role, a specific task, and an output format. "Summarise this" is vague. "You are a research analyst. Extract the 3 main findings relevant to [topic] in bullet points" is precise and powerful.

research_assistant.py — Part 2: AI Summariser
def summarise_with_claude( content: str, research_question: str, source_url: str ) -> str: """Send content to Claude and get a research-focused summary."""system_prompt = """You are a precise research analyst. Extract and summarise information directly relevant to the user's question. Structure your response as:FINDINGS — 3-5 bullet points of the most relevant facts INSIGHT — 2-3 sentences of your analytical interpretation LIMITATIONS — what this source does NOT cover SOURCE QUALITY — rate High / Medium / Low with one-line reason """user_message = f"""Research question: {research_question}Source URL: {source_url}Content to analyse: {content}Please summarise the above content relative to my research question."""response = client.messages.create( model="claude-sonnet-4-20250514", max_tokens=1024, system=system_prompt, messages=[{"role": "user", "content": user_message}] ) return response.content[0].text
04

Add Conversation Memory

~5 minutes

This is what separates a basic API call from a true AI agent. By keeping a conversation history list and passing it on every call, Claude remembers everything from your session.

How Memory Works

User:
Question 1
Claude:
Answer 1
User:
Question 2
history[]
sent every time
Claude:
Contextual Answer
research_assistant.py — Part 3: Memory
# Conversation history — persists for the whole session conversation_history = []def chat_with_memory(user_message: str) -> str: """Send a message to Claude with full conversation history."""# Append the new user turn conversation_history.append({ "role": "user", "content": user_message })response = client.messages.create( model="claude-sonnet-4-20250514", max_tokens=1024, system="""You are a personal AI research assistant. You maintain full context of this research session and help synthesise findings from multiple sources.""", messages=conversation_history # full history every time )assistant_reply = response.content[0].text# Append Claude's reply to maintain the thread conversation_history.append({ "role": "assistant", "content": assistant_reply })return assistant_reply
05

Multi-Source Synthesis + Save Report

~8 minutes

Loop over multiple URLs, collect summaries, then ask Claude to synthesise them into a single coherent report — saved automatically to a file.

research_assistant.py — Part 4: Synthesis + Save
def synthesise_sources(summaries: list, research_question: str) -> str: """Combine multiple source summaries into one final report.""" combined = "\n\n---\n\n".join( f"SOURCE {i+1}:\n{s}" for i, s in enumerate(summaries) ) synthesis_prompt = f"""Research question: {research_question}I have gathered summaries from {len(summaries)} sources. Synthesise them into a final research report with:## EXECUTIVE SUMMARY (3-4 sentences) ## MAIN FINDINGS (consolidated bullet points) ## AREAS OF AGREEMENT (what all/most sources agree on) ## CONFLICTING VIEWS (where sources disagree) ## RESEARCH GAPS (what no source adequately covered) ## NEXT STEPS (2-3 actionable follow-up questions)Source summaries: {combined}"""return chat_with_memory(synthesis_prompt)def save_report(report: str, filename: str = "research_report.txt"): """Save the final report to a file.""" os.makedirs("reports", exist_ok=True) path = f"reports/{filename}" with open(path, "w", encoding="utf-8") as f: f.write(report) print(f"\nReport saved to: {path}")

Full Code — Everything Together

Copy the complete research_assistant.py below, add your API key, and run it.

research_assistant.py — COMPLETE FILE FULL CODE
#!/usr/bin/env python3 """ Personal AI Research Assistant Built with Claude API (claude-sonnet-4-20250514) AiBytec.com — Agentic AI Tutorial """import os import requests from bs4 import BeautifulSoup import anthropic from datetime import datetime# Client & memory client = anthropic.Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY")) conversation_history = []def fetch_webpage_content(url: str, max_chars: int = 8000) -> str: try: r = requests.get(url, headers={'User-Agent': 'ResearchBot/1.0'}, timeout=10) soup = BeautifulSoup(r.text, 'html.parser') for tag in soup(['script', 'style', 'nav', 'footer', 'header']): tag.decompose() text = ' '.join(p.get_text(strip=True) for p in soup.find_all('p')) return text[:max_chars] except Exception as e: return f"Error: {str(e)}"def chat_with_memory(user_message: str) -> str: conversation_history.append({"role": "user", "content": user_message}) response = client.messages.create( model="claude-sonnet-4-20250514", max_tokens=1500, system="You are a personal AI research assistant. You maintain full context of this research session and help synthesise findings from multiple sources into clear, actionable reports.", messages=conversation_history ) reply = response.content[0].text conversation_history.append({"role": "assistant", "content": reply}) return replydef summarise_source(url: str, research_question: str) -> str: print(f" Fetching: {url}...") content = fetch_webpage_content(url) prompt = f"""Analyse this web content for my research question: "{research_question}"Source: {url} Content: {content}Provide: FINDINGS — 3-5 bullets relevant to my question INSIGHT — 2-3 sentences of analysis LIMITATIONS — what this source misses""" return chat_with_memory(prompt)def synthesise_and_save(summaries: list, research_question: str): combined = "\n\n---\n\n".join( f"SOURCE {i+1}:\n{s}" for i, s in enumerate(summaries) ) final = chat_with_memory( f"""Synthesise these {len(summaries)} source summaries into a final report for: "{research_question}"Include: Executive Summary, Main Findings, Areas of Agreement, Conflicting Views, Research Gaps, Recommended Next Steps{combined}""" ) os.makedirs("reports", exist_ok=True) filename = f"reports/report_{datetime.now().strftime('%Y%m%d_%H%M')}.txt" with open(filename, "w", encoding="utf-8") as f: f.write(f"RESEARCH QUESTION: {research_question}\n\n") f.write(final) print(f"\nReport saved to: {filename}") return final# MAIN if __name__ == "__main__": print("Personal AI Research Assistant — AiBytec.com") print("=" * 50)research_question = input("\nEnter your research question: ") print("\nEnter source URLs (one per line, blank line when done):")urls = [] while True: url = input(f" URL {len(urls)+1}: ").strip() if not url: break urls.append(url)print(f"\nProcessing {len(urls)} sources...\n") summaries = [summarise_source(url, research_question) for url in urls]print("\nGenerating final synthesis report...\n") report = synthesise_and_save(summaries, research_question) print("\n" + "=" * 50) print(report)# Follow-up questions with full memory print("\nAsk follow-up questions (type 'exit' to quit):") while True: q = input("\nYou: ") if q.lower() == 'exit': break print(f"\nAssistant: {chat_with_memory(q)}")
$ run it
python research_assistant.pyPersonal AI Research Assistant — AiBytec.com ==================================================Enter your research question: What are the best AI agent use cases in 2026?Enter source URLs (one per line, blank line when done): URL 1: https://example.com/article-1 URL 2: https://example.com/article-2 URL 3:Processing 2 sources... Fetching: https://example.com/article-1... Fetching: https://example.com/article-2...Generating final synthesis report... Report saved to: reports/report_20260323_1430.txt

Next Steps & Extensions

You now have a working AI research assistant. Here is how to level it up:

🖥️

Streamlit UI

Wrap the CLI in a Streamlit dashboard with URL input fields and a formatted output panel.

🔎

Auto Web Search

Integrate Tavily or SerpAPI to auto-find sources — no manual URLs needed.

🗄️

Vector Memory (RAG)

Store past reports in ChromaDB or Pinecone for long-term semantic recall.

📄

PDF Input Support

Use Claude's native document API to feed research papers directly — no scraping needed.

"The difference between a basic API call and a true AI agent is memory, structure, and purpose. You now have all three."

You Built a Real AI Agent Today

In 30 minutes you went from zero to a working Personal AI Research Assistant — reading web content, summarising with purpose, remembering context, and delivering reports you can save and act on.

This is exactly the agentic AI skill that separates developers who understand AI from developers who just use AI. Keep building.

🎓

Want to Build More Agents Like This?

Join Certificate 2: Agentic AI Developer at AiBytec — Pakistan's most practical AI course. Real projects. Claude API. OpenAI Agents SDK. FastAPI. LangChain.

Enroll at AiBytec.com →

💡 Found this useful? Share it on LinkedIn and help a fellow developer level up.

#AgenticAI #ClaudeAPI #PythonAI #AIResearchAssistant #ConversationMemory #BuildWithAI #AiBytec

Leave a Comment

Your email address will not be published. Required fields are marked *

Advanced AI solutions for business Chatbot
Chat with AI
Verified by MonsterInsights