diff --git a/ai_agent_tutorials/ai_tic_tac_toe_agent/README.md b/ai_agent_tutorials/ai_tic_tac_toe_agent/README.md
new file mode 100644
index 0000000..2da034f
--- /dev/null
+++ b/ai_agent_tutorials/ai_tic_tac_toe_agent/README.md
@@ -0,0 +1,68 @@
+# AI vs AI Tic-Tac-Toe Game 🎮
+
+An interactive Tic-Tac-Toe game where two AI agents powered by different language models compete against each other built on phidata Agent Framework and Streamlit as UI. Watch as GPT-4O battles against either DeepSeek V3 or Google's Gemini 1.5 Flash in this classic game!
+
+## Features 🌟
+
+- Player X: Powered by OpenAI's GPT-4o (o1 models as api is yet to roll out for tier)
+- Player O: Choice between DeepSeek AI or Google's Gemini
+- Interactive game board using Streamlit
+- Real-time move visualization
+- AI Judge to determine game outcomes
+- Clean and intuitive user interface
+
+## Prerequisites 📋
+
+- Python 3.8+
+- OpenAI API key
+- Either DeepSeek API key or Google API key (for Player O)
+
+## How to Run 🚀
+
+1. **Setup Environment**
+ ```bash
+ # Clone the repository
+ git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
+ cd ai_agent_tutorials/ai_tic_tac_toe_agent
+
+ # Install dependencies
+ pip install -r requirements.txt
+ ```
+
+2. **Configure API Keys**
+ - Get OpenAI API key from [OpenAI Platform](https://platform.openai.com)
+ - Get Google API key from [Google AI Studio](https://aistudio.google.com) (if using Gemini)
+ - Get DeepSeek API key from DeepSeek platform [Deepseek platform](https://www.deepseek.com) (if using DeepSeek v3 model)
+
+4. **Run the Application**
+ ```bash
+ streamlit run ai_tic_tac_toe_agent.py
+ ```
+
+5. **Using the Interface**
+ - Enter your API keys in the sidebar
+ - Click "Start Game" to begin
+ - Watch as the AI agents battle it out!
+ - Monitor the game progress and final results
+
+## Game Components 🎯
+
+- **Game Board**
+ - 3x3 interactive grid
+ - Real-time move visualization
+ - Clear symbol placement (X/O)
+
+- **AI Players**
+ - Player X (GPT-4o): Strategic offensive moves
+ - Player O (DeepSeek/Gemini): Defensive countermoves since this agent started later
+ - AI Judge: Game outcome validation
+
+- **Game Flow**
+ - Alternating turns between AIs
+ - Move validation and error handling
+ - Winner determination
+ - Draw detection
+
+## Disclaimer ⚠️
+
+This is a demonstration project showcasing AI capabilities in game playing. API costs will apply based on your usage of the OpenAI, DeepSeek, or Google APIs.
diff --git a/ai_agent_tutorials/ai_tic_tac_toe_agent/ai_tic_tac_toe_agent.py b/ai_agent_tutorials/ai_tic_tac_toe_agent/ai_tic_tac_toe_agent.py
new file mode 100644
index 0000000..67d32f4
--- /dev/null
+++ b/ai_agent_tutorials/ai_tic_tac_toe_agent/ai_tic_tac_toe_agent.py
@@ -0,0 +1,273 @@
+import re
+import streamlit as st
+from phi.agent import Agent
+from phi.model.openai import OpenAIChat
+from phi.model.deepseek import DeepSeekChat
+from phi.model.google import Gemini
+
+# Streamlit App Title
+st.title("🤖 Tic-Tac-Toe: AI vs AI")
+
+# Enhanced Welcome Message
+with st.chat_message("assistant"):
+ st.markdown("""
+ **Welcome to the Tic-Tac-Toe AI Battle!** 🎮
+ This project pits two advanced AI agents against each other in a classic game of Tic-Tac-Toe.
+ Here's what you need to know:
+ """)
+ st.info("""
+ - **Player X**: Powered by OpenAI's GPT-4.
+ - **Player O**: Powered by DeepSeek's AI or Google's Gemini (if DeepSeek API key is not provided).
+ - **How to Play**: Enter your API keys in the sidebar, click **Start Game**, and watch the AI battle it out!
+ - **Goal**: The first player to get three of their symbols in a row (horizontally, vertically, or diagonally) wins.
+ - **Draw**: If the board fills up without a winner, the game ends in a draw.
+ """)
+ st.markdown("Ready to see who wins? Click the **Start Game** button below! 🚀")
+
+# Initialize the game board in session state
+if 'board' not in st.session_state:
+ st.session_state.board = [[None, None, None],
+ [None, None, None],
+ [None, None, None]]
+
+# Function to display the board with better styling
+def display_board(board):
+ st.markdown("""
+
+ """, unsafe_allow_html=True)
+
+ st.write("Current Board:")
+ board_html = '
'
+ for row in board:
+ for cell in row:
+ cell_value = cell if cell is not None else " "
+ board_html += f'
{cell_value}
'
+ board_html += '
'
+ st.markdown(board_html, unsafe_allow_html=True)
+
+# Function to get the board state as a string
+def get_board_state(board):
+ rows = []
+ for i, row in enumerate(board):
+ row_str = " | ".join([f"({i},{j}) {cell or ' '}" for j, cell in enumerate(row)])
+ rows.append(f"Row {i}: {row_str}")
+ return "\n".join(rows)
+
+# Function to check for a winner
+def check_winner(board):
+ # Check rows
+ for row in board:
+ if row[0] == row[1] == row[2] and row[0] is not None:
+ return row[0]
+ # Check columns
+ for col in range(3):
+ if board[0][col] == board[1][col] == board[2][col] and board[0][col] is not None:
+ return board[0][col]
+ # Check diagonals
+ if board[0][0] == board[1][1] == board[2][2] and board[0][0] is not None:
+ return board[0][0]
+ if board[0][2] == board[1][1] == board[2][0] and board[0][2] is not None:
+ return board[0][2]
+ # Check for draw
+ if all(cell is not None for row in board for cell in row):
+ return "Draw"
+ return None
+
+# Sidebar for API keys
+st.sidebar.header("API Keys")
+openai_api_key = st.sidebar.text_input("Enter your OpenAI API Key", type="password")
+deepseek_api_key = st.sidebar.text_input("Enter your DeepSeek API Key", type="password")
+google_api_key = st.sidebar.text_input("Enter your Google API Key (for Gemini)", type="password")
+
+if openai_api_key:
+ st.session_state.openai_api_key = openai_api_key
+if deepseek_api_key:
+ st.session_state.deepseek_api_key = deepseek_api_key
+if google_api_key:
+ st.session_state.google_api_key = google_api_key
+
+# Initialize agents if API keys are provided
+if 'openai_api_key' in st.session_state:
+ player_x = Agent(
+ name="Player X",
+ model=OpenAIChat(id="gpt-4o", temperature=0.1, api_key=st.session_state.openai_api_key),
+ instructions=[
+ "You are a Tic-Tac-Toe player using the symbol 'X'.",
+ "Your opponent is using the symbol 'O'. Block their potential winning moves.",
+ "Make your move in the format 'row, col' based on the current board state.",
+ "Strategize to win by placing your symbol in a way that blocks your opponent from forming a straight line.",
+ "Do not include any explanations or extra text. Only provide the move.",
+ "Row and column indices start from 0.",
+ ],
+ markdown=True,
+ )
+
+ # Initialize Player O with DeepSeek or Google Gemini
+ if 'deepseek_api_key' in st.session_state:
+ player_o = Agent(
+ name="Player O",
+ model=DeepSeekChat(api_key=st.session_state.deepseek_api_key),
+ instructions=[
+ "You are a Tic-Tac-Toe player using the symbol 'O'.",
+ "Your opponent is using the symbol 'X'. Block their potential winning moves.",
+ "Make your move in the format 'row, col' based on the current board state.",
+ "Strategize to win by placing your symbol in a way that blocks your opponent from forming a straight line.",
+ "Do not include any explanations or extra text. Only provide the move.",
+ "Row and column indices start from 0.",
+ ],
+ markdown=True,
+ )
+ elif 'google_api_key' in st.session_state:
+ player_o = Agent(
+ name="Player O",
+ model=Gemini(id="gemini-1.5-flash", api_key=st.session_state.google_api_key),
+ instructions=[
+ "You are a Tic-Tac-Toe player using the symbol 'O'.",
+ "Your opponent is using the symbol 'X'. Block their potential winning moves.",
+ "Make your move in the format 'row, col' based on the current board state.",
+ "Strategize to win by placing your symbol in a way that blocks your opponent from forming a straight line.",
+ "Do not include any explanations or extra text. Only provide the move.",
+ "Row and column indices start from 0.",
+ ],
+ markdown=True,
+ )
+ else:
+ st.warning("Please provide either a DeepSeek API key or a Google API key for Player O.")
+
+ judge = Agent(
+ name="Judge",
+ model=OpenAIChat(id="gpt-4o", temperature=0.1, api_key=st.session_state.openai_api_key),
+ instructions=[
+ "You are the judge of a Tic-Tac-Toe game.",
+ "The board is presented as rows with positions separated by '|'.",
+ "Rows are labeled from 0 to 2, and columns from 0 to 2.",
+ "Example board state:",
+ "Row 0: (0,0) X | (0,1) | (0,2) O",
+ "Row 1: (1,0) O | (1,1) X | (1,2) X",
+ "Row 2: (2,0) X | (2,1) O | (2,2) O",
+ "Determine the winner based on this board state.",
+ "The winner is the player with three of their symbols in a straight line (row, column, or diagonal).",
+ "If the board is full and there is no winner, declare a draw.",
+ "Provide only the result (e.g., 'Player X wins', 'Player O wins', 'Draw').",
+ ],
+ markdown=True,
+ )
+
+ # Function to extract the move from the agent's response
+ def extract_move(response):
+ content = response.content.strip()
+ match = re.search(r'\d\s*,\s*\d', content)
+ if match:
+ move = match.group().replace(' ', '')
+ return move
+ numbers = re.findall(r'\d+', content)
+ if len(numbers) >= 2:
+ row = int(numbers[0])
+ col = int(numbers[1])
+ return f"{row},{col}"
+ return None
+
+ # Game loop
+ def play_game():
+ if 'current_player' not in st.session_state:
+ st.session_state.current_player = player_x
+ if 'symbol' not in st.session_state:
+ st.session_state.symbol = "X"
+ if 'move_count' not in st.session_state:
+ st.session_state.move_count = 0
+
+ max_moves = 9
+ winner = None # Initialize winner variable
+
+ while st.session_state.move_count < max_moves:
+ # Display the board
+ display_board(st.session_state.board)
+
+ # Prepare the board state for the agent
+ board_state = get_board_state(st.session_state.board)
+ move_prompt = (
+ f"Current board state:\n{board_state}\n"
+ f"{st.session_state.current_player.name}'s turn. Make your move in the format 'row, col'."
+ )
+
+ # Get the current player's move
+ with st.chat_message("assistant"):
+ st.write(f"**{st.session_state.current_player.name}'s turn:**")
+ move_response = st.session_state.current_player.run(move_prompt)
+ st.code(f"Agent {st.session_state.current_player.name} response:\n{move_response.content}", language="markdown")
+ move = extract_move(move_response)
+ st.write(f"**Extracted move:** {move}")
+
+ if move is None:
+ st.error("Invalid move! Please use the format 'row, col'.")
+ continue
+
+ try:
+ row, col = map(int, move.split(','))
+ if st.session_state.board[row][col] is not None:
+ st.error("Invalid move! Cell already occupied.")
+ continue
+ st.session_state.board[row][col] = st.session_state.symbol
+ except (ValueError, IndexError):
+ st.error("Invalid move! Please use the format 'row, col'.")
+ continue
+
+ # Check for a winner or draw
+ winner = check_winner(st.session_state.board)
+ if winner:
+ break # Exit the loop if there's a winner
+
+ # Switch players
+ st.session_state.current_player = player_o if st.session_state.current_player == player_x else player_x
+ st.session_state.symbol = "O" if st.session_state.symbol == "X" else "X"
+ st.session_state.move_count += 1
+
+ # After the game loop, display the final board and involve the judge agent
+ st.write("**Final Board:**")
+ display_board(st.session_state.board)
+
+ if winner:
+ st.success(f"**Result:** {winner}")
+ else:
+ st.success("**Result:** Draw")
+
+ # Judge's announcement
+ st.write("\n**Game Over. Judge is determining the result...**")
+ st.write("**Final board state passed to judge:**")
+ st.code(get_board_state(st.session_state.board), language="markdown")
+ judge_prompt = (
+ f"Final board state:\n{get_board_state(st.session_state.board)}\n"
+ f"Determine the winner and announce the result."
+ )
+ judge_response = judge.run(judge_prompt)
+ st.code(f"Judge's raw response:\n{judge_response.content}", language="markdown")
+ announcement = judge_response.content.strip()
+ st.success(f"**Judge's Announcement:** {announcement}")
+
+ # Start Game Button
+ if st.button("Start Game"):
+ st.session_state.board = [[None, None, None],
+ [None, None, None],
+ [None, None, None]]
+ st.session_state.current_player = player_x
+ st.session_state.symbol = "X"
+ st.session_state.move_count = 0
+ play_game()
+else:
+ st.warning("Please enter your OpenAI API key and either Deepseek/Gemini API key to start the game.")
\ No newline at end of file
diff --git a/ai_agent_tutorials/ai_tic_tac_toe_agent/requirements.txt b/ai_agent_tutorials/ai_tic_tac_toe_agent/requirements.txt
new file mode 100644
index 0000000..4129d50
--- /dev/null
+++ b/ai_agent_tutorials/ai_tic_tac_toe_agent/requirements.txt
@@ -0,0 +1,4 @@
+streamlit==1.41.1
+phidata==2.7.3
+openai==1.58.1
+google-generativeai==0.8.3