An end-to-end Agentic AI application built with the ReAct (Reason + Act) framework - capable of managing your Notion workspace (notes & calendar) and fetching real-time weather, all through a natural language chat interface. Deployed on AWS EC2 via Docker and automated with GitHub Actions CI/CD.
ReAct is a modern agentic AI paradigm that combines chain-of-thought reasoning with tool-use action loops. Instead of a single-shot LLM response, the agent follows a structured cognitive loop:
Thought β Action β Observation β Thought β Action β ... β Final Answer
| Step | What happens |
|---|---|
| Thought | The LLM reasons about what it needs to do next |
| Action | It selects and calls the appropriate tool |
| Observation | It receives the tool's output |
| Repeat | It reasons again based on that output |
| Final Answer | It synthesises everything into a natural language response |
This approach allows the agent to break complex multi-step requests into individual tool calls, chain them together intelligently, and explain its reasoning β far beyond what a basic prompt-response LLM can achieve.
ReAct_Agent/
β
βββ agent/
β βββ bot.py # Agent core: LLM + tool registration
β
βββ api/
β βββ server.py # FastAPI server with /chat and /health endpoints
β
βββ tools/
β βββ weather.py # Weather tool (Open-Meteo API)
β βββ notion_notes.py # Notes CRUD tools (Notion API)
β βββ notion_calender.py # Calendar CRUD tools (Notion API)
β
βββ static/
β βββ index.html # Chat UI frontend
β βββ style.css # Styling
β βββ script.js # Frontend logic
β
βββ utils/
β βββ logger.py # Structured application logger
β
βββ assets/ # Screenshots for documentation
βββ Dockerfile # Container build instructions
βββ docker-compose.yml # Local container orchestration
βββ requirements.txt # Python dependencies
βββ main.py # Application entrypoint
βββ .github/workflows/
βββ deploy.yml # GitHub Actions CI/CD pipeline
Full CRUD operations on your Notion notes database via natural language:
| Tool | What it does |
|---|---|
get_notes |
Fetch all notes β returns title and status (Pending / Done) |
add_note |
Create a new note (defaulted to Pending status) |
update_note_status |
Change a note's status to Pending or Done |
delete_note |
Archive (remove) a note by title β partial match supported |
Full CRUD operations on your Notion calendar database:
| Tool | What it does |
|---|---|
get_calendar_events(date) |
Fetch events for a specific date (YYYY-MM-DD) |
get_all_calendar_events |
Fetch all events, sorted by date ascending |
add_calendar_event |
Add event β auto-sets status to Upcoming or Done based on date |
update_calendar_event |
Update any combination of name, date, time, or status |
Valid calendar statuses: Upcoming Β· Done Β· Cancelled
| Tool | What it does |
|---|---|
get_weather(city) |
Fetches current temperature for any city using the free Open-Meteo API β no API key required |
The tool performs a two-step call: first geocodes the city name to coordinates, then fetches live weather data.
User (Browser)
β
βΌ
ββββββββββββββββββββββββββββββββββββ
β FastAPI Server β
β POST /chat GET /health β
β Static UI served at / β
ββββββββββββββββ¬ββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββ
β ReAct Agent Core β
β LLM: Groq (llama3-70b-8192) β
β Framework: LangGraph β
β create_react_agent() β
ββββββββ¬βββββββββββββββββββββ¬βββββββ
β β
βΌ βΌ
βββββββββββββββ βββββββββββββββββββββββ
β Weather β β Notion API β
β Tool β β Notes + Calendar β
β (Open-Meteo)β β (REST v1 API) β
βββββββββββββββ βββββββββββββββββββββββ
- LangGraph
create_react_agentβ handles the full Thought β Action β Observation loop automatically @tooldecorator β each tool is self-describing; the agent reads the docstring to decide when and how to use it- Global agent singleton β the agent is initialised once at FastAPI startup via
@app.on_event("startup")for performance - Partial match search β note and calendar tools use Notion's
containsfilter so users don't need to type exact names - Auto-status on date β calendar tools automatically set
Upcoming/Donebased on whether the event date is in the future or past
| Layer | Technology |
|---|---|
| LLM | Groq β ultra-fast inference |
| Agent Framework | LangGraph β stateful agentic workflows |
| LLM Toolkit | LangChain β tools, prompts, and chain abstractions |
| API Backend | FastAPI β async Python REST API |
| API Server | Uvicorn β ASGI server |
| Frontend | Vanilla HTML / CSS / JavaScript |
| Data Sources | Notion API Β· Open-Meteo |
| Containerization | Docker + Docker Compose |
| Container Registry | GitHub Container Registry (GHCR) |
| Cloud Hosting | AWS EC2 |
| CI/CD | GitHub Actions |
| Package Manager | uv β ultra-fast Python package installer |
| Logging | Python logging with structured stdout formatter |
Here's what happens when a user sends: "What are my pending notes and what's the weather in New York?"
1. User sends message via chat UI
βββΆ POST /chat { "message": "..." }
2. FastAPI passes message to the ReAct agent
3. Agent THINKS:
"I need to fetch notes AND weather. Two tool calls needed."
4. Agent ACTS β calls get_notes()
βββΆ Notion API returns: [{"note": "Buy groceries", "status": "Pending"}, ...]
5. Agent OBSERVES the result, THINKS again:
"Got notes. Now fetch weather."
6. Agent ACTS β calls get_weather("New York")
βββΆ Open-Meteo API returns: {"city": "New York", "temp": 3.2, "unit": "C"}
7. Agent OBSERVES, THINKS:
"I have all the information. I can now give a final answer."
8. Agent generates a natural language response combining both results
9. FastAPI returns { "response": "..." } to the browser
The entire loop is powered by LangGraph's prebuilt ReAct agent, which manages the state machine, tool dispatch, and response synthesis without any custom orchestration code.
# Clone the repo
git clone https://github.com/LeelaKarthik-26/ReAct_Agent.git
cd ReAct_Agent
# Create .env file (see Environment Variables section)
cp .env.example .env # fill in your API keys
# Run with Docker Compose
docker-compose up --build
# Visit
open http://localhost:8000FROM python:3.12-slim
WORKDIR /app
RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
RUN pip install uv
COPY requirements.txt .
RUN uv pip install --system -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "main.py"]- Uses
python:3.12-slimfor a minimal image footprint - Uses
uvinstead ofpipfor dramatically faster dependency resolution - Multi-stage-friendly structure (copy requirements before source for Docker layer caching)
Every push to master triggers the full pipeline automatically:
Push to master
β
βΌ
βββββββββββββββββββββββββββββββ
β Job 1: build-and-push β
β βββββββββββββββββββββββββ β
β 1. Checkout code β
β 2. Login to GHCR β
β 3. Build Docker image β
β 4. Push β ghcr.io/... β
ββββββββββββ¬βββββββββββββββββββ
β (needs: build-and-push)
βΌ
βββββββββββββββββββββββββββββββ
β Job 2: deploy β
β βββββββββββββββββββββββββ β
β 1. SSH into AWS EC2 β
β 2. docker stop old containerβ
β 3. docker pull new image β
β 4. docker run with env varsβ
βββββββββββββββββββββββββββββββ
Zero-downtime rolling deploy β the old container is stopped, removed, and replaced with the new image in under 30 seconds.
| Variable | Description |
|---|---|
GROQ_API_KEY |
API key from console.groq.com |
NOTION_API_KEY |
Notion integration token from notion.so/my-integrations |
NOTION_NOTES_DB_ID |
ID of your Notion notes database |
NOTION_CALENDAR_DB_ID |
ID of your Notion calendar database |
β οΈ Never commit your.envfile. It is listed in.gitignore.
| Method | Endpoint | Description |
|---|---|---|
GET |
/ |
Serves the chat UI (static frontend) |
POST |
/chat |
Send a message to the agent |
GET |
/health |
Health check β returns {"status": "ok"} |
// POST /chat
{
"message": "What are my upcoming events this week?",
"history": []
}
// Response
{
"response": "You have 2 upcoming events this week: ..."
}User: "Add a note to call the dentist"
Agent: "Added note 'Call the dentist' with status Pending β
"
User: "What are my notes?"
Agent: "You have 3 notes:
- Call the dentist (Pending)
- Buy groceries (Pending)
- Read LangGraph docs (Done)"
User: "Mark 'Buy groceries' as done"
Agent: "Updated note 'Buy groceries' status to Done β
"
User: "Schedule a team meeting on March 10th at 10:00"
Agent: "Added Event: 'Team meeting' at 10:00 on 2026-03-10 with status 'Upcoming' β
"
User: "What's the weather in London?"
Agent: "The current temperature in London is 8.4Β°C."
User: "Cancel the team meeting"
Agent: "Updated event 'Team meeting': status β 'Cancelled' β
"
# 1. Clone
git clone https://github.com/LeelaKarthik-26/ReAct_Agent.git
cd ReAct_Agent
# 2. Create virtual environment
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 3. Install dependencies
pip install uv
uv pip install -r requirements.txt
# 4. Set up .env with your API keys
# 5. Run
python main.py
# 6. Open browser
open http://localhost:8000| Concept | Reference |
|---|---|
| ReAct Prompting | ReAct: Synergizing Reasoning and Acting in Language Models (Yao et al., 2022) |
| LangGraph Agents | LangGraph Docs β Prebuilt ReAct Agent |
| Agentic Workflows | Andrew Ng β Agentic Design Patterns |
| Notion API | Notion Developers Documentation |
| Open-Meteo | Open-Meteo Free Weather API |
- β End-to-end production system β not a notebook demo; it's a containerised, deployed, live application
- β Real agentic reasoning β the agent dynamically decides which tools to call and in what order
- β Full CI/CD pipeline β code pushed to GitHub automatically builds, pushes to GHCR, and deploys to AWS
- β Clean tool architecture β each tool is a self-contained, documented, independently testable function
- β Real-world integrations β Notion API, Open-Meteo API, Groq LLM
- β Production patterns β structured logging, startup lifecycle hooks, error handling, graceful Docker restarts
LeelaKarthik Devisetty
AI/ML Engineer Β· Building intelligent agentic systems
Built with π§ LangGraph Β· β‘ Groq Β· π³ Docker Β· βοΈ AWS EC2



