Khi bạn sử dụng ChatGPT hay Claude, chắc hẳn bạn đã thấy text xuất hiện từng ký tự một, như thể có người đang gõ phím thật sự. Đó gọi là streaming response (phản hồi truyền trực tuyến) hay hiệu ứng typewriter. Trong bài viết này, mình sẽ hướng dẫn bạn cách implement tính năng này trong n8n workflow một cách dễ hiểu nhất, dù bạn chưa từng đụng đến code.

Tại sao nên dùng n8n + HolySheep AI?

Trước khi đi vào chi tiết, mình muốn chia sẻ lý do mình chọn combo này:

Streaming Response là gì?

Để đơn giản nhất: thay vì chờ AI trả lời xong rồi hiển thị toàn bộ (có thể mất vài giây), streaming cho phép nhận từng phần câu trả lời ngay khi AI generate. Người dùng thấy text xuất hiện dần dần, trải nghiệm tự nhiên hơn nhiều.

Chuẩn bị trước khi bắt đầu

Bước 1: Lấy API Key từ HolySheep AI

Sau khi đăng ký tài khoản HolySheep AI, bạn vào Dashboard > API Keys > Create New Key. Copy key đó lại, giữ kỹ như mật khẩu. Nếu chưa rõ, cứ xem ảnh chụp màn hình bên dưới:

YOUR_HOLYSHEEP_API_KEY

Bảng giá tham khảo (cập nhật 2026):

Bước 2: Tạo Workflow cơ bản trong n8n

Mình sẽ hướng dẫn tạo workflow đơn giản nhất trước. Sau đó mới thêm tính năng streaming.

2.1. Thêm node HTTP Request

Trong n8n, click + > tìm HTTP Request > kéo vào canvas.

2.2. Cấu hình Request

{
  "url": "https://api.holysheep.ai/v1/chat/completions",
  "method": "POST",
  "authentication": "genericCredentialType",
  "genericAuthType": "httpHeaderAuth",
  "sendHeaders": true,
  "headerParameters": {
    "parameters": [
      {
        "name": "Authorization",
        "value": "Bearer YOUR_HOLYSHEEP_API_KEY"
      },
      {
        "name": "Content-Type",
        "value": "application/json"
      }
    ]
  },
  "sendBody": true,
  "bodyParameters": {
    "parameters": [
      {
        "name": "model",
        "value": "deepseek-v3.2"
      },
      {
        "name": "messages",
        "value": "[{\"role\": \"user\", \"content\": \"Xin chào, hãy kể cho tôi nghe về bạn\"}]"
      },
      {
        "name": "stream",
        "value": true
      }
    ]
  }
}

Bước 3: Xử lý Stream Response

Đây là phần quan trọng nhất. Khi bạn bật stream: true, API sẽ trả về dữ liệu theo định dạng Server-Sent Events (SSE). Mỗi chunk sẽ chứa một phần nhỏ text, thường là vài ký tự.

3.1. Thêm node Code để parse SSE

Thêm node Code sau HTTP Request:

// JavaScript xử lý SSE stream từ HolySheep AI
// Dữ liệu nhận vào là text dạng SSE, ta cần tách từng chunk

const responseData = $input.item.json.data;
const lines = responseData.split('\n');

let fullText = '';
const chunks = [];

for (const line of lines) {
  if (line.startsWith('data: ')) {
    const jsonStr = line.slice(6); // Bỏ "data: "
    
    if (jsonStr === '[DONE]') {
      break;
    }
    
    try {
      const chunk = JSON.parse(jsonStr);
      const content = chunk.choices?.[0]?.delta?.content;
      
      if (content) {
        fullText += content;
        chunks.push({
          text: content,
          fullResponse: fullText
        });
      }
    } catch (e) {
      // Bỏ qua JSON parse error
    }
  }
}

return {
  json: {
    fullText: fullText,
    chunks: chunks,
    chunkCount: chunks.length
  }
};

Bước 4: Tạo Webhook để hiển thị real-time

Để người dùng thấy được hiệu ứng typewriter, bạn cần một webhook trả về từng chunk. Cấu hình n8n workflow như sau:

4.1. Cấu trúc Workflow hoàn chỉnh

┌─────────────┐
│  Webhook    │ ← Trigger endpoint
└──────┬──────┘
       │
┌──────▼──────┐
│ HTTP Request│ ← Gọi HolySheep AI stream
└──────┬──────┘
       │
┌──────▼──────┐
│ Code        │ ← Parse SSE chunks
└──────┬──────┘
       │
┌──────▼──────┐
│ Respond    │ ← Trả về cho frontend
└─────────────┘

4.2. Code xử lý stream hoàn chỉnh

// n8n Code node - Xử lý streaming response hoàn chỉnh
// Tích hợp HolySheep AI với base_url chuẩn

const HOLYSHEEP_API_KEY = 'YOUR_HOLYSHEEP_API_KEY';
const BASE_URL = 'https://api.holysheep.ai/v1';

// Lấy user message từ webhook
const userMessage = $input.item.json.body?.message || 'Xin chào';

const response = await fetch(${BASE_URL}/chat/completions, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': Bearer ${HOLYSHEEP_API_KEY}
  },
  body: JSON.stringify({
    model: 'deepseek-v3.2',  // Model rẻ nhất, $0.42/MTok
    messages: [{ role: 'user', content: userMessage }],
    stream: true
  })
});

const reader = response.body.getReader();
const decoder = new TextDecoder();
let fullText = '';
let chunkCount = 0;
const chunks = [];

while (true) {
  const { done, value } = await reader.read();
  
  if (done) break;
  
  const chunk = decoder.decode(value);
  const lines = chunk.split('\n');
  
  for (const line of lines) {
    if (line.startsWith('data: ')) {
      const jsonStr = line.slice(6);
      
      if (jsonStr === '[DONE]') continue;
      
      try {
        const data = JSON.parse(jsonStr);
        const content = data.choices?.[0]?.delta?.content;
        
        if (content) {
          fullText += content;
          chunkCount++;
          chunks.push({
            index: chunkCount,
            text: content,
            timestamp: new Date().toISOString()
          });
        }
      } catch (e) {
        // Ignore parse errors
      }
    }
  }
}

// Trả về kết quả cho node tiếp theo
return {
  json: {
    success: true,
    userMessage: userMessage,
    fullResponse: fullText,
    chunks: chunks,
    stats: {
      totalChunks: chunkCount,
      totalLength: fullText.length,
      avgChunkSize: (fullText.length / chunkCount).toFixed(2)
    }
  }
};

Bước 5: Frontend để hiển thị Typewriter Effect

Để có hiệu ứng đẹp mắt, bạn cần code frontend. Dưới đây là ví dụ HTML đơn giản:

<!DOCTYPE html>
<html lang="vi">
<head>
  <meta charset="UTF-8">
  <title>AI Typewriter Demo - HolySheep AI</title>
  <style>
    #chat-container {
      max-width: 600px;
      margin: 50px auto;
      font-family: Arial, sans-serif;
    }
    #output {
      border: 1px solid #ddd;
      padding: 20px;
      min-height: 200px;
      border-radius: 8px;
      background: #f9f9f9;
      line-height: 1.6;
    }
    .cursor {
      animation: blink 1s infinite;
    }
    @keyframes blink {
      0%, 50% { opacity: 1; }
      51%, 100% { opacity: 0; }
    }
    input, button {
      padding: 10px 15px;
      margin-top: 15px;
      border-radius: 4px;
    }
    input { flex: 1; border: 1px solid #ddd; }
    button { background: #4CAF50; color: white; border: none; cursor: pointer; }
    button:hover { background: #45a049; }
  </style>
</head>
<body>
  <div id="chat-container">
    <h2>💬 Chat AI với Hiệu ứng Typewriter</h2>
    <div id="output"><span class="cursor">█</span></div>
    <div style="display: flex;">
      <input type="text" id="message" placeholder="Nhập tin nhắn...">
      <button onclick="sendMessage()">Gửi</button>
    </div>
  </div>

  <script>
    // Thay bằng webhook URL của n8n
    const WEBHOOK_URL = 'https://your-n8n-instance.com/webhook/ai-stream';
    
    const output = document.getElementById('output');
    
    async function sendMessage() {
      const message = document.getElementById('message').value;
      if (!message) return;
      
      output.innerHTML = '<span class="cursor">█</span>';
      
      try {
        // Gọi n8n webhook
        const response = await fetch(WEBHOOK_URL, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ message })
        });
        
        const data = await response.json();
        
        // Typewriter effect
        const fullText = data.fullResponse || '';
        await typewriterEffect(fullText);
        
      } catch (error) {
        output.innerHTML = '❌ Lỗi: ' + error.message;
      }
    }
    
    async function typewriterEffect(text) {
      output.innerHTML = '';
      const cursor = document.createElement('span');
      cursor.className = 'cursor';
      cursor.textContent = '█';
      
      for (let i = 0; i < text.length; i++) {
        output.textContent += text[i];
        output.appendChild(cursor);
        await sleep(20 + Math.random() * 30); // 20-50ms delay
      }
      cursor.remove();
    }
    
    function sleep(ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
    }
  </script>
</body>
</html>

Bước 6: Demo với Server-Sent Events trực tiếp

Nếu bạn muốn response thật sự real-time (từng ký tự hiện ngay), dùng SSE trực tiếp từ n8n:

// Nút "Respond to Webhook" trong n8n
// Cấu hình Response Format: "Response Head"

// Nội dung Response Body (sử dụng Expression):
/*
{{ $json.chunks.map(c => data: ${JSON.stringify({text: c.text})}).join('\n') }}
data: [DONE]
*/

// Tùy chọn Response Headers:
{
  "Content-Type": "text/event-stream",
  "Cache-Control": "no-cache",
  "Connection": "keep-alive"
}
// Frontend xử lý SSE trực tiếp
const output = document.getElementById('output');
const eventSource = new EventSource(https://api.holysheep.ai/v1/chat/completions? + 
  new URLSearchParams({
    message: document.getElementById('message').value
  }));

// Lưu ý: n8n cần proxy qua để xử lý authentication
// Code này minh họa concept, thực tế cần backend proxy

eventSource.onmessage = (event) => {
  if (event.data === '[DONE]') {
    eventSource.close();
    return;
  }
  
  try {
    const data = JSON.parse(event.data);
    output.textContent += data.text;
  } catch (e) {}
};

eventSource.onerror = () => {
  eventSource.close();
};

Kiểm tra và Debug

Để test workflow, click Test Workflow trong n8n. Bạn sẽ thấy:

Mẹo: Thêm node Log giữa các bước để debug dễ hơn. Trong n8n, click vào kết nối > Add Node > Log.

Lỗi thường gặp và cách khắc phục

1. Lỗi "Invalid API Key" hoặc 401 Unauthorized

// ❌ SAI: Thiếu Bearer prefix
"Authorization": "YOUR_HOLYSHEEP_API_KEY"

// ✅ ĐÚNG: Phải có "Bearer " phía trước
"Authorization": "Bearer YOUR_HOLYSHEEP_API_KEY"

// Kiểm tra lại:
// 1. Vào https://www.holysheep.ai/dashboard/api-keys
// 2. Copy đúng API key (bắt đầu bằng "hs-" hoặc "sk-")
// 3. Không copy thừa/kém ký tự

2. Lỗi "stream is not supported" hoặc 400 Bad Request

// ❌ SAI: stream phải là boolean, không phải string
"stream": "true"

// ✅ ĐÚNG: stream là boolean
"stream": true

// Kiểm tra lại:
// 1. Model cần hỗ trợ streaming (hầu hết đều có)
// 2. Dùng model đúng: "deepseek-v3.2", "gpt-4.1", "claude-sonnet-4.5"
// 3. Không dùng model cũ như "gpt-3.5-turbo" (không hỗ trợ streaming)

3. Lỗi SSE parsing - chunks không hiển thị đúng

// ❌ SAI: Không xử lý đúng format SSE
const lines = data.split('\n');
// Chỉ split là chưa đủ

// ✅ ĐÚNG: Parse đúng format SSE
const lines = data.split('\n');
let buffer = '';

for (const line of lines) {
  if (line.startsWith('data: ')) {
    const jsonStr = line.slice(6); // Luôn cắt 6 ký tự "data: "
    
    // Bỏ qua comment lines
    if (jsonStr.startsWith(':')) continue;
    
    // Bỏ qua [DONE]
    if (jsonStr === '[DONE]') break;
    
    // Parse JSON
    const chunk = JSON.parse(jsonStr);
    const content = chunk.choices?.[0]?.delta?.content || '';
    
    // Xử lý content ở đây
    console.log('Chunk received:', content);
  }
}

// Debug: Log raw response để xem format
console.log('Raw response:', data);

4. Lỗi CORS khi gọi trực tiếp từ browser

// ❌ Browser gọi trực tiếp sang HolySheep AI sẽ bị CORS
// Không bao giờ expose API key phía client

// ✅ ĐÚNG: Proxy qua n8n
// 1. Tạo n8n webhook endpoint
// 2. Frontend gọi webhook URL của n8n
// 3. n8n xử lý authentication với HolySheep AI

// Frontend code:
const response = await fetch('https://your-n8n.com/webhook/my-ai-chat', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ message: userMessage })
});

// KHÔNG BAO GIỜ làm thế này:
// const response = await fetch('https://api.holysheep.ai/v1/...');
// API key sẽ bị lộ!

5. Lỗi chunk bị trùng lặp hoặc mất thứ tự

// ❌ Streaming không đảm bảo thứ tự nếu xử lý async sai
const chunks = data.split('data: ')
  .map(s => JSON.parse(s)) // Parse song song = có thể sai thứ tự

// ✅ ĐÚNG: Xử lý tuần tự theo thứ tự nhận được
const lines = rawData.split('\n');
for (const line of lines) {  // for...of giữ thứ tự
  if (line.startsWith('data: ')) {
    await processChunk(line); // Xử lý tuần tự
  }
}

// Thêm sequence number để debug
const chunk = JSON.parse(jsonStr);
const index = chunk.choices?.[0]?.index; // HolySheep AI cung cấp index
console.log(Chunk ${index}:, content);

Tối ưu hiệu suất

Qua kinh nghiệm thực chiến của mình:

// Ví dụ: Tối ưu hiển thị với batching
class TypewriterBuffer {
  constructor(delay = 50) {
    this.buffer = '';
    this.displayCallback = null;
    this.delay = delay;
  }
  
  push(text) {
    this.buffer += text;
    this.scheduleFlush();
  }
  
  scheduleFlush() {
    if (this.timeout) return;
    this.timeout = setTimeout(() => {
      if (this.displayCallback && this.buffer) {
        this.displayCallback(this.buffer);
        this.buffer = '';
      }
      this.timeout = null;
    }, this.delay);
  }
}

// Sử dụng:
const typewriter = new TypewriterBuffer(50);
typewriter.displayCallback = (text) => {
  document.getElementById('output').textContent += text;
};

Kết luận

Việc implement streaming response với n8n và HolySheep AI thực ra không khó như bạn tưởng. Quan trọng là hiểu đúng format SSE, xử lý chunks tuần tự, và bảo mật API key bằng cách proxy qua n8n.

HolySheep AI là lựa chọn tuyệt vời với giá chỉ từ $0.42/MTok (DeepSeek V3.2), tốc độ dưới 50ms, và hỗ trợ thanh toán WeChat/Alipay. Đặc biệt, đăng ký ngay hôm nay để nhận tín dụng miễn phí giúp bạn thử nghiệm không giới hạn.

Nếu gặp khó khăn, để lại comment bên dưới, mình sẽ hỗ trợ ngay. Chúc bạn thành công!

👉 Đăng ký HolySheep AI — nhận tín dụng miễn phí khi đăng ký