Почему ваш AI-агент все еще не умеет работать с файлами?
Вы создали умного помощника. Он анализирует код, пишет документацию, даже делает код-ревью. Но стоит попросить его "посмотреть содержимое папки и найти все .py файлы" - и он замирает. Или предлагает странные решения вроде "я не могу читать файлы, но могу предположить...". Знакомо?
Это не проблема модели. Это проблема архитектуры. В 2026 году мы все еще пытаемся заставить LLM работать с файловой системой через костыли, хотя решение лежит на поверхности.
Если ваш агент не может выполнить ls -la и проанализировать результат - вы строите дом без фундамента. Файловая система - это операционная среда любого разработчика. Игнорировать ее - все равно что пытаться готовить ужин с завязанными глазами.
Эволюция: от тупых инструментов к умным навыкам
1 MCP: первый шаг к осознанию проблемы
Model Context Protocol от Anthropic - это как первая попытка научить ребенка пользоваться ложкой. Не идеально, но лучше, чем есть руками.
MCP решает базовую проблему: как безопасно дать LLM доступ к внешним ресурсам. Серверы, инструменты, API - все через единый протокол. Звучит логично, пока не сталкиваешься с реальностью.
Вот типичный сценарий провала:
# tools.py - классический MCP подход
@tool
def read_file(path: str) -> str:
"""Читает содержимое файла"""
with open(path, 'r') as f:
return f.read()
@tool
def list_directory(path: str) -> list:
"""Список файлов в директории"""
return os.listdir(path)
Проблема? Агент вызывает read_file. Получает 1000 строк кода. Пытается их анализировать. Забывает контекст. Вызывает еще один инструмент. Контекстное окно переполняется. Результат - хаос.
2 Skills: когда инструменты становятся умными
Skills - это следующий эволюционный скачок. Если MCP-инструменты - это отдельные функции, то skills - это целые библиотеки с контекстом, памятью и логикой.
Вспомните статью про Skills, MCP и сабагенты. Там мы разбирали, как навыки превращают хаотичный диалог в предсказуемую систему.
Но даже skills не решают главную проблему работы с файлами: агент все еще мыслит дискретными шагами. "Прочитать файл" -> "Проанализировать" -> "Принять решение". Это медленно. Это неэффективно. Это не похоже на то, как работает разработчик.
REPL-подход: когда агент становится разработчиком
REPL (Read-Eval-Print Loop) - это концепция из мира программирования. Вы вводите код, система выполняет его, показывает результат. Цикл повторяется.
Теперь представьте: агент не вызывает инструменты. Он генерирует код, который выполняет задачу. Не "прочитай файл", а "вот скрипт, который найдет все .py файлы и проанализирует их структуру".
Это меняет все.
| Подход | Как работает | Проблема |
|---|---|---|
| MCP-инструменты | Агент вызывает API для каждого действия | Много контекстных переключений, медленно |
| Skills | Агент активирует навык с готовой логикой | Ограниченная гибкость, нужно предопределять все сценарии |
| REPL | Агент генерирует код под конкретную задачу | Требует контроля безопасности, может генерировать плохой код |
3 Как это работает на практике
Давайте разберем реальный пример. Задача: "Найди все Python-файлы в проекте, которые содержат SQL-запросы без параметризации".
Старый подход (MCP):
# Агент делает:
1. Вызывает list_directory("/project")
2. Фильтрует .py файлы (в уме)
3. Для каждого файла вызывает read_file()
4. Ищет SQL-запросы (в уме)
5. Проверяет параметризацию (в уме)
6. Формирует отчет
6 вызовов инструментов. 6 разрывов контекста. Идеальный рецепт для ошибки.
Новый подход (REPL + Skills):
# Агент генерирует:
import os
import re
def find_sql_injections(root_dir):
results = []
sql_pattern = re.compile(r'SELECT|INSERT|UPDATE|DELETE.*FROM', re.IGNORECASE)
param_pattern = re.compile(r'%s|\?|:param|@param')
for root, dirs, files in os.walk(root_dir):
for file in files:
if file.endswith('.py'):
path = os.path.join(root, file)
with open(path, 'r', encoding='utf-8') as f:
content = f.read()
# Ищем SQL-запросы
sql_matches = sql_pattern.findall(content)
if sql_matches:
# Проверяем параметризацию
has_params = bool(param_pattern.search(content))
if not has_params:
results.append({
'file': path,
'sql_count': len(sql_matches),
'lines': [i+1 for i, line in enumerate(content.split('\n'))
if sql_pattern.search(line)]
})
return results
# Выполняем
injections = find_sql_injections('/project')
print(f"Найдено {len(injections)} файлов с потенциальными SQL-инъекциями")
for item in injections:
print(f" {item['file']}: {item['sql_count']} запросов на строках {item['lines']}")
Один вызов. Один результат. Агент мыслит как разработчик, а не как пользователь API.
Архитектура универсального агента 2026
Собираем все вместе. Вот как выглядит современный агент для работы с файлами и CLI:
# architecture.py
class UniversalFileAgent:
def __init__(self):
self.skills_registry = SkillsRegistry() # Динамические навыки
self.repl_executor = REPLExecutor() # Безопасное выполнение кода
self.context_manager = ContextManager() # Управление контекстом
self.safety_checker = SafetyChecker() # Проверка безопасности кода
async def handle_request(self, task: str) -> str:
"""Основной цикл обработки задач"""
# 1. Определяем, нужен ли навык или REPL
if self._is_standard_task(task):
# Используем готовый навык
skill = self.skills_registry.get_skill(task)
return await skill.execute(task)
else:
# 2. Генерируем код под задачу
generated_code = await self._generate_code(task)
# 3. Проверяем безопасность
if not self.safety_checker.is_safe(generated_code):
return "Код не прошел проверку безопасности"
# 4. Выполняем в sandbox
result = await self.repl_executor.execute(generated_code)
# 5. Анализируем результат, учимся
self._learn_from_execution(task, generated_code, result)
return result
def _is_standard_task(self, task: str) -> bool:
"""Определяем, есть ли готовый навык"""
# Здесь логика определения типа задачи
standard_tasks = [
"code review",
"documentation",
"security scan",
"dependency update"
]
return any(st in task.lower() for st in standard_tasks)
Ключевое отличие от традиционной архитектуры: агент не просто выбирает между инструментами. Он выбирает между парадигмами. "Использовать готовое решение" или "создать новое под задачу". Это уровень мышления, а не просто выполнения.
4 Безопасность: самая сложная часть
REPL-подход - это мощно. И страшно. Дать агенту возможность выполнять произвольный код - все равно что дать ребенку бензопилу.
Вот что НЕЛЬЗЯ делать:
# НИКОГДА ТАК НЕ ДЕЛАЙТЕ
exec(generated_code) # Прямое выполнение
os.system(user_input) # Выполнение shell-команд
subprocess.run(unsafe_command) # Без проверки
Вот как делать правильно:
# security.py
class SafeREPLExecutor:
def __init__(self):
self.allowed_modules = {
'os': ['path', 'listdir', 'walk'],
're': ['compile', 'search', 'findall'],
'json': ['loads', 'dumps'],
'pathlib': ['Path'],
'sys': ['version']
}
self.banned_patterns = [
r'__import__\s*\(',
r'eval\s*\(',
r'exec\s*\(',
r'open\s*\(.*[wax]\s*[,)]', # Запись в файлы
r'os\.(system|popen|remove|rmdir)',
r'subprocess\.',
r'import\s+shutil',
r'import\s+subprocess'
]
async def execute(self, code: str) -> str:
"""Безопасное выполнение кода"""
# 1. Статический анализ
for pattern in self.banned_patterns:
if re.search(pattern, code):
raise SecurityError(f"Запрещенная конструкция: {pattern}")
# 2. Sandbox выполнение
try:
# Ограниченное пространство имен
safe_globals = {
'__builtins__': {
'len': len,
'range': range,
'str': str,
'list': list,
'dict': dict,
'bool': bool,
'int': int,
'float': float
}
}
# Добавляем разрешенные модули
for module, functions in self.allowed_modules.items():
imported = __import__(module)
safe_globals[module] = {f: getattr(imported, f) for f in functions}
# Выполняем в изолированном контексте
exec_globals = {}
exec(code, safe_globals, exec_globals)
# Ищем результат (предполагаем, что код что-то возвращает)
if 'result' in exec_globals:
return str(exec_globals['result'])
else:
return "Код выполнен, но не вернул результат"
except Exception as e:
return f"Ошибка выполнения: {str(e)}"
Интеграция с существующей экосистемой
Вы не строите агента с нуля. Вы интегрируете его в существующий workflow. Вот как это выглядит на практике.
Сценарий: вы используете динамические навыки через файловую систему. У вас уже есть структура:
agent_skills/
├── code_review/
├── documentation/
└── security_scan/
Добавляем REPL-навык:
agent_skills/
├── code_review/
├── documentation/
├── security_scan/
└── repl_generator/ # Новый навык
├── SKILL.md
├── safety_rules.yaml
├── code_templates/
└── examples/
SKILL.md для REPL-навыка:
# repl_generator/SKILL.md
name: "code_generator"
description: "Генерация и выполнение Python кода для работы с файлами"
triggers:
- "напиши скрипт для"
- "создай программу которая"
- "автоматизируй задачу"
- "обработай файлы"
safety_rules:
- "запрещено выполнение shell-команд"
- "запрещена запись в системные файлы"
- "максимальное время выполнения: 30 секунд"
- "максимальный размер вывода: 10MB"
code_templates:
file_processing: |
import os
import re
def process_files(directory, pattern):
results = []
for root, dirs, files in os.walk(directory):
for file in files:
if re.search(pattern, file):
path = os.path.join(root, file)
# Добавьте свою логику здесь
results.append(path)
return results
Ошибки, которые все еще совершают в 2026
Даже с современными инструментами разработчики наступают на одни и те же грабли.
Ошибка 1: Слишком много доверия
# ПЛОХО: полагаться на то, что агент сам все проверит
result = await agent.execute("удали все .log файлы старше 30 дней")
# Агент может сгенерировать: os.system("find / -name '*.log' -mtime +30 -delete")
# Поздравляем, вы только что удалили системные логи
Ошибка 2: Игнорирование контекста
# ПЛОХО: каждый запрос обрабатывается изолированно
agent.handle("покажи структуру проекта")
agent.handle("найди все тесты")
agent.handle("проверь покрытие")
# Три отдельных вызова, три раза агент обходит файловую систему
Ошибка 3: Отсутствие обучения
Самый большой провал - не учиться на успешных выполнениях. Если агент сгенерировал идеальный скрипт для обработки CSV-файлов - сохраните его как новый навык. В следующий раз он будет использовать готовое решение, а не изобретать велосипед.
Практический пример: миграция проекта
Давайте посмотрим, как универсальный агент справляется с реальной задачей: "Перенеси все конфигурационные файлы из формата YAML в TOML".
Вместо того чтобы писать длинный промпт с инструкциями, агент:
- Анализирует структуру проекта (используя навык анализа файлов)
- Определяет, что задача нестандартная (нет навыка YAML-TOML конвертации)
- Генерирует скрипт, который:
- Находит все .yaml и .yml файлы
- Анализирует их структуру
- Конвертирует в TOML с учетом специфики (комментарии, многоуровневые структуры)
- Создает backup оригинальных файлов
- Генерирует отчет о конвертации
- Выполняет скрипт в sandbox
- Предлагает сохранить скрипт как новый навык для будущего использования
Весь процесс занимает минуты, а не часы ручной работы.
Что дальше? Эволюция не остановится
К 2027 году мы увидим еще больший сдвиг. REPL-подход эволюционирует в то, что я называю "когнитивным программированием". Агент не просто генерирует код - он понимает контекст проекта, знает историю изменений, предсказывает побочные эффекты.
Представьте агента, который:
- Видит, что вы меняете API endpoint
- Автоматически находит все клиенты этого API в кодовой базе
- Генерирует миграционные скрипты для каждого клиента
- Запускает тесты, чтобы убедиться, что ничего не сломалось
- Создает PR с изменениями и описанием
Это не фантастика. Это следующий логический шаг после REPL-подхода.
Самый важный урок 2026 года: перестаньте думать об агентах как о чат-ботах с инструментами. Начинайте думать о них как о автономных разработчиках, которые могут не только использовать инструменты, но и создавать их под задачи. Разница фундаментальная.
Если вы до сих пор строите агентов, которые не умеют работать с файловой системой - вы отстали на два поколения архитектур. MCP был вчера. Skills - сегодня. REPL-подход - завтра. И это завтра уже наступило.
Начните с малого. Добавьте REPL-навык в своего агента. Дайте ему возможность генерировать простые скрипты для обработки файлов. Увидите - через неделю вы не сможете представить работу без этого. Потому что это не просто еще одна фича. Это изменение парадигмы.