Главная/Блог/Гайд/OpenSpace: Создаем самообучающихся…
Гайд12 мин чтения · 25 июля 2026 г.

OpenSpace: Создаем самообучающихся AI-агентов с эволюцией навыков

Полное руководство по созданию самоэволюционирующих AI-агентов с помощью OpenSpace: от настройки окружения до интеграции MCP и анализа lineage-метаданных.

OpenSpace: Создаем самообучающихся AI-агентов с эволюцией навыков

В мире искусственного интеллекта, где скорость изменений измеряется не годами, а днями, статические модели быстро устаревают. Традиционные подходы к разработке AI-агентов часто приводят к созданию «глухих» систем, которые не способны учиться на своих ошибках или переиспользовать накопленный опыт. Однако появление фреймворков, таких как OpenSpace, знаменует собой сдвиг парадигмы: от простых исполнителей команд к самообучающимся системам, которые эволюционируют, сохраняя историю своих изменений и оптимизируя затраты на токены. В этой статье мы подробно разберем, как построить такую систему с нуля, используя Python, SQLite и протокол MCP (Model Context Protocol), чтобы создать агента, который становится умнее с каждым выполнением задачи.

OpenSpace — это не просто библиотека для вызова LLM (Large Language Models). Это архитектура, которая рассматривает навыки (skills) как первый класс сущностей. Каждый раз, когда агент успешно решает задачу, система может извлечь этот опыт, сохранить его в виде структурированного навыка с метаданными о происхождении (lineage) и версионности, а затем переиспользовать его в будущих, схожих задачах. Это снижает потребность в дорогостоящих запросах к моделям и повышает надежность системы. Мы пройдем весь путь: от клонирования репозитория и настройки переменных окружения до запуска сервера MCP и глубокого анализа базы данных эволюции навыков.

011. Подготовка среды и установка OpenSpace

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

Для начала работы мы используем Google Colab или локальный сервер с доступом к интернету. Процесс установки включает в себя не просто `pip install`, а более тонкую настройку. Мы клонируем репозиторий с использованием `sparse checkout`. Это позволяет загрузить только необходимые файлы проекта, игнорируя тяжелые ассеты (например, изображения или большие датасеты в папке `/assets`), что значительно ускоряет начальную загрузку и экономит дисковое пространство.

OpenSpace: Создаем самообучающихся AI-агентов с эволюцией навыков
💡
Совет по оптимизации. Использование `--filter=blob:none` при клонировании Git-репозиториев с большим количеством файлов позволяет загружать только структуру директорий и метаданные, а сами бинарные объекты подгружаются по мере необходимости. Это стандартная практика для работы с большими кодовыми базами в облачных средах.

После клонирования репозитория в директорию `REPO_DIR`, мы устанавливаем пакет в режиме «редактируемой установки» (`-e`). Это означает, что любые изменения в коде OpenSpace будут немедленно отражаться в работе вашей системы без необходимости повторной установки. Далее устанавливаются дополнительные зависимости, такие как `nest_asyncio`, который позволяет запускать вложенные асинхронные циклы, что часто требуется при интеграции с Jupyter/Colab ноутбуками.

terminalpython
import os
import sys
import subprocess
import sqlite3
import json
import textwrap
import shutil
import time
import pathlib

ANTHROPIC_API_KEY = ""
OPENAI_API_KEY = ""
OPENSPACE_MODEL = "anthropic/claude-sonnet-4-5"
OPENSPACE_CLOUD_KEY = ""

assert sys.version_info >= (3, 12), f"OpenSpace needs Python 3.12+, Colab has {sys.version}. Runtime > Change runtime type, or use a fallback py312 venv."

print(f"✅ Python: {sys.version.split()[0]}")

REPO_DIR = "/content/OpenSpace"
if not os.path.exists(REPO_DIR):
    subprocess.run(["git", "clone", "--filter=blob:none", "--sparse", "https://github.com/HKUDS/OpenSpace.git", REPO_DIR], check=True)
    subprocess.run(["git", "sparse-checkout", "set", "--no-cone", "/*", "!/assets/"], cwd=REPO_DIR, check=True)
    print(f"✅ Cloned to {REPO_DIR}")
    print("Top-level:", sorted(os.listdir(REPO_DIR)))

subprocess.run([sys.executable, "-m", "pip", "install", "-q", "-e", REPO_DIR], check=True)
subprocess.run([sys.executable, "-m", "pip", "install", "-q", "nest_asyncio"], check=True)

for cli in ["openspace-mcp", "openspace-dashboard"]:
    path = shutil.which(cli)
    print(f"{'✅' if path else '⚠️ '} {cli}: {path}")

subprocess.run(["openspace-mcp", "--help"], check=False)

022. Конфигурация и управление переменными окружения

Гибкость OpenSpace строится на четком разделении конфигурации. Система ожидает, что ключевые параметры, такие как API-ключи провайдеров LLM (Anthropic, OpenAI) и настройки самого фреймворка, будут переданы через переменные окружения. Это обеспечивает безопасность и позволяет легко переключаться между разными моделями или средами выполнения без изменения кода.

Мы создаем два ключевых каталога: `WORKSPACE` для хранения состояния агента и базы данных, и `SKILLS_DIR` для пользовательских навыков. Затем мы генерируем файл `.env`, который содержит строки вида `KEY=VALUE`. Важно отметить, что скрипт автоматически проверяет наличие ключей API. Если ключи не предоставлены, система корректно предупредит об этом, но продолжит работу в режиме «offline» или с заглушками, что полезно для тестирования структуры кода без затрат на токены.

OpenSpace: Создаем самообучающихся AI-агентов с эволюцией навыков
⚠️ Важно: Безопасность ключей.
Никогда не храните API-ключи в открытом виде в коде. Используйте переменные окружения или файлы `.env`, которые добавлены в `.gitignore`. В примере ниже показано, как скрипт маскирует значения ключей при выводе в лог для предотвращения случайной утечки.

Скрипт также экспортирует переменные в текущее окружение процесса Python, чтобы модули OpenSpace могли получить к ним доступ. Модель по умолчанию установлена на `anthropic/claude-sonnet-4-5`, но вы можете легко заменить её на любую другую поддерживаемую модель, изменив переменную `OPENSPACE_MODEL`. Это демонстрирует абстракцию уровня модели, заложенную в архитектуру OpenSpace.

terminalpython
WORKSPACE = "/content/openspace_workspace"
SKILLS_DIR = "/content/my_agent_skills"
os.makedirs(WORKSPACE, exist_ok=True)
os.makedirs(SKILLS_DIR, exist_ok=True)

env_lines = [
    f"OPENSPACE_MODEL={OPENSPACE_MODEL}",
    f"OPENSPACE_WORKSPACE={WORKSPACE}",
    f"OPENSPACE_HOST_SKILL_DIRS={SKILLS_DIR}"
]
if ANTHROPIC_API_KEY:
    env_lines.append(f"ANTHROPIC_API_KEY={ANTHROPIC_API_KEY}")
if OPENAI_API_KEY:
    env_lines.append(f"OPENAI_API_KEY={OPENAI_API_KEY}")
if OPENSPACE_CLOUD_KEY:
    env_lines.append(f"OPENSPACE_API_KEY={OPENSPACE_CLOUD_KEY}")

env_path = os.path.join(REPO_DIR, "openspace", ".env")
pathlib.Path(env_path).write_text("\n".join(env_lines) + "\n")
pathlib.Path("/content/.env").write_text("\n".join(env_lines) + "\n")

for line in env_lines:
    key, _, value = line.partition("=")
    os.environ[key] = value

print("✅ .env written:\n" + "\n".join([l.split("=")[0] + "=***" if "KEY" in l else l for l in env_lines]))

HAS_LLM_KEY = bool(ANTHROPIC_API_KEY or OPENAI_API_KEY)
if not HAS_LLM_KEY:
    print("⚠️  No LLM key set — Steps 4/6 (live execution) will be skipped.")

033. Асинхронное выполнение задач и эволюция навыков

Сердце OpenSpace — это его способность выполнять задачи асинхронно и анализировать результаты. Мы определяем асинхронную функцию `run_task`, которая использует контекстный менеджер `OpenSpace` для инициализации сессии. Внутри этой сессии мы вызываем метод `execute`, передавая естественное описание задачи. Система не просто возвращает ответ; она возвращает сложный объект, содержащий ответ, а также список «эволюционировавших навыков» (evolved skills).

Что такое эволюция навыка? Когда агент решает сложную задачу, он может создать новый фрагмент кода или логику, который ранее не был известен системе. OpenSpace фиксирует этот новый навык, присваивает ему имя и тип происхождения (origin). В следующем примере мы просим агента написать функцию для расчета заработной платы с учетом сверхурочных. После выполнения мы анализируем ответ, чтобы увидеть, какие новые навыки были сгенерированы или улучшены.

OpenSpace: Создаем самообучающихся AI-агентов с эволюцией навыков
terminalpython
import asyncio
import nest_asyncio
nest_asyncio.apply()

async def run_task(query: str):
    from openspace import OpenSpace
    async with OpenSpace() as cs:
        result = await cs.execute(query)
        print("── RESPONSE ──"[:50])
        print(result["response"][:3000])
        for skill in result.get("evolved_skills", []):
            print(f"  🧬 Evolved: {skill['name']} (origin={skill['origin']})")
    return result

if HAS_LLM_KEY:
    result_1 = asyncio.run(run_task(
        "Write a Python function that parses a CSV of employee hours and "
        "computes weekly payroll with overtime (1.5x beyond 40h). Test it "
        "on a small synthetic example and show the output."
    ))
else:
    print("⏭️  Skipped live task (no key).")

044. Инспекция базы данных SQLite и реестра навыков

OpenSpace использует SQLite для хранения состояния. Это решение выбрано не случайно: SQLite — это легковесная, серверная база данных, которая хранится в одном файле. Для агентов, работающих в изолированных средах (как Colab или локальные скрипты), это идеальное решение. Оно не требует настройки отдельного сервера БД и обеспечивает высокую скорость чтения/записи для небольших и средних объемов данных.

Мы создаем функцию `dump_db`, которая подключается к файлу базы данных (расположенному в `.openspace/openspace.db` внутри рабочей директории) и выводит структуру таблиц. Это позволяет разработчику «заглянуть под капот» и увидеть, как именно хранятся навыки, их метаданные и история изменений. Мы также проверяем доступность модуля `skill_engine` и типов `sk_types`, что подтверждает корректность установки и возможность программной работы с реестром навыков.

terminalpython
def dump_db(db_path, max_rows=5):
    if not os.path.exists(db_path):
        print(f"No DB at {db_path}")
        return
    con = sqlite3.connect(db_path)
    cur = con.cursor()
    tables = [r[0] for r in cur.execute("SELECT name FROM sqlite_master WHERE type='table'").fetchall()]
    print(f"📀 {db_path}\n   tables: {tables}")
    for t in tables:
        try:
            cols = [c[1] for c in cur.execute(f"PRAGMA table_info({t})").fetchall()]
            rows = cur.execute(f"SELECT * FROM {t} LIMIT {max_rows}").fetchall()
            print(f"\n▶ {t} ({len(rows)} shown) cols={cols[:8]}{'…' if len(cols)>8 else ''}")
            for r in rows:
                print(f"   {str(r)[:160]}")
        except Exception as e:
            print(f"   (skip {t}: {e})")
    con.close()

runtime_db = os.path.join(WORKSPACE, ".openspace", "openspace.db")
alt_db = os.path.join(REPO_DIR, ".openspace", "openspace.db")
dump_db(runtime_db if os.path.exists(runtime_db) else alt_db)

try:
    from openspace.skill_engine.registry import SkillRegistry
    from openspace.skill_engine import types as sk_types
    print("\n✅ skill_engine importable:")
    for n in dir(sk_types):
        if n.isupper():
            print(f"  - {n}")
except Exception as e:
    print(f"ℹ️ registry import note: {e}")

055. Переиспользование навыков и кастомные SKILL.md

Одна из самых мощных функций OpenSpace — это способность к переиспользованию. Если мы запустим задачу, связанную с предыдущей (например, добавление расчета налогов к уже созданной функции зарплаты), система попытается найти подходящий навык в своем реестре. Если он есть, она может использовать его как основу, что экономит токены и время. Мы демонстрируем это, запуская вторую задачу и снова вызывая `dump_db`, чтобы увидеть, как изменились записи.

OpenSpace: Создаем самообучающихся AI-агентов с эволюцией навыков

Кроме того, пользователи могут добавлять свои собственные навыки. OpenSpace поддерживает формат `SKILL.md` — это Markdown-файл, который описывает, как агент должен выполнять определенную задачу. Мы создаем кастомный навык `colab-csv-report`, который инструктирует агента преобразовывать любые CSV-файлы в краткие отчеты с использованием pandas. Этот файл размещается в `SKILLS_DIR`, и OpenSpace автоматически обнаруживает его при запуске.

📌 Факт: Типы происхождения навыков.
В базе данных OpenSpace навыки классифицируются по типу происхождения: FIX (исправленный существующий навык), DERIVED (выведенный из других навыков) и CAPTURED (захваченный из успешного выполнения задачи). Эта метаданные позволяют отслеживать «генетическую историю» каждого навыка.
terminalpython
if HAS_LLM_KEY:
    result_2 = asyncio.run(run_task(
        "Extend the payroll logic: add a second CSV of tax withholding rates "
        "per employee and produce net pay. Reuse any prior payroll skill."
    ))
    dump_db(runtime_db if os.path.exists(runtime_db) else alt_db, max_rows=12)
else:
    print("⏭️  Skipped warm-rerun demo (no key).")

custom = pathlib.Path(SKILLS_DIR) / "colab-csv-report"
custom.mkdir(parents=True, exist_ok=True)
(custom / "SKILL.md").write_text(textwrap.dedent("""
---
name: colab-csv-report
description: Turn any CSV into a short markdown report with summary stats,
  null counts, dtypes, and 3 key observations. Use pandas; never plot.
---
# colab-csv-report
1. Load the CSV with pandas (`on_bad_lines="skip"` fallback).
2. Emit: shape, dtypes table, describe(), null counts.
3. Write 3 bullet observations in plain markdown.
4. If parsing fails, retry with `sep=None, engine="python"`.
"""))
print("✅ Custom skill written:", custom / "SKILL.md")

for host_skill in ["delegate-task", "skill-discovery"]:
    src = os.path.join(REPO_DIR, "openspace", "host_skills", host_skill)
    dst = os.path.join(SKILLS_DIR, host_skill)
    if os.path.isdir(src) and not os.path.isdir(dst):
        shutil.copytree(src, dst)
print("✅ Host skills installed into agent dir:", sorted(os.listdir(SKILLS_DIR)))

066. Интеграция через MCP (Model Context Protocol)

Чтобы сделать навыки OpenSpace доступными для других агентов или систем, мы запускаем сервер MCP. MCP — это открытый стандарт, позволяющий LLM-приложениям безопасно обмениваться данными и инструментами. Мы используем транспорт `streamable-http`, который позволяет подключаться к серверу через стандартные HTTP-запросы.

Запуск сервера происходит в фоновом процессе (`subprocess.Popen`). Мы затем проверяем доступность эндпоинта, отправляя GET-запрос. Даже если сервер вернет ошибку HTTP (так как MCP использует свой собственный протокол поверх HTTP), сам факт ответа подтверждает, что сервер запущен. Это позволяет другим агентам, таким как Claude Code, Codex или OpenClaw, использовать навыки, созданные в OpenSpace, как внешние инструменты.

terminalpython
mcp_proc = subprocess.Popen(
    ["openspace-mcp", "--transport", "streamable-http", "--host", "127.0.0.1", "--port", "8081"],
    stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True,
    env={**os.environ}
)
time.sleep(2)

try:
    import urllib.request
    req = urllib.request.Request("http://127.0.0.1:8081/mcp", method="GET")
    try:
        urllib.request.urlopen(req, timeout=5)
        print("✅ MCP streamable-HTTP endpoint is up at http://127.0.0.1:8081/mcp")
    except urllib.error.HTTPError as e:
        print(f"✅ MCP server alive (HTTP {e.code} on bare GET, expected for MCP)")
except Exception as e:
    print(f"⚠️ MCP probe failed: {e}")

print(json.dumps({
    "mcpServers": {
        "openspace": {
            "command": "openspace-mcp",
            "toolTimeout": 600,
            "env": {
                "OPENSPACE_HOST_SKILL_DIRS": SKILLS_DIR,
                "OPENSPACE_WORKSPACE": WORKSPACE,
                "OPENSPACE_API_KEY": "sk-xxx (optional, for cloud)"
            }
        }
    }
}, indent=2))

mcp_proc.terminate()

077. Анализ эволюции и облачная синхронизация

На финальном этапе мы исследуем базу данных из демонстрационного репозитория (`showcase`), чтобы понять, как выглядит масштабная эволюция навыков. Мы агрегируем данные по типу происхождения (origin), чтобы увидеть соотношение между навыками, которые были захвачены, выведены или исправлены. Это дает представление о том, как система обучается: преобладает ли создание новых навыков или оптимизация существующих.

Также мы рассматриваем возможность загрузки кастомных навыков в облачное сообщество OpenSpace, если доступен API-ключ. Это позволяет делиться навыками с другими разработчиками, создавая экосистему переиспользуемых компонентов. Завершающий вывод подчеркивает, что OpenSpace предоставляет полный цикл: от создания навыка до его интеграции в более крупные агенты через MCP.

terminalpython
if OPENSPACE_CLOUD_KEY:
    subprocess.run(["openspace-upload-skill", str(custom)], check=False)
    print("✅ Cloud CLI demo executed (upload).")
else:
    print("ℹ️ Cloud skipped — set OPENSPACE_CLOUD_KEY to enable openspace-upload-skill / openspace-download-skill.")

showcase_db = os.path.join(REPO_DIR, "showcase", ".openspace", "openspace.db")
dump_db(showcase_db, max_rows=10)

if os.path.exists(showcase_db):
    con = sqlite3.connect(showcase_db)
    cur = con.cursor()
    for t in ["skills", "skill_versions"]:
        try:
            cols_lower = [c[1].lower() for c in cur.execute(f"PRAGMA table_info({t})").fetchall()]
            if "origin" in cols_lower:
                print(f"\n📊 Evolution-mode breakdown in table '{t}':")
                for origin, n in cur.execute(f"SELECT origin, COUNT(*) FROM {t} GROUP BY origin ORDER BY 2 DESC").fetchall():
                    print(f"   {origin:>10}: {n}")
        except:
            pass
    con.close()

print("""
══════════════════════════════════════════════════════════════════
🎓 TUTORIAL COMPLETE — what you now have:
 • OpenSpace installed + configured in Colab
 • Live task execution via the Python API (if key set)
 • A custom SKILL.md your agent auto-discovers
 • Host skills (delegate-task, skill-discovery) staged for any
   SKILL.md-capable agent (Claude Code / Codex / OpenClaw / nanobot)
 • An MCP server you booted over streamable HTTP
 • Full lineage inspection of a 60+ skill evolution DB
Next: run more related tasks and watch token usage drop as skills
FIX / DERIVE / CAPTURE themselves. Dashboard (needs Node ≥ 20):
 openspace-dashboard --port 7788   +   cd frontend && npm i && npm run dev
══════════════════════════════════════════════════════════════════
""")

08Что это значит на практике

Внедрение самоэволюционирующих агентов, подобных тем, что построены на базе OpenSpace, меняет подход к разработке AI-приложений. Вместо того чтобы каждый раз писать код с нуля для решения схожих задач, разработчики создают систему, которая накапливает знания. Это приводит к значительному снижению затрат на токены, так как переиспользование готовых навыков требует меньше вычислительных ресурсов, чем генерация нового кода. Кроме того, наличие полной истории изменений (lineage) позволяет отлаживать поведение агентов, понимая, какой именно навык привел к ошибке или успеху. Интеграция через MCP открывает двери для создания модульных AI-экосистем, где навыки могут быть легко перенесены между различными платформами и фреймворками, делая ИИ-инфраструктуру более гибкой, экономичной и устойчивой к изменениям.

Источник: MarkTechPost ↗