Diese Funktion ist für Zero Data Retention (ZDR) qualifiziert. Wenn deine Organisation eine ZDR-Vereinbarung hat, werden Daten, die über diese Funktion gesendet werden, nicht gespeichert, nachdem die API-Antwort zurückgegeben wurde.
Das Bash-Tool ist ein Client-Tool: Claude führt Befehle nicht selbst aus. Wenn du das Tool in eine Anfrage einbindest, antwortet Claude mit einem tool_use-Block, der den auszuführenden Befehl benennt. Deine Anwendung führt diesen Befehl in einer Bash-Session aus, die ihr gehört, und gibt die Ausgabe in einem tool_result-Block zurück.
Deine Anwendung hält einen Bash-Prozess über Tool-Aufrufe hinweg am Leben, sodass der Zustand zwischen Befehlen erhalten bleibt. Das Arbeitsverzeichnis, Umgebungsvariablen und alle Dateien, die ein Befehl erstellt, sind für den nächsten Befehl noch vorhanden.
Die aktuelle Version des Tools ist bash_20250124. Für Modellunterstützung, Beta-Header und die frühere Version siehe Tool-Versionen. Für alle von Anthropic bereitgestellten Tools siehe die Tool-Referenz.
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
tools=[{"type": "bash_20250124", "name": "bash"}],
messages=[
{"role": "user", "content": "List all Python files in the current directory."}
],
)
print(response)Claude antwortet mit stop_reason: "tool_use" und einem tool_use-Block, der den Befehl enthält, den deine Anwendung ausführen soll:
{
"id": "msg_01XAbCDeFgHiJkLmNoPQrStU",
"model": "claude-opus-4-8",
"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"
}
}
]
}Führe input.command in deiner Bash-Session aus und sende die Ausgabe als tool_result zurück. Siehe Das Bash-Tool implementieren für den vollständigen Ablauf.
Jeder Tool-Aufruf ist ein Hin und Zurück zwischen Claude und deiner Anwendung:
tool_use-Block zurück, der den auszuführenden command enthält.tool_result-Block an Claude zurück.Claude kann auch mehrere tool_use-Blöcke in einer Antwort zurückgeben. Führe sie der Reihe nach in derselben Session aus und gib alle Ergebnisse in einer user-Nachricht zurück. Siehe Parallele Tool-Nutzung.
Die API ist zustandslos. Nichts von deiner Shell-Session wird zwischen Anfragen übertragen, daher entscheidet deine Anwendung, wann die Session startet, wie lange sie lebt und wann sie neu gestartet wird. Für den vollständigen Anfrage- und Antwortzyklus siehe Tool-Aufrufe verarbeiten.
Eine Bash-Tool-Definition hat zwei erforderliche Felder, type und name, und der name muss bash sein. Das Tool ist schemalos: Du gibst kein input_schema an, weil das Schema in Claudes Modell eingebaut ist und nicht verändert werden kann. Die folgende Tabelle listet die Eingabefelder auf, die Claude setzt, wenn es das Tool aufruft.
| Parameter | Erforderlich | Beschreibung |
|---|---|---|
command | Ja* | Der auszuführende Bash-Befehl |
restart | Nein | Auf true setzen, um die Bash-Session neu zu starten |
*Erforderlich, außer bei Verwendung von restart
Um restart: true zu verarbeiten, beende den Shell-Prozess, starte einen neuen und gib ein tool_result zurück, das den Neustart bestätigt. Eine neu gestartete Session beginnt sauber: Das Arbeitsverzeichnis, Umgebungsvariablen und alle laufenden Prozesse sind weg.
bash_20250124 ist die aktuelle Version des Tools und benötigt keinen Beta-Header. Jedes Modell ab Claude Sonnet 3.7 (eingestellt) akzeptiert es, einschließlich aller aktuellen Claude-Modelle.
Die ursprüngliche Version bash_20241022 ist Teil der Computer-Use-Beta, und die Claude Sonnet 3.5-Version vom Oktober 2024 (eingestellt) ist das einzige Modell, das sie akzeptiert. Anfragen, die sie verwenden, benötigen den Header anthropic-beta: computer-use-2024-10-22, und die SDKs stellen sie nur in ihren Beta-Namespaces bereit. Neue Integrationen sollten bash_20250124 verwenden.
Claude kann Befehle über Tool-Aufrufe hinweg verketten, um eine mehrstufige Aufgabe abzuschließen:
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"}Die Session behält den Zustand zwischen Befehlen bei, sodass Dateien, die in Schritt 2 erstellt wurden, in Schritt 3 verfügbar sind.
Claude bestimmt, welcher Befehl ausgeführt wird. Deine Anwendung besitzt alles andere: den Shell-Prozess, das Timeout und die Sicherheitsprüfungen. Die folgenden Schritte zeigen eine minimale Implementierung.
Erstelle eine persistente Bash-Session
Starte einen langlebigen Bash-Prozess und führe jeden Befehl darin aus. Da eine Pipe zu einem laufenden Prozess niemals ein Dateiende meldet, gibt die Session nach jedem Befehl eine eindeutige Sentinel-Zeile aus, um zu markieren, wo die Ausgabe dieses Befehls endet:
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 stateDie Session verschachtelt stderr mit stdout, sodass Fehlermeldungen dort landen, wo sie aufgetreten sind. Das Beispiel lässt aus, was eine vollständige Implementierung zusätzlich benötigt: ein Timeout, das die Shell und jeden von ihr gestarteten Prozess beendet, wenn ein Befehl hängt, und dann die Session neu startet. Die Best Practice Befehls-Timeouts verwenden zeigt eine Möglichkeit, dies hinzuzufügen.
Verarbeite Claudes Tool-Aufrufe
Extrahiere und führe Befehle aus Claudes Antworten aus:
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)
# Ein tool_result pro tool_use-Block, alle in der nächsten User-Nachricht zurückgegeben
tool_results.append(
{"type": "tool_result", "tool_use_id": content.id, "content": result}
)Gib das Ergebnis an Claude zurück
Sende das tool_result in einer user-Nachricht zurück, die dieselbe Konversation fortsetzt. Claude fordert entweder einen weiteren Befehl in derselben Session an oder schließt seine Antwort ab:
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-8",
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)Wiederhole den Ausführen-und-Zurückgeben-Zyklus, solange stop_reason gleich tool_use ist. Für die vollständige Schleife siehe Ergebnisse von Client-Tools verarbeiten.
Implementiere Sicherheitsmaßnahmen
Füge Validierung und Einschränkungen hinzu. Verwende eine Allowlist statt einer Blocklist: Eine Blocklist übersieht jeden Befehl, den sie nicht vorhergesehen hat. Das Beispiel lehnt auch Shell-Operatoren ab, die als separate Wörter erscheinen:
import shlex
ALLOWED_COMMANDS = {"ls", "cat", "echo", "pwd", "grep", "find", "wc", "head", "tail"}
SHELL_OPERATORS = {"&&", "||", "|", ";", "&", ">", "<", ">>"}
def validate_command(command):
# Erlaube nur Befehle aus einer expliziten Allowlist
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"
# Lehne Shell-Operatoren ab, die als separate Wörter geschrieben sind
for token in tokens[1:]:
if token in SHELL_OPERATORS or token.startswith(("$", "`")):
return False, f"Shell operator '{token}' is not allowed"
return True, NoneDiese Prüfung ist ein Stolperdraht für offensichtliche Fehler, keine Durchsetzungsgrenze. Sie lehnt die mit Leerzeichen getrennte Verkettung (&&), Pipes und Umleitungen ab, die die anderen Beispiele auf dieser Seite verwenden. Sie erkennt keinen Operator, der an ein Wort angehängt ist, wie cat data.txt|grep x, weil der Tokenizer data.txt|grep in einem Token belässt. Entscheide, welche Befehle und Operatoren deine Anwendung erlaubt. Die eigentliche Kontrolle ist Isolation: Führe die gesamte Session in einem Container oder einer virtuellen Maschine aus (siehe Sicherheit).
Wenn ein Befehl fehlschlägt oder die Session abbricht, teile Claude mit, was passiert ist. Gib die Nachricht als tool_result-Inhalt zurück und setze is_error auf true, was den Tool-Aufruf als fehlgeschlagen markiert. Siehe Fehlerbehandlung mit is_error.
Deine Anwendung führt jeden Befehl aus, den Claude anfordert. Führe die Session in einer isolierten Umgebung aus, etwa einem Container oder einer virtuellen Maschine, als der Benutzer mit den geringsten Rechten, der die Arbeit erledigen kann. Behandle jeden Befehl als nicht vertrauenswürdige Eingabe.
Füge über die Isolation hinaus diese Kontrollen hinzu:
ulimit.Die Bash-Tool-Definition fügt deiner Anfrage die folgenden Input-Token hinzu. Dies kommt zusätzlich zum modellspezifischen System-Prompt für Tool-Nutzung, der immer dann gilt, wenn ein Tool vorhanden ist.
| Modell | Zusätzliche Input-Token |
|---|---|
| Claude Opus 4.7 und Claude Opus 4.8 | 325 Token |
| Claude Opus 4.6, Claude Sonnet 4.6 und früher | 244 Token |
Zusätzliche Token werden verbraucht durch:
Siehe Preise für Tool-Nutzung für vollständige Preisdetails.
pytest && coverage reportnpm install && npm run buildgit status && git add . && git commit -m "message"Für Hinweise zur Verwendung von Git als Checkpoint-und-Wiederherstellungsmechanismus in langlaufenden Agenten-Workflows siehe Best Practices für Zustandsverwaltung.
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, Passwortabfragen oder andere Befehle, die auf Eingaben über stdin warten, nicht ausführen.tool_result in der nächsten Anfrage zurückgibt.Das Bash-Tool passt gut zum Texteditor-Tool: Claude bearbeitet eine Datei mit dem einen Tool und fordert mit dem anderen den Befehl an, der sie ausführt.
Wenn du auch das Code-Execution-Tool verwendest, hat Claude Zugriff auf zwei separate Ausführungsumgebungen: deine lokale Bash-Session und Anthropics Sandbox-Container. Der Zustand wird nicht zwischen ihnen geteilt. Siehe Code-Ausführung mit anderen Ausführungstools verwenden für Hinweise, wie du Claude dazu anleitest, zwischen den Umgebungen zu unterscheiden.
Zeige Textdateien an und ändere sie, um Code zu debuggen, zu korrigieren und zu verbessern.
Verbinde Claude mit externen Tools und APIs. Sieh, wo Tools ausgeführt werden, wann Claude sie aufruft und welches Tool zu deiner Aufgabe passt.
Was this page helpful?