Lo strumento bash è uno strumento client: Claude non esegue i comandi direttamente. Quando includi lo strumento in una richiesta, Claude risponde con un blocco tool_use che specifica il comando da eseguire. La tua applicazione esegue quel comando in una sessione bash di sua proprietà e restituisce l'output in un blocco tool_result.
La tua applicazione mantiene attivo un singolo processo bash tra le chiamate allo strumento, quindi lo stato persiste tra i comandi. La directory di lavoro, le variabili d'ambiente e qualsiasi file creato da un comando sono ancora presenti per il comando successivo.
La versione corrente dello strumento è bash_20250124. Per il supporto dei modelli, gli header beta e la versione precedente, consulta Versioni dello strumento. Per tutti gli strumenti forniti da Anthropic, consulta il Riferimento degli strumenti.
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 risponde con stop_reason: "tool_use" e un blocco tool_use che contiene il comando che la tua applicazione deve eseguire:
{
"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"
}
}
]
}Esegui input.command nella tua sessione bash e invia l'output come tool_result. Consulta Implementare lo strumento bash per il ciclo completo.
Ogni chiamata allo strumento è un ciclo di andata e ritorno tra Claude e la tua applicazione:
tool_use contenente il command da eseguire.tool_result.Claude può anche restituire diversi blocchi tool_use in una singola risposta. Eseguili in ordine nella stessa sessione e restituisci tutti i risultati in un unico messaggio user. Consulta Uso parallelo degli strumenti.
L'API è stateless. Nessuna informazione sulla tua sessione shell viene trasmessa tra le richieste, quindi la tua applicazione decide quando la sessione inizia, quanto dura e quando riavviarla. Per il ciclo completo di richiesta e risposta, consulta Gestire le chiamate agli strumenti.
Una definizione dello strumento bash ha due campi obbligatori, type e name, e il name deve essere bash. Lo strumento è privo di schema: non fornisci un input_schema, perché lo schema è integrato nel modello di Claude e non può essere modificato. La tabella seguente elenca i campi di input che Claude imposta quando chiama lo strumento.
| Parametro | Obbligatorio | Descrizione |
|---|---|---|
command | Sì* | Il comando bash da eseguire |
restart | No | Imposta a true per riavviare la sessione bash |
*Obbligatorio a meno che non si utilizzi restart
Per gestire restart: true, termina il processo shell, avviane uno nuovo e restituisci un tool_result che conferma il riavvio. Una sessione riavviata parte pulita: la directory di lavoro, le variabili d'ambiente e qualsiasi processo in esecuzione non sono più presenti.
bash_20250124 è la versione corrente dello strumento e non richiede alcun header beta. Ogni modello da Claude Sonnet 3.7 (ritirato) in poi la accetta, inclusi tutti i modelli Claude attuali.
La versione originale bash_20241022 fa parte della beta di computer use, e la release di Claude Sonnet 3.5 di ottobre 2024 (ritirata) è l'unico modello che la accetta. Le richieste che la utilizzano necessitano dell'header anthropic-beta: computer-use-2024-10-22, e gli SDK la espongono solo nei loro namespace beta. Le nuove integrazioni dovrebbero utilizzare bash_20250124.
Claude può concatenare comandi tra le chiamate allo strumento per completare un'attività multi-step:
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"}La sessione mantiene lo stato tra i comandi, quindi i file creati nel passaggio 2 sono disponibili nel passaggio 3.
Claude determina quale comando eseguire. La tua applicazione possiede tutto il resto: il processo shell, il timeout e i controlli di sicurezza. I passaggi seguenti mostrano un'implementazione minima.
Crea una sessione bash persistente
Avvia un processo bash a lunga durata ed esegui ogni comando al suo interno. Poiché una pipe verso un processo attivo non segnala mai la fine del file, la sessione stampa una riga sentinella univoca dopo ogni comando per indicare dove termina l'output di quel comando:
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 stateLa sessione intercala stderr con stdout, quindi i messaggi di errore appaiono dove si sono verificati. L'esempio omette ciò che un'implementazione completa richiede anche: un timeout che termina la shell e ogni processo che ha avviato quando un comando si blocca, quindi riavvia la sessione. La best practice Usa timeout per i comandi mostra un modo per aggiungerlo.
Elabora le chiamate agli strumenti di Claude
Estrai ed esegui i comandi dalle risposte di 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)
# Un tool_result per ogni blocco tool_use, tutti restituiti nel messaggio utente successivo
tool_results.append(
{"type": "tool_result", "tool_use_id": content.id, "content": result}
)Restituisci il risultato a Claude
Invia il tool_result in un messaggio user che continua la stessa conversazione. Claude richiede un altro comando nella stessa sessione oppure completa la sua risposta:
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)Ripeti il ciclo di esecuzione e restituzione finché stop_reason è tool_use. Per il ciclo completo, consulta Gestione dei risultati dagli strumenti client.
Implementa misure di sicurezza
Aggiungi validazione e restrizioni. Usa una allowlist piuttosto che una blocklist: una blocklist non rileva i comandi che non ha previsto. L'esempio rifiuta anche gli operatori shell che appaiono come parole separate:
import shlex
ALLOWED_COMMANDS = {"ls", "cat", "echo", "pwd", "grep", "find", "wc", "head", "tail"}
SHELL_OPERATORS = {"&&", "||", "|", ";", "&", ">", "<", ">>"}
def validate_command(command):
# Consenti solo i comandi presenti in una allowlist esplicita
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"
# Rifiuta gli operatori di shell scritti come parole separate
for token in tokens[1:]:
if token in SHELL_OPERATORS or token.startswith(("$", "`")):
return False, f"Shell operator '{token}' is not allowed"
return True, NoneQuesto controllo è un filo d'inciampo per errori evidenti, non un confine di applicazione. Rifiuta il concatenamento con spazi (&&), le pipe e il reindirizzamento che gli altri esempi in questa pagina utilizzano. Non rileva un operatore attaccato a una parola, come cat data.txt|grep x, perché il tokenizer mantiene data.txt|grep all'interno di un singolo token. Decidi quali comandi e operatori la tua applicazione consente. Il vero controllo è l'isolamento: esegui l'intera sessione all'interno di un container o di una macchina virtuale (consulta Sicurezza).
Quando un comando fallisce o la sessione si interrompe, comunica a Claude cosa è successo. Restituisci il messaggio come contenuto del tool_result e imposta is_error a true, che contrassegna la chiamata allo strumento come fallita. Consulta Gestione degli errori con is_error.
Oltre all'isolamento, aggiungi questi controlli:
ulimit.La definizione dello strumento bash aggiunge i seguenti token di input alla tua richiesta. Questo si aggiunge al prompt di sistema per l'uso degli strumenti specifico per modello che si applica ogni volta che è presente uno strumento.
| Modello | Token di input aggiuntivi |
|---|---|
| Claude Opus 5, Claude Opus 4.8 e Claude Opus 4.7 | 325 token |
| Claude Opus 4.6, Claude Sonnet 4.6 e precedenti | 244 token |
Token aggiuntivi vengono consumati da:
Consulta prezzi dell'uso degli strumenti per i dettagli completi sui prezzi.
pytest && coverage reportnpm install && npm run buildgit status && git add . && git commit -m "message"Per indicazioni sull'uso di git come meccanismo di checkpoint e ripristino nei flussi di lavoro agentici a lunga durata, consulta best practice per la gestione dello stato.
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, prompt di password o qualsiasi comando che attende input su stdin.tool_result nella richiesta successiva.Lo strumento bash si abbina bene con lo strumento Text editor: Claude modifica un file con uno strumento e richiede il comando che lo esegue con l'altro.
Visualizza e modifica file di testo per eseguire il debug, correggere e migliorare il codice.
Connetti Claude a strumenti e API esterni. Scopri dove vengono eseguiti gli strumenti, quando Claude li chiama e quale strumento è adatto alla tua attività.
Was this page helpful?