本地 Shell 是一种允许智能体在您或用户提供的机器上本地运行 Shell 命令的工具。它旨在与 Codex CLI 和 codex-mini-latest 配合使用。命令在您自己的运行环境中执行,您完全掌控实际运行哪些命令——API 仅返回指令,不会在 OpenAI 基础设施上执行它们。
本地 Shell 可通过 Responses API 配合 codex-mini-latest 使用。它不适用于其他模型,也不支持通过 Chat Completions API 使用。
它是如何工作的
本地 Shell 工具使智能体能够在拥有终端访问权限的情况下持续循环运行。
它发送 Shell 命令,您的代码在本地机器上执行这些命令,然后将输出返回给模型。这种循环允许模型无需用户额外干预即可完成“构建-测试-运行”循环。
作为代码的一部分,您需要实现一个循环,监听 local_shell_call 输出项并执行其中包含的命令。我们强烈建议对这些命令的执行进行沙箱化,以防止执行任何未经授权的意外命令。
集成本地 Shell 工具
要将计算机使用工具集成到您的应用程序中,需要遵循以下高级步骤:
-
向模型发送请求:将
local_shell工具作为可用工具的一部分包含在内。 -
接收来自模型的响应:检查响应中是否有任何
local_shell_call项。此工具调用包含诸如exec之类的操作以及要执行的命令。 -
执行请求的操作:通过代码在计算机或容器环境中执行相应的操作。
-
返回操作输出:执行操作后,将命令输出和诸如状态码之类的元数据返回给模型。
-
重复:使用更新后的状态作为
local_shell_call_output发送新请求,并重复此循环,直到模型停止请求操作或您决定停止为止。
工作流示例
以下是一个展示请求/响应循环的极简(Python)示例。为简洁起见,省略了错误处理和安全检查——在没有额外保障措施的情况下,请勿在生产环境中执行不受信任的命令。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import os
import shlex
import subprocess
from openai import OpenAI
client = OpenAI()
# 1) Create the initial response request with the tool enabled
response = client.responses.create(
model="codex-mini-latest",
tools=[{"type": "local_shell"}],
input=[
{
"role": "user",
"content": [
{"type": "input_text", "text": "List files in the current directory"},
],
}
],
)
while True:
# 2) Look for a local_shell_call in the model's output items
shell_calls = []
for item in response.output:
item_type = getattr(item, "type", None)
if item_type == "local_shell_call":
shell_calls.append(item)
elif item_type == "tool_call" and getattr(item, "tool_name", None) == "local_shell":
shell_calls.append(item)
if not shell_calls:
# No more commands — the assistant is done.
break
call = shell_calls[0]
args = getattr(call, "action", None) or getattr(call, "arguments", None)
# 3) Execute the command locally (here we just trust the command!)
# The command is already split into argv tokens.
def _get(obj, key, default=None):
if isinstance(obj, dict):
return obj.get(key, default)
return getattr(obj, key, default)
timeout_ms = _get(args, "timeout_ms")
command = _get(args, "command")
if not command:
break
if isinstance(command, str):
command = shlex.split(command)
completed = subprocess.run(
command,
cwd=_get(args, "working_directory") or os.getcwd(),
env={**os.environ, **(_get(args, "env") or {})},
capture_output=True,
text=True,
timeout=(timeout_ms / 1000) if timeout_ms else None,
)
output_item = {
"type": "local_shell_call_output",
"call_id": getattr(call, "call_id", None),
"output": completed.stdout + completed.stderr,
}
# 4) Send the output back to the model to continue the conversation
response = client.responses.create(
model="codex-mini-latest",
tools=[{"type": "local_shell"}],
previous_response_id=response.id,
input=[output_item],
)
# Print the assistant's final answer
print(response.output_text)最佳实践
- 沙箱化或容器化执行。考虑使用 Docker、firejail 或受限用户帐户。
- 施加资源限制(时间、内存、网络)。模型提供的
timeout_ms仅供参考,您应该强制执行自己的限制。 - 过滤或审查高风险命令(例如
rm、curl、网络工具)。 - 记录每一个命令及其输出,以便于审计和调试。
错误处理
如果命令在您侧失败(非零退出码、超时等),您仍然可以发送 local_shell_call_output;请将错误信息包含在 output 字段中。
模型可以选择恢复或尝试执行不同的命令。如果您发送的数据格式错误(例如缺少 call_id),API 将返回标准的 400 验证错误。