
Песочница с нулевым доверием для AI-агентов, включающая изоляцию файловой системы на уровне ядра, прозрачный сетевой прокси и движок политик на основе YAML для перехвата и контроля команд оболочки, файловых операций и сетевых запросов.
Песочница с нулевым доверием для автономных AI-агентов.
AgentGuard оборачивает любого AI-агента (LangChain, CrewAI, AutoGen, пользовательские скрипты) в защитные ограничения. Изменение одной команды:
# До (опасно — агент имеет полный доступ к системе)
python my_agent.py
# После (в песочнице)
agentguard run -- python my_agent.py
AgentGuard перехватывает каждую команду оболочки, изменение файла и сетевой запрос, которые совершает агент. Безопасные действия автоматически разрешаются, опасные — автоматически блокируются, а всё остальное запрашивает одобрение человека.
AgentGuard имеет четыре уровня защиты, работающих вместе:
┌─────────────────────────────────────────────────────────────┐
│ Уровень 0: Файловая изоляция (sandbox-exec на macOS) │
│ Принудительное выполнение на уровне ядра. Ограничивает │
│ запись файлов и сеть на уровне системных вызовов. Агент │
│ не может обойти из пользовательского пространства. │
│ Блокирует Python open(), requests.post() и т.д. │
├─────────────────────────────────────────────────────────────┤
│ Уровень 1: Сетевой прокси │
│ Прозрачный HTTP/HTTPS-прокси. Каждый сетевой вызов агента │
│ проверяется на соответствие политике. Разрешение/запрет │
│ для каждого назначения с полной видимостью в TUI. │
├─────────────────────────────────────────────────────────────┤
│ Уровень 2: PATH-заглушки (Shims) │
│ Скрипты-заглушки, перехватывающие команды типа git, │
│ pip, curl, rm. Каждая заглушка запрашивает разрешение │
│ у демона перед запуском реального бинарника. │
├─────────────────────────────────────────────────────────────┤
│ Уровень 3: Механизм политик + Демон одобрения │
│ Правила на основе YAML оценивают каждое перехваченное │
│ действие. Автоматически разрешают безопасные команды, │
│ автоматически блокируют опасные, а всё остальное │
│ запрашивает у человека. │
└─────────────────────────────────────────────────────────────┘
Ни один уровень не является единственной границей безопасности. Они работают вместе — защита в глубину.
go build -o agentguard ./cmd/agentguard/
go build -o agentguard-check ./cmd/agentguard-check/
Оба бинарника должны находиться в одном каталоге.
agentguard init
Это создаёт файл .agentguard/policy.yaml в текущем каталоге. Отредактируйте его под свои нужды.
agentguard run -- python my_agent.py
TUI перехватывает управление терминалом и показывает:
Для интерактивных инструментов, таких как Claude Code, которым нужен терминал:
agentguard run --headless -- claude
Агент получает терминал напрямую. AgentGuard работает в фоне без вывода. Все события записываются в ~/.agentguard/logs/headless.log. Следите в другом терминале:
tail -f ~/.agentguard/logs/headless.log
agentguard run [flags] -- <команда> [аргументы...]
--policy <путь> Использовать определённый файл политики
--headless Без TUI — агент получает терминал
--default-allow Автоматически разрешать решения PROMPT в безголовом режиме (по умолчанию: auto-deny)
--no-sandbox Отключить sandbox-exec (заглушки и прокси остаются активными)
agentguard init Создать файл политики по умолчанию
agentguard version Показать версию
Политики — это YAML-файлы, определяющие, что агенту разрешено, а что запрещено. AgentGuard проверяет три расположения (по порядку):
./.agentguard/policy.yaml (локальный для проекта)~/.agentguard/policy.yaml (глобальный для пользователя)version: 1
deny:
# Блокировать опасные команды
- command: "rm"
args: "-rf *"
reason: "Рекурсивное принудительное удаление слишком опасно"
- command: "sudo"
args: "*"
reason: "Повышение привилегий не разрешено"
- command: "chmod"
args: "777 *"
reason: "Права доступа для всех пользователей опасны"
# Блокировать чтение конфиденциальных файлов (принудительно через sandbox-exec)
- file:
path: "*.env"
action: "read"
reason: "Не позволяйте агенту читать .env файлы"
- file:
path: "*.pem"
action: "read"
reason: "Не позволяйте агенту читать закрытые ключи"
allow:
# Безопасные команды только для чтения
- command: "ls"
- command: "cat"
- command: "pwd"
- command: "echo"
- command: "grep"
- command: "head"
- command: "tail"
- command: "wc"
# Git только для чтения
- command: "git"
args: "status"
- command: "git"
args: "log *"
- command: "git"
args: "diff *"
# Разрешить запись в рабочую область
- file:
path: "/tmp/workspace/**"
action: "write"
# Разрешить определённые API-эндпоинты
- network:
destination: "api.anthropic.com:443"
- network:
destination: "api.github.com:443"
deny network *) — проверяются третьими. Действуют как запрет по умолчанию.Правила команд — сопоставляют команды оболочки по имени и шаблону аргументов:
- command: "git"
args: "push *"
reason: "Отправка требует одобрения"
Правила файлов — сопоставляют операции с файлами (принудительно через sandbox-exec):
- file:
path: "*.env"
action: "read" # "read" или "write"
reason: "Защитить секреты"
Правила сети — сопоставляют сетевые назначения (принудительно через прокси + sandbox-exec):
- network:
destination: "api.anthropic.com:443"
Используйте * как подстановочный знак в аргументах команд, путях файлов и сетевых назначениях.
| Клавиша | Действие | Когда |
|---|---|---|
Y | Разрешить ожидающий запрос | Виден запрос на одобрение |
N | Запретить ожидающий запрос | Виден запрос на одобрение |
A | Разрешить и запомнить на эту сессию ("Всегда разрешать") | Виден запрос на одобрение |
B | Запретить и запомнить на эту сессию ("Блокировать навсегда") | Виден запрос на одобрение |
Tab | Переключить панель stdout/stderr агента | Всегда |
Вверх/Вниз | Прокрутка потока событий | Всегда |
Q | Выйти (завершает агента) | Всегда |
| Действие агента | Заглушки | Прокси | sandbox-exec |
|---|---|---|---|
subprocess.run(["rm", "-rf", "/"]) | Да | - | - |
subprocess.run(["git", "push"]) | Да | - | - |
requests.post("https://evil.com") | - | Да | Да |
urllib.request.urlopen("https://api.com") | - | Да | Да |
open(".env", "r") | - | - | Да |
open("/etc/shadow", "w") | - | - | Да |
/usr/bin/curl https://evil.com (абсолютный путь) | - | Да | Да |