Инструмент bash — это клиентский инструмент: Claude не выполняет команды самостоятельно. Когда вы включаете инструмент в запрос, Claude отвечает блоком tool_use, в котором указана команда для выполнения. Ваше приложение выполняет эту команду в собственной сессии bash и возвращает вывод в блоке tool_result.
Ваше приложение поддерживает один процесс bash активным между вызовами инструмента, поэтому состояние сохраняется между командами. Рабочий каталог, переменные окружения и любые файлы, созданные командой, остаются доступными для следующей команды.
Текущая версия инструмента — bash_20250124. Информацию о поддержке моделей, бета-заголовках и более ранней версии см. в разделе Версии инструмента. Все инструменты, предоставляемые Anthropic, перечислены в Справочнике инструментов.
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5",
max_tokens=1024,
tools=[{"type": "bash_20250124", "name": "bash"}],
messages=[
{"role": "user", "content": "List all Python files in the current directory."}
],
)
print(response)Claude отвечает с stop_reason: "tool_use" и блоком tool_use, содержащим команду, которую должно выполнить ваше приложение:
{
"id": "msg_01XAbCDeFgHiJkLmNoPQrStU",
"model": "claude-opus-5",
"stop_reason": "tool_use",
"role": "assistant",
"content": [
{
"type": "text",
"text": "I'll list all Python files in the current directory for you."
},
{
"type": "tool_use",
"id": "toolu_01A09q90qw90lq917835lq9",
"name": "bash",
"input": {
"command": "ls *.py"
}
}
]
}Выполните input.command в вашей сессии bash и отправьте вывод обратно как tool_result. Полный цикл обмена описан в разделе Реализация инструмента bash.
Каждый вызов инструмента — это один цикл обмена между Claude и вашим приложением:
tool_use, содержащий команду command для выполнения.tool_result.Claude также может вернуть несколько блоков tool_use в одном ответе. Выполните их по порядку в той же сессии и верните все результаты в одном сообщении user. См. Параллельное использование инструментов.
API не хранит состояние. Никакая информация о вашей сессии оболочки не передаётся между запросами, поэтому ваше приложение решает, когда сессия начинается, как долго она существует и когда её перезапустить. Полный цикл запроса и ответа описан в разделе Обработка вызовов инструментов.
Определение инструмента bash содержит два обязательных поля — type и name, причём name должно быть равно bash. Инструмент не имеет схемы: вы не предоставляете input_schema, поскольку схема встроена в модель Claude и не может быть изменена. В следующей таблице перечислены поля ввода, которые Claude устанавливает при вызове инструмента.
| Параметр | Обязательный | Описание |
|---|---|---|
command | Да* | Команда bash для выполнения |
restart | Нет | Установите значение true, чтобы перезапустить сессию bash |
*Обязателен, если не используется restart
Чтобы обработать restart: true, завершите процесс оболочки, запустите новый и верните tool_result, подтверждающий перезапуск. Перезапущенная сессия начинается с чистого состояния: рабочий каталог, переменные окружения и все запущенные процессы исчезают.
bash_20250124 — текущая версия инструмента, и она не требует бета-заголовка. Её принимают все модели начиная с Claude Sonnet 3.7 (выведена из эксплуатации), включая все текущие модели Claude.
Исходная версия bash_20241022 является частью бета-версии computer use, и выпуск Claude Sonnet 3.5 от октября 2024 года (выведен из эксплуатации) — единственная модель, которая её принимает. Запросы, использующие её, требуют заголовка anthropic-beta: computer-use-2024-10-22, а SDK предоставляют её только в своих бета-пространствах имён. Новые интеграции должны использовать bash_20250124.
Claude может объединять команды в цепочку между вызовами инструмента для выполнения многошаговой задачи:
User request:
"Install the requests library and create a simple Python script that
fetches a joke from an API, then run it."
Claude's tool uses:
1. Install package
{"command": "pip install requests"}
2. Create script
{"command": "cat > fetch_joke.py << 'EOF'\nimport requests\nresponse = requests.get('https://official-joke-api.appspot.com/random_joke')\njoke = response.json()\nprint(f\"Setup: {joke['setup']}\")\nprint(f\"Punchline: {joke['punchline']}\")\nEOF"}
3. Run script
{"command": "python fetch_joke.py"}Сессия сохраняет состояние между командами, поэтому файлы, созданные на шаге 2, доступны на шаге 3.
Claude определяет, какую команду выполнить. Ваше приложение отвечает за всё остальное: процесс оболочки, тайм-аут и проверки безопасности. Следующие шаги показывают минимальную реализацию.
Создайте постоянную сессию bash
Запустите один долгоживущий процесс bash и выполняйте каждую команду внутри него. Поскольку канал к активному процессу никогда не сообщает о конце файла, сессия печатает уникальную строку-маркер после каждой команды, чтобы обозначить, где заканчивается вывод этой команды:
import subprocess
import uuid
class BashSession:
"""A bash process that stays alive between commands so state persists."""
def __init__(self):
self.process = subprocess.Popen(
["/bin/bash"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, # interleave errors with output, in order
start_new_session=True, # own process group: a timeout can kill every child
text=True,
)
def execute_command(self, command):
"""Run a command in the session and return its output."""
sentinel = f"__CLAUDE_BASH_DONE_{uuid.uuid4().hex}__" # unique per call
self.process.stdin.write(f"{command}\necho {sentinel}\n")
self.process.stdin.flush()
output = []
for line in self.process.stdout:
if sentinel in line: # this command's output is complete
break
output.append(line)
return "".join(output)
def restart(self):
self.process.kill()
self.process.wait()
self.__init__()
bash_session = BashSession()
print(bash_session.execute_command("cd /tmp && pwd"))
print(bash_session.execute_command("pwd")) # still /tmp: the session kept its stateСессия чередует stderr с stdout, поэтому сообщения об ошибках оказываются там, где они произошли. В примере опущено то, что также необходимо для полной реализации: тайм-аут, который завершает оболочку и все запущенные ею процессы, когда команда зависает, а затем перезапускает сессию. Рекомендация Используйте тайм-ауты команд показывает один из способов добавить это.
Обработайте вызовы инструмента от Claude
Извлеките и выполните команды из ответов Claude:
tool_results = []
for content in response.content:
if content.type == "tool_use" and content.name == "bash":
if content.input.get("restart"):
bash_session.restart()
result = "Bash session restarted"
else:
command = content.input.get("command")
result = bash_session.execute_command(command)
# Один tool_result на каждый блок tool_use, все возвращаются в следующем сообщении пользователя
tool_results.append(
{"type": "tool_result", "tool_use_id": content.id, "content": result}
)Верните результат Claude
Отправьте tool_result обратно в сообщении user, которое продолжает тот же разговор. Claude либо запросит другую команду в той же сессии, либо завершит свой ответ:
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5",
max_tokens=1024,
tools=[{"type": "bash_20250124", "name": "bash"}],
messages=[
{"role": "user", "content": "List all Python files in the current directory."},
{
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01A09q90qw90lq917835lq9",
"name": "bash",
"input": {"command": "ls *.py"},
}
],
},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"content": "analysis.py\nprocess_data.py\n",
}
],
},
],
)
print(response.content)Повторяйте цикл выполнения и возврата, пока stop_reason равен tool_use. Полный цикл описан в разделе Обработка результатов клиентских инструментов.
Реализуйте меры безопасности
Добавьте валидацию и ограничения. Используйте список разрешённых команд, а не список запрещённых: список запрещённых пропускает любую команду, которую он не предусмотрел. Пример также отклоняет операторы оболочки, которые появляются как отдельные слова:
import shlex
ALLOWED_COMMANDS = {"ls", "cat", "echo", "pwd", "grep", "find", "wc", "head", "tail"}
SHELL_OPERATORS = {"&&", "||", "|", ";", "&", ">", "<", ">>"}
def validate_command(command):
# Разрешать только команды из явного списка разрешённых
try:
tokens = shlex.split(command)
except ValueError:
return False, "Could not parse command"
if not tokens:
return False, "Empty command"
executable = tokens[0]
if executable not in ALLOWED_COMMANDS:
return False, f"Command '{executable}' is not in the allowlist"
# Отклонять операторы оболочки, записанные как отдельные слова
for token in tokens[1:]:
if token in SHELL_OPERATORS or token.startswith(("$", "`")):
return False, f"Shell operator '{token}' is not allowed"
return True, NoneЭта проверка — сигнализация для очевидных ошибок, а не граница контроля. Она отклоняет разделённые пробелами цепочки (&&), каналы и перенаправления, которые используются в других примерах на этой странице. Она не перехватывает оператор, склеенный со словом, например cat data.txt|grep x, потому что токенизатор оставляет data.txt|grep внутри одного токена. Решите, какие команды и операторы разрешает ваше приложение. Настоящий контроль — это изоляция: запускайте всю сессию внутри контейнера или виртуальной машины (см. Безопасность).
Когда команда завершается с ошибкой или сессия прерывается, сообщите Claude, что произошло. Верните сообщение как содержимое tool_result и установите is_error в true, что помечает вызов инструмента как неудачный. См. Обработка ошибок с помощью is_error.
Помимо изоляции, добавьте следующие меры контроля:
ulimit.Определение инструмента bash добавляет следующие входные токены к вашему запросу. Это в дополнение к системной подсказке использования инструментов для каждой модели, которая применяется всякий раз, когда присутствует любой инструмент.
| Модель | Дополнительные входные токены |
|---|---|
| Claude Opus 5, Claude Opus 4.8 и Claude Opus 4.7 | 325 токенов |
| Claude Opus 4.6, Claude Sonnet 4.6 и более ранние | 244 токена |
Дополнительные токены потребляются:
Полную информацию о ценах см. в разделе цены на использование инструментов.
pytest && coverage reportnpm install && npm run buildgit status && git add . && git commit -m "message"Рекомендации по использованию git как механизма контрольных точек и восстановления в длительных агентных рабочих процессах см. в разделе рекомендации по управлению состоянием.
wc -l *.csv && ls -lh *.csvfind . -name "*.py" | xargs grep "pattern"tar -czf backup.tar.gz ./datadf -h && free -mps aux | grep pythonexport PATH=$PATH:/new/path && echo $PATHvim, less, запросы пароля или любую команду, ожидающую ввода через stdin.tool_result в следующем запросе.Инструмент bash хорошо сочетается с инструментом текстового редактора: Claude редактирует файл одним инструментом и запрашивает команду для его запуска другим.
Просматривайте и изменяйте текстовые файлы для отладки, исправления и улучшения кода.
Подключайте Claude к внешним инструментам и API. Узнайте, где выполняются инструменты, когда Claude их вызывает и какой инструмент подходит для вашей задачи.
Was this page helpful?