Создайте AI-агент на Bun.js за 30 минут без LangChain | Гайд | AiManual
AiManual Logo Ai / Manual.
31 Дек 2025 Гайд

Свой AI-агент на Bun за 30 минут: прощай, LangChain

Пошаговый гайд по созданию легковесного AI-агента на Bun.js с DOM парсингом. Альтернатива тяжелым фреймворкам вроде LangChain.

Проблема: Зачем отказываться от LangChain?

LangChain стал де-факто стандартом для создания AI-агентов, но у этого подхода есть серьезные недостатки. Фреймворк превратился в монолита с сотнями зависимостей, где даже простой агент требует подключения десятков пакетов. Это приводит к:

  • Раздутым бандлам — ваш проект весит сотни мегабайт
  • Сложности отладки — когда что-то ломается, непонятно, в каком слое фреймворка искать проблему
  • Низкой производительности — много слоев абстракции замедляют выполнение
  • Vendor lock-in — ваш код становится привязанным к конкретной реализации

Если вам нужен простой агент для конкретной задачи (парсинг сайтов, обработка документов, автоматизация рутинных действий), LangChain — это избыточно. Как в статье про Cogitator, мы ищем минималистичные альтернативы.

Решение: Bun + простые библиотеки = легковесный агент

Bun — это не просто быстрый JavaScript-рантайм. Это целая экосистема с нативной поддержкой TypeScript, встроенным пакетным менеджером и тест-раннером. Вместо того чтобы тянуть за собой весь LangChain, мы соберем агента из:

  • Bun — как среда выполнения
  • OpenAI API (или любой другой провайдер) — для LLM
  • Cheerio — для парсинга DOM (альтернатива LangChain's document loaders)
  • Свой собственный код — 100% контроль над логикой
💡
Этот подход похож на философию из статьи «Agent Skills» — мы даем агенту конкретные инструменты и четкие инструкции, а не полагаемся на магию фреймворка.

Пошаговый план: от нуля до работающего агента

1 Установка и настройка окружения (5 минут)

Сначала установите Bun, если еще не сделали этого:

curl -fsSL https://bun.sh/install | bash

Создайте новый проект:

mkdir my-ai-agent
cd my-ai-agent
bun init

Установите необходимые зависимости:

bun add openai cheerio
bun add -D @types/node typescript

Обратите внимание: мы устанавливаем только 2 основные зависимости! Сравните это с десятками пакетов в типичном LangChain-проекте.

2 Создание базового агента (10 минут)

Создайте файл agent.ts с простейшей реализацией:

import OpenAI from 'openai';

class SimpleAgent {
  private openai: OpenAI;
  
  constructor(apiKey: string) {
    this.openai = new OpenAI({ apiKey });
  }
  
  async think(prompt: string): Promise {
    const completion = await this.openai.chat.completions.create({
      model: "gpt-4o-mini",
      messages: [
        { role: "system", content: "Ты полезный AI-агент. Отвечай кратко и по делу." },
        { role: "user", content: prompt }
      ],
      temperature: 0.7,
    });
    
    return completion.choices[0].message.content || "Нет ответа";
  }
}

// Использование
const agent = new SimpleAgent(process.env.OPENAI_API_KEY!);
const response = await agent.think("Какая погода в Москве?");
console.log(response);

Запустите агента:

OPENAI_API_KEY=your_key_here bun run agent.ts

3 Добавляем DOM парсинг (10 минут)

Теперь расширим функциональность, добавив возможность анализа веб-страниц. Создайте файл web-agent.ts:

import OpenAI from 'openai';
import * as cheerio from 'cheerio';

class WebAgent {
  private openai: OpenAI;
  
  constructor(apiKey: string) {
    this.openai = new OpenAI({ apiKey });
  }
  
  async fetchAndParse(url: string): Promise {
    const response = await fetch(url);
    const html = await response.text();
    const $ = cheerio.load(html);
    
    // Удаляем скрипты и стили для чистого текста
    $('script, style, nav, footer').remove();
    
    // Берем основной контент
    const text = $('body').text()
      .replace(/\s+/g, ' ') // Убираем лишние пробелы
      .trim()
      .substring(0, 4000); // Ограничиваем длину для токенов
    
    return text;
  }
  
  async analyzeWebsite(url: string, question: string): Promise {
    const websiteContent = await this.fetchAndParse(url);
    
    const prompt = `На основе содержимого сайта ответь на вопрос.

Содержимое сайта:
${websiteContent}

Вопрос: ${question}`;
    
    return this.think(prompt);
  }
  
  private async think(prompt: string): Promise {
    const completion = await this.openai.chat.completions.create({
      model: "gpt-4o-mini",
      messages: [
        { 
          role: "system", 
          content: "Ты специалист по анализу веб-контента. Отвечай только на основе предоставленной информации."
        },
        { role: "user", content: prompt }
      ],
      temperature: 0.5,
    });
    
    return completion.choices[0].message.content || "Не могу проанализировать";
  }
}

// Пример использования
const agent = new WebAgent(process.env.OPENAI_API_KEY!);
const answer = await agent.analyzeWebsite(
  "https://example.com",
  "Какие услуги предлагает этот сайт?"
);
console.log(answer);
💡
Обратите внимание на архитектуру: мы четко разделяем загрузку данных (fetchAndParse) и их обработку (think). Это похоже на подход из статьи «Как спроектировать современного AI-агента», где разделяются planner и executor.

4 Добавляем цепочку вызовов (5 минут)

Чтобы агент мог выполнять последовательность действий, реализуем простую цепочку:

class SequentialAgent extends WebAgent {
  async processMultiple(urls: string[], question: string): Promise {
    const results: string[] = [];
    
    for (const url of urls) {
      try {
        const result = await this.analyzeWebsite(url, question);
        results.push(`Результат для ${url}: ${result}`);
      } catch (error) {
        results.push(`Ошибка для ${url}: ${error}`);
      }
    }
    
    return results;
  }
  
  async summarizeResults(results: string[]): Promise {
    const prompt = `Суммируй следующие результаты анализа:

${results.join('\n\n')}`;
    
    return this.think(prompt);
  }
}

Нюансы и возможные ошибки

Проблема Решение Пояснение
Превышение лимита токенов Обрезать контент до 3000-4000 символов GPT-4o-mini имеет контекст 128K, но для скорости лучше ограничиться
Медленная загрузка страниц Добавить timeout и retry логику Используйте AbortController для контроля времени
Проблемы с кодировкой Конвертировать текст в UTF-8 Bun автоматически обрабатывает кодировки, но проверьте
Слишком частые запросы к API Добавить rate limiting Используйте p-limit или простой счетчик

Важный нюанс: Bun использует свой собственный fetch API, который может отличаться от Node.js. Всегда проверяйте, что ваши HTTP-запросы работают корректно в продакшене.

Что дальше? Развитие вашего агента

Теперь, когда у вас есть базовый агент, можно добавить более сложные функции:

  1. Память агента — сохраняйте контекст между вызовами (см. статью про Agent Skills)
  2. Инструменты (Tools) — дайте агенту доступ к API, базам данных, файловой системе
  3. Планировщик задач — разбивайте сложные задачи на подзадачи
  4. Локальные модели — вместо OpenAI используйте локальные LLM (как в статье про 7 маленьких LLM на ноутбуке)

Преимущество нашего подхода в том, что вы контролируете каждую часть системы. Нет черного ящика, как в LangChain. Вы точно знаете, какой код выполняется и почему.

Заключение

Создание AI-агента на Bun за 30 минут — это не только возможно, но и практично. Вы получаете:

  • Минимальные зависимости — 2 пакета вместо 200
  • Полный контроль — ваш код, ваша логика
  • Высокую производительность — Bun работает быстрее Node.js
  • Простоту отладки — меньше слоев абстракции

Этот подход особенно хорош для:

  • Прототипирования идей
  • Специфических задач (парсинг, анализ, автоматизация)
  • Образовательных целей (чтобы понять, как работают агенты на низком уровне)
  • Продакшена, где важны контроль и производительность

Как показано в статье про Claude Opus, будущее за агентами, которые могут работать автономно. Начните с простой реализации на Bun, и постепенно расширяйте функциональность по мере необходимости.

💡
Помните: лучший фреймворк — тот, который вы понимаете полностью. Иногда проще написать 100 строк своего кода, чем разбираться в 1000 строках чужого абстрактного фреймворка.