关于"zero data retention"(零数据保留),即 ZDR 如何适用于此功能,请参阅 API 与数据保留。
Bash 工具是一个客户端工具:Claude 本身不运行命令。当您在请求中包含该工具时,Claude 会回复一个 tool_use 块,其中指明要运行的命令。您的应用程序在其拥有的 bash 会话中运行该命令,并在 tool_result 块中返回输出。
您的应用程序在多次工具调用之间保持一个 bash 进程存活,因此状态会在命令之间持久保留。工作目录、环境变量以及命令创建的任何文件在下一个命令执行时仍然存在。
该工具的当前版本是 bash_20250124。有关模型支持、beta 标头和早期版本,请参阅工具版本。有关 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"
}
}
]
}在您的 bash 会话中运行 input.command,并将输出作为 tool_result 发送回去。有关完整的往返流程,请参阅实现 bash 工具。
每次工具调用都是 Claude 与您的应用程序之间的一次往返:
command 的 tool_use 块。tool_result 块返回给 Claude。Claude 也可以在一次响应中返回多个 tool_use 块。请在同一会话中按顺序运行它们,并在一条 user 消息中返回所有结果。请参阅并行工具使用。
API 是无状态的。您的 shell 会话的任何信息都不会在请求之间传递,因此由您的应用程序决定会话何时开始、存活多久以及何时重启。有关完整的请求和响应周期,请参阅处理工具调用。
Bash 工具定义有两个必需字段:type 和 name,且 name 必须为 bash。该工具是无模式(schema-less)的:您无需提供 input_schema,因为该模式已内置于 Claude 的模型中且无法修改。下表列出了 Claude 调用该工具时设置的输入字段。
| 参数 | 必需 | 描述 |
|---|---|---|
command | 是* | 要运行的 bash 命令 |
restart | 否 | 设置为 true 以重启 bash 会话 |
*除非使用 restart,否则为必需
要处理 restart: true,请终止 shell 进程,启动一个新进程,并返回一个确认重启的 tool_result。重启后的会话是全新的:工作目录、环境变量以及任何正在运行的进程都会消失。
bash_20250124 是该工具的当前版本,不需要 beta 标头。从 Claude Sonnet 3.7(已停用)开始的所有模型都接受它,包括所有当前的 Claude 模型。
最初的 bash_20241022 版本是计算机使用(computer use)beta 的一部分,2024 年 10 月发布的 Claude Sonnet 3.5(已停用)是唯一接受它的模型。使用它的请求需要 anthropic-beta: computer-use-2024-10-22 标头,并且 SDK 仅在其 beta 命名空间中公开它。新的集成应使用 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 决定要运行哪个命令。您的应用程序负责其他一切:shell 进程、超时和安全检查。以下步骤展示了一个最小化实现。
创建持久的 bash 会话
启动一个长期存活的 bash 进程,并在其中运行每个命令。由于连接到活动进程的管道永远不会报告文件结束(end-of-file),会话会在每个命令之后打印一个唯一的哨兵(sentinel)行,以标记该命令输出的结束位置:
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 交错输出,因此错误消息会出现在它们发生的位置。该示例省略了完整实现还需要的内容:当命令挂起时,需要一个超时机制来终止 shell 及其启动的所有进程,然后重启会话。使用命令超时最佳实践展示了一种添加方法。
处理 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_use 块对应一个 tool_result,全部在下一条用户消息中返回
tool_results.append(
{"type": "tool_result", "tool_use_id": content.id, "content": result}
)将结果返回给 Claude
在继续同一对话的 user 消息中将 tool_result 发送回去。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 时,重复运行并返回的循环。有关完整循环,请参阅处理客户端工具的结果。
实施安全措施
添加验证和限制。使用允许列表(allowlist)而不是阻止列表(blocklist):阻止列表会遗漏任何它未预料到的命令。该示例还会拒绝作为独立单词出现的 shell 运算符:
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"
# 拒绝以独立单词形式书写的 shell 运算符
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 处理错误。
您的应用程序会运行 Claude 请求的任何命令。请在隔离环境(例如容器或虚拟机)中以能够完成工作的最低权限用户身份运行会话。将每个命令都视为不可信的输入。
除了隔离之外,还应添加以下控制措施:
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 时,输出才会到达 Claude。Bash 工具与文本编辑器工具配合良好:Claude 使用一个工具编辑文件,并使用另一个工具请求运行该文件的命令。
如果您还在使用代码执行工具,Claude 可以访问两个独立的执行环境:您的本地 bash 会话和 Anthropic 的沙盒容器。它们之间不共享状态。有关提示 Claude 区分不同环境的指导,请参阅将代码执行与其他执行工具结合使用。
查看和修改文本文件以调试、修复和改进代码。
将 Claude 连接到外部工具和 API。了解工具在何处执行、Claude 何时调用它们,以及哪种工具适合您的任务。
Was this page helpful?