Build an AI Chatbot in Golang with OpenAI GPT and WebSockets

by Didin J. on Sep 18, 2025 Build an AI Chatbot in Golang with OpenAI GPT and WebSockets

Build a real-time AI chatbot in Golang with OpenAI GPT and WebSockets. Step-by-step guide with server, client, streaming responses, and production tips.

In this tutorial, we’ll walk through building a real-time AI chatbot in Go (Golang) that uses WebSockets for low-latency client communication and OpenAI GPT for generating intelligent responses.

Instead of waiting for full responses, we’ll implement streaming, so your chatbot feels fast and interactive — responses appear as they’re generated, token by token.

By the end, you’ll have:

  • A Go WebSocket server that relays user messages to OpenAI GPT and streams responses back.

  • A browser client with live chat UI powered by HTML and JavaScript.

  • A simple but extendable architecture for multi-user real-time AI apps.

Prerequisites

Before starting, make sure you have:

  • Go 1.20+ is installed on your system.

  • An OpenAI API key (set as OPENAI_API_KEY).

  • Basic knowledge of Go, WebSockets, and JavaScript.

We’ll use the following Go packages:

  • gorilla/websocket – WebSocket server library.

  • sashabaranov/go-openai – popular Go client for OpenAI API.


Project Setup

Create a new folder and initialize a Go module:

mkdir go-ai-chatbot
cd go-ai-chatbot
go mod init github.com/yourusername/go-ai-chatbot
go get github.com/gorilla/websocket
go get github.com/sashabaranov/go-openai

Project structure:

go-ai-chatbot/
├─ cmd/
│  └─ server/main.go
├─ web/
│  └─ index.html
├─ go.mod
└─ README.md


Step 1: Go to the WebSocket Server

Create cmd/server/main.go:

package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"time"

	"github.com/gorilla/websocket"
	openai "github.com/sashabaranov/go-openai"
)

var upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool { return true },
}

type WSMessage struct {
	Type    string `json:"type"`
	Payload string `json:"payload"`
}

func main() {
	apiKey := os.Getenv("OPENAI_API_KEY")
	if apiKey == "" {
		log.Fatal("OPENAI_API_KEY env var is required")
	}

	client := openai.NewClient(apiKey)

	http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
		handleWS(w, r, client)
	})

	fs := http.FileServer(http.Dir("./web"))
	http.Handle("/", fs)

	addr := ":8080"
	log.Printf("Server running at %s", addr)
	log.Fatal(http.ListenAndServe(addr, nil))
}

func handleWS(w http.ResponseWriter, r *http.Request, client *openai.Client) {
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println("Upgrade error:", err)
		return
	}
	defer conn.Close()

	ctx := context.Background()

	for {
		var msg WSMessage
		if err := conn.ReadJSON(&msg); err != nil {
			log.Println("ReadJSON error:", err)
			return
		}

		if msg.Type == "user_message" {
			go handleUserMessage(ctx, conn, client, msg.Payload)
		}
	}
}

func handleUserMessage(ctx context.Context, conn *websocket.Conn, client *openai.Client, userText string) {
	req := openai.ChatCompletionRequest{
		Model: openai.GPT3Dot5Turbo,
		Messages: []openai.ChatCompletionMessage{
			{Role: "system", Content: "You are a helpful assistant."},
			{Role: "user", Content: userText},
		},
		Stream: true,
	}

	stream, err := client.CreateChatCompletionStream(ctx, req)
	if err != nil {
		sendError(conn, fmt.Sprintf("Stream error: %v", err))
		return
	}
	defer stream.Close()

	for {
		response, err := stream.Recv()
		if err != nil {
			if err == io.EOF {
				_ = conn.WriteJSON(WSMessage{Type: "ai_done", Payload: ""})
				return
			}
			sendError(conn, fmt.Sprintf("Recv error: %v", err))
			return
		}

		if len(response.Choices) > 0 {
			delta := response.Choices[0].Delta.Content
			if delta != "" {
				_ = conn.WriteJSON(WSMessage{Type: "ai_delta", Payload: delta})
			}
		}
	}
}

func sendError(conn *websocket.Conn, text string) {
	_ = conn.WriteJSON(WSMessage{Type: "error", Payload: text})
	time.Sleep(50 * time.Millisecond)
}


Step 2: Browser Client

Create web/index.html:

<!doctype html>
<html>
<head>
  <meta charset="utf-8" />
  <title>Go AI Chatbot</title>
  <style>
    body { font-family: sans-serif; margin: 20px; }
    #log { white-space: pre-wrap; border: 1px solid #ccc; padding: 12px; height: 300px; overflow:auto; }
  </style>
</head>
<body>
  <h1>AI Chatbot (Go + WebSocket)</h1>
  <div id="log"></div>
  <input id="input" placeholder="Type a message..." style="width:70%" />
  <button id="send">Send</button>

  <script>
    const log = document.getElementById('log');
    const input = document.getElementById('input');
    const sendBtn = document.getElementById('send');

    const ws = new WebSocket(`${location.origin.replace(/^http/, "ws")}/ws`);
    ws.onopen = () => appendLog("[connected]\n");
    ws.onmessage = (ev) => {
      const msg = JSON.parse(ev.data);
      if (msg.type === "ai_delta") {
        appendLog(msg.payload);
      } else if (msg.type === "ai_done") {
        appendLog("\n\n[response complete]\n\n");
      } else if (msg.type === "error") {
        appendLog("\n[ERROR] " + msg.payload + "\n");
      }
    };

    sendBtn.onclick = sendMessage;
    input.addEventListener("keydown", (e) => { if (e.key === "Enter") sendMessage(); });

    function sendMessage() {
      const text = input.value.trim();
      if (!text) return;
      appendLog("\nYou: " + text + "\n");
      ws.send(JSON.stringify({ type: "user_message", payload: text }));
      input.value = "";
    }

    function appendLog(s) {
      log.textContent += s;
      log.scrollTop = log.scrollHeight;
    }
  </script>
</body>
</html>


Step 3: Run and Test

Run the server:

export OPENAI_API_KEY="sk-..."
go run ./cmd/server

Open a browser at http://localhost:8080.
Type a message and watch as the chatbot streams responses live.

Screenshot suggestions for your article:

  • Terminal running the Go server.

  • Browser showing the chat UI.

  • Streaming response in real-time.


Step 4: Improvements

  • Store conversation history per user.

  • Add authentication (e.g., JWT).

  • Use Redis/Postgres for persistence.

  • Deploy behind Nginx with TLS.

  • Add text-to-speech (TTS) or speech-to-text (STT) for a voice-enabled chatbot.


Conclusion

We’ve built a fully functional real-time AI chatbot in Go using WebSockets and OpenAI GPT. This setup ensures low-latency communication and smooth, streaming responses.

With this foundation, you can expand to multi-user support, persistent memory, or even integrate into mobile and desktop clients.

You can find the full source code on our GitHub.

That is just the basics. If you need more deep learning about the Golang (Go) language and frameworks, you can take the following cheap course:

Thanks!