The Jerusalem PostParashat Noah: How prayer becomes an ark that carries us through turbulent times - opinionInquirerDe Lima backs QC task force axing: No authority for ‘utak-Tokhang’Daily MaverickFruit juice is not ‘more equal’ when it comes to sugar and public healthRTP DesportoMundiais Ciclismo. Miguel Salgueiro medalha de bronze na corrida por pontosEl Comercio¿Por qué Ucrania ataca a Yandex, el “Google de Rusia”, y cómo podría responder Putin?Straits Times SportJodar apologises for swearing at ball kid in ShanghaiGIGAZINE「マチ★アソビ vol.31」イベントスケジュール一覧まとめZDF heuteAktuelle Pressemitteilungen des ZDFBBC NewsNorwegian teen 'hitman' detained for UK murder plot20 MinutenNackte (38) schleicht in Wohnung – und muss Schmerzensgeld zahlenIl Fatto QuotidianoViolenze sulla Flotilla, non solo Ben-Gvir: indagato anche il ministro della Difesa KatzWirtualna Polska"Jestem na to gotowy". Sędzia TK mógłby oddać mandat. Stawia jeden warunek
The Daily Newsstand · Free, Always
Friday, October 16, 2026

Свой AI-агент с блекджеком: собираем из того, что есть

Translate

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

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

Отдельное правило для критиков: — Правило многообразия: отвергайте все утверждения о «единственно правильном пути».

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

Проблема

Я, как можно догадаться, большой сторонник открытого, расширяемого, модульного ПО. Фанат Linux, микросервисной архитектуры и не большой любитель больших и сложных фреймворков, которые предлагают решить все возможные проблемы из коробки (хоть и пишу на .NET — каюсь). Поэтому меня во многом угнетает тенденция все большей зависимости от крупных корпораций в части программирования, когда за само создание программ или доступ к знаниям нужно платить деньги за подписку. Возможно, с дальнейшим развитием технологий, железо и сами модели станут гораздо более доступны для запуска на локальных устройствах и начнет появляться больше инструментов для этого, но я не хочу сидеть и ждать, когда эти времена настанут. По этой причине возникла идея создать своего модульного агента из доступных Open Source компонентов в том виде, в каком я вижу направление развития.

Определения

AI Agent — автономная программа, которая использует большую языковую модель (LLM) для достижения поставленной цели — агент не просто отвечает на вопрос, а планирует последовательность шагов, выбирает инструменты, выполняет действия и анализирует результат, чтобы решить задачу.

Tools — внешние функции или программные интерфейсы, которые агент может вызывать для взаимодействия с миром за пределами языковой модели — это его «руки», «глаза» и «уши».

OpenAI API — контракт REST API для доступа к LLM от компании OpenAI, который стал де-факто стандартом для множества движков запуска моделей (не является общепризнанным стандартом, но имеем, что имеем).

Llama.cpp — открытый движок для локального запуска больших языковых моделей (LLM), который поддерживает квантование, аппаратное ускорение на различных видеокартах, запуск в гибридном режиме (CPU + GPU) и предоставляет OpenAI API для взаимодействия с моделями.

Подготовка

Для запуска агента имеется домашний сервер, собранный из б/у компонентов:

  • Motherboard: Supermicro H11SSL-i

  • CPU: AMD EPYC 7601 (32 ядра, 64 потока, 8 каналов памяти)

  • RAM: 512 GB DDR4-2400

  • SSD: 2 TB

  • OS: Ubuntu Server 26.04.1 LTS

Также я использовал следующие LLM которые можно скачать с сайта Hugging Face:

Скачиваем GGUF файлы этих моделей в отдельные папки для каждой модели и кладем в общую папку models.

Архитектура

Схема взаимодействия компонентов выглядит следующим образом:

Архитектура построена по модульному принципу. Инструменты могут подключаться/отключаться к аугменторам (о них подробнее будет ниже) независимо. Также сам состав аугменторов может быть изменен в зависимости от задачи и принципов композиции наборов инструментов. Взаимодействие между компонентами происходит через контракт OpenAI Responses API, а подключение инструментов через стандартный MCP веб протокол. Таким образом llama.cpp может быть заменена на любой сервер, поддерживающий запросы через OpenAI контракт. Клиент, который в данной реализации слушает входящие email, также может быть заменен на любого другого агента поддерживающего отправку запросов к OpenAI API, даже имея свой набор инструментов и алгоритм их вызова, т.к. клиент в этой схеме вообще о присутствии каких-либо инструментов не догадывается — их вызов и обработка происходят абсолютно непрозрачно для него. Каждый компонент отвечает строго за выполнение только своей функции и не требует для работы наличия каких-либо других связанных компонентов.

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

или

Реализация

Полный скрипт для запуска агентской системы выглядит следующим образом:

services:

  llama:
    image: ghcr.io/ggml-org/llama.cpp:server
    restart: unless-stopped
    ports:
      - "11434:8080"
    volumes:
      - ./models:/models
    command:
      - "--models-dir"
      - "/models"
      - "--port"
      - "8080"
      - "--host"
      - "0.0.0.0"

  mentat:
    image: gendalf90/mentat:latest
    restart: unless-stopped
    depends_on:
      - thinking-tools-augmentor
    environment:
      OpenAIUrl: "http://thinking-tools-augmentor:8080"
      OpenAIModel: "Qwen3.5-122B-A10B-GGUF"
      MailImapHost: "imap.mail.ru"
      MailSmtpHost: "smtp.mail.ru"
      MailUsers: "user-to-be-answered@mail.com"
      MailLogin: "user-to-login@mail.ru"
      MailPassword: "<mail server app password>"

  programmer-buddy-mcp:
    image: gendalf90/buddy:latest
    restart: unless-stopped
    environment:
      OpenAIUrl: "http://common-tools-augmentor:8080"
      OpenAIModel: "Qwen3-Coder-Next-GGUF"
      OpenAIPrompt: "You are a good programmer."
      ToolName: "ask_programmer"
      ToolDescription: "Call special programming LLM. Use this when you need to solve any programming problem. The model can use common files in workspace and search or open pages from internet."
      PromptDescription: "The free text for request."

  office-buddy-mcp:
    image: gendalf90/buddy:latest
    restart: unless-stopped
    environment:
      OpenAIUrl: "http://common-tools-augmentor:8080"
      OpenAIModel: "Qwen3.8-27B-GGUF"
      OpenAIPrompt: "You are an office worker who can do various routine extensive work."
      ToolName: "ask_office"
      ToolDescription: "Call simple LLM. Use this when you need do various routine extensive work. The model can use common files in workspace and search or open pages from internet."
      PromptDescription: "The free text for request."

  files-mcp:
    image: supercorp/supergateway:latest
    restart: unless-stopped
    volumes:
      - ./workspace:/workspace
    command:
      - "--stdio"
      - "npx -y @modelcontextprotocol/server-filesystem /workspace"
      - "--outputTransport"
      - "sse"
      - "--port"
      - "8080"

  thinking-mcp:
    image: supercorp/supergateway:latest
    restart: unless-stopped
    command:
      - "--stdio"
      - "npx -y @modelcontextprotocol/server-sequential-thinking"
      - "--outputTransport"
      - "sse"
      - "--port"
      - "8080"

  fetcher-mcp:
    image: ghcr.io/jae-jae/fetcher-mcp:latest
    restart: unless-stopped

  search-mcp:
    image: supercorp/supergateway:latest
    restart: unless-stopped
    environment:
      - SEARXNG_INSTANCES=http://searxng:8080
    depends_on:
      - searxng
    command:
      - "--stdio"
      - "npx -y @kevinwatt/mcp-server-searxng"
      - "--outputTransport"
      - "sse"
      - "--port"
      - "8080"

  thinking-tools-augmentor:
    image: gendalf90/augmentor:latest
    restart: unless-stopped
    ports:
      - "8822:8080"
    depends_on:
      - thinking-mcp
      - programmer-buddy-mcp
      - office-buddy-mcp
      - common-tools-augmentor
    environment:
      - Endpoint=http://common-tools-augmentor:8080
      - Mcp__Thinking__Endpoint=http://thinking-mcp:8080/sse
      - Mcp__Programmer__Endpoint=http://programmer-buddy-mcp:8080
      - Mcp__Office__Endpoint=http://office-buddy-mcp:8080

  common-tools-augmentor:
    image: gendalf90/augmentor:latest
    restart: unless-stopped
    ports:
      - "8811:8080"
    depends_on:
      - files-mcp
      - fetcher-mcp
      - search-mcp
      - llama
    environment:
      - Endpoint=http://llama:8080
      - Mcp__Files__Endpoint=http://files-mcp:8080/sse
      - Mcp__Fetcher__Endpoint=http://fetcher-mcp:3000/mcp
      - Mcp__Search__Endpoint=http://search-mcp:8080/sse

  searxng:
    image: searxng/searxng:latest
    container_name: searxng
    restart: unless-stopped
    volumes:
      - ./searxng:/etc/searxng

Docker в данном случае выбран как средство контейнеризации и данная система или ее части могут быть развернуты например в Kubernetes или как самостоятельные процессы. В том числе очень удобно производить отладку частей системы запуская отдельные сервисы в debug режиме или с расширенным логированием.

Mentat

Сервис, единственной задачей которого является обработка входящих email сообщений и формирование тредов из связанных ответов для последующей отправки модели в качестве истории. Электронную почту для коммуникации я выбрал как наиболее распространенный стандарт, доступный в виде множества реализаций и клиентов от разных компаний и не подверженный блокировкам, т.к. авторизация очень многих сервисов зависит от этого протокола. Также уже имеется встроенный механизм формирования тредов сообщений из которого легко формируется контекст для истории переписки с моделью.

Augmentor

Существует множество реализаций агентов, которые позволяют подключать MCP инструменты и обрабатывать их вызовы при запросах от модели. Но каждый раз при создании своего агента требуется реализовывать этот механизм заново. Данный сервис выносит механизм подключения и обработки запросов от модели во вне и позволяет переиспользовать независимо от агента. Клиентское приложение даже не догадывается, что какие-либо инструменты подключены и получает уже готовый ответ, независимо от того, сколько и какие инструменты вызывались моделью. Более того, данное решение меняет парадигму взаимодействия: инструменты подключаются не к клиенту, а являются как бы расширением сервера. Сервис выставляет наружу OpenAI интерфейс и выглядит для клиента как обычный движок для обработки запросов, скрывая за собой любое количество подключенных инструментов или даже цепочку из нескольких аугменторов.

Buddy

Единственной задачей данного сервиса является создание обертки вокруг OpenAI интерфейса в виде MCP инструмента. Это дает возможность одной модели стандартным образом вызывать другую, более специализированную, модель. Т.е. это по сути адаптер позволяющий подключить и расширить существующего агента до полноценной агентской системы, где разные модели могут решать задачи совместно, координируюясь через общую историю вызовов.

Supergateway

Я изначально принял решение, что компоненты будут взаимодействовать через сеть. Но не все существующие реализации MCP инструментов это поддерживают. Стандартом сегодня является возможность подключения через stdio. Данный сервис является адаптером, который создает веб MCP интерфейс и транслирует вызовы к stdio инструмента.

Searxng

Движок поиска в интернете, поддерживающий несколько провайдеров таких как: bing, duckduckgo, wikipedia и другие. Взаимодействие происходит через веб интерфейс, а результат поиска возвращается в json формате со списком найденных ресурсов. Сам по себе не имеет возможности подключения в виде инструмента, но добрые люди сделали MCP инструмент, который является адаптером к его интерфейсу.

Пример настроек из файла searxng/settings.yml, которые используются при запуске контейнера:

use_default_settings:
  engines:
    keep_only:
      - bing
      - duckduckgo
      - wikipedia

server:
  bind_address: "0.0.0.0"
  secret_key: "<some generated key>"
  port: 8080

search:
  safe_search: 0
  formats:
    - html
    - json

Результат

В результате мы получили локальную агентскую систему, способную гибко конфигурироваться и пересобираться под конкретное требование и решать широкий круг задач. Система находится полностью под нашим контролем, собрана из открытых и бесплатных компонентов. Каждая часть этой системы заменяема с возможностью подключать множество существующих доступных и совместимых компонентов.

Возможности:

  • принимает запросы по email;

  • поддерживает контекст в рамках треда;

  • может искать информацию через локальный SearXNG;

  • может открывать и читать содержимое веб-страницы через fetcher MCP;

  • может работать с файлами в изолированной workspace папке;

  • может делегировать рутинные, объемные задачи отдельной небольшой модели;

  • может делегировать программистские задачи отдельной coding-модели;

  • может при сложных запросах использовать sequential thinking как отдельный инструмент.

Что дальше?

Следующим шагом я вижу решение проблемы сохранения новых знаний и использования моделью долговременной памяти. Также мою фантазию будоражат возможности автоматизированного проектирования агентных систем (ADAS) когда целая агентная система создается под конкретную задачу специальным отдельным агентом-проектировщиком (MAS). При использовании подобного подхода к сборке системы из отдельных универсальных совместимых модулей такое проектирование значительно облегчается.

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.