A fully autonomous research agent built with OpenAI-Compatible LLMs + LangGraph that:
- Plans research tasks automatically
- Searches the web (Tavily / DuckDuckGo)
- Retrieves from uploaded documents (RAG via ChromaDB)
- Summarises content with map-reduce
- Maintains memory across tasks
- Generates structured Markdown / HTML reports
All free resources — can run entirely locally using Ollama or using free tier cloud APIs like Groq.
User Query
│
▼
┌─────────────┐
│ Planner │ LLM decomposes query → ordered task list
└──────┬──────┘
│
▼
┌─────────────┐ ┌───────────────┐ ┌──────────────┐
│ Executor │◄────────│ Web Search │ │ Doc Retrieval│
│ (ReAct │────────►│ Tavily / DDG │ │ ChromaDB RAG │
│ loop) │ └───────────────┘ └──────────────┘
└──────┬──────┘ ┌───────────────┐ ┌──────────────┐
│ │ Summariser │ │ Memory │
│ │ (Map-Reduce) │ │ (ChromaDB) │
▼ └───────────────┘ └──────────────┘
┌─────────────┐
│ Summariser │ Section-level synthesis
└──────┬──────┘
▼
┌─────────────┐
│ Reporter │ Jinja2 → Markdown + HTML report
└─────────────┘
git clone <this-repo>
cd autonomous_research_agent
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txtcp .env.example .env
# Open .env and set LLM_API_KEY and LLM_BASE_URL
# Optionally set TAVILY_API_KEY for better search qualitystreamlit run app.py
# Open http://localhost:8501# Simple query
python main.py "What are the latest breakthroughs in quantum computing?"
# With local documents
python main.py "Summarise the key arguments in the attached papers" \
--docs paper1.pdf notes.txt
# Save report to custom path
python main.py "AI regulation in the EU" --output my_report.mdautonomous_research_agent/
├── agents/
│ ├── state.py # ResearchState TypedDict
│ ├── planner.py # Planner LangGraph node
│ ├── executor.py # Executor ReAct loop node
│ └── graph.py # Full LangGraph workflow
├── tools/
│ ├── web_search.py # Tavily + DuckDuckGo
│ ├── doc_loader.py # PDF / URL / text ingestion + chunking
│ └── summarizer.py # Map-Reduce summarisation
├── memory/
│ ├── vector_store.py # ChromaDB + sentence-transformers
│ └── agent_memory.py # Agent memory add/query layer
├── report/
│ ├── generator.py # Jinja2 report rendering + save
│ └── templates/
│ └── report_template.md
├── data/ # Auto-created at runtime
│ ├── chroma_db/ # Persistent vector store
│ ├── reports/ # Generated reports
│ └── uploads/ # Saved uploads
├── app.py # Streamlit UI
├── main.py # CLI entry point
├── config.py # Centralised settings
├── requirements.txt
└── .env.example
| Component | Tool | Cost |
|---|---|---|
| LLM | Generic OpenAI / Groq / Ollama | Free / Low Cost |
| Web Search | DuckDuckGo | Free |
| Web Search+ | Tavily API | 1K/mo free |
| Vector DB | ChromaDB (local) | Free |
| Embeddings | sentence-transformers | Free (local) |
| Agent framework | LangGraph (OSS) | Free |
| RAG pipeline | Custom (LlamaIndex-free) | Free |
| Report | Jinja2 + Markdown | Free |
| UI | Streamlit | Free |
| Variable | Default | Description |
|---|---|---|
LLM_API_KEY |
empty | Your API key (optional if using Ollama) |
LLM_BASE_URL |
empty | Base URL (e.g., https://api.groq.com/openai/v1) |
TAVILY_API_KEY |
empty (uses DuckDuckGo) | Optional – better search |
PLANNER_MODEL |
llama-3.1-8b-instant | Model for planning |
EXECUTOR_MODEL |
llama-3.1-8b-instant | Model for execution |
REPORTER_MODEL |
llama-3.1-8b-instant | Model for report generation |
MAX_TASKS_PER_PLAN |
8 | Max sub-tasks per research run |
MAX_SEARCH_RESULTS |
5 | Results per web search |
CHUNK_SIZE |
500 | Words per document chunk |
CHUNK_OVERLAP |
50 | Overlap between chunks |
- Create
tools/my_tool.pywith a function that returnsstr. - In
agents/executor.py, add a newelif task["type"] == "my_tool":branch. - In
agents/planner.py, add"my_tool"to the valid types in the system prompt.
Set PLANNER_MODEL, EXECUTOR_MODEL, or REPORTER_MODEL in .env to any
supported model string (e.g. llama-3.3-70b-versatile for Groq, or llama3 for Ollama).
Replace the chromadb.PersistentClient in memory/vector_store.py with
chromadb.HttpClient(host=..., port=...) or swap in Pinecone / Weaviate.
MIT — use freely.
