셸 도구는 응답 API 호출의 일부로 전체 터미널 환경에서 명령을 실행합니다. 스크립트를 실행하고, 파일로 작업하고, 프로그램을 실행하는 데 사용합니다. 셸 도구는 다음 두 가지 실행 모드를 지원합니다.
- 호스트된 셸: Azure OpenAI는 요청에 대한 샌드박스 컨테이너를 프로비전하고 관리합니다.
-
로컬 셸: 사용자 고유의
shell_call런타임에서 모델의 작업을 실행하고 결과를 반환합니다.
응답 API를 통해서만 셸 도구에 액세스할 수 있습니다. 채팅 완료 API를 통해 사용할 수 없습니다.
Important
임의의 셸 명령을 실행하는 것은 위험할 수 있습니다. 항상 샌드박스 실행을 수행하고, 가능한 경우 허용 목록 또는 차단 목록을 적용하고, 감사에 대한 로그 도구 작업을 적용합니다.
메모
셸 도구에는 이를 지원하는 Azure OpenAI API 버전과 응답 API를 지원하는 모델 배포가 필요합니다. 프로덕션 환경에 배포하기 전에 대상 API 버전에 대한 지원을 확인합니다.
사전 요구 사항
- 응답 API 및 셸 도구를 지원하는 Azure OpenAI 모델이 배포되었습니다.
- 인증 방법:
- API 키 또는
- 마이크로소프트 Entra ID.
- 언어에 대한 클라이언트 라이브러리를 설치합니다.
-
Python:
pip install openai azure-identity -
JavaScript/TypeScript:
npm install openai @azure/identity -
Java: 프로젝트에
com.openai:openai-java및com.azure:azure-identity추가합니다.
-
Python:
- REST 예제의 경우
AZURE_OPENAI_API_KEY(API 키 흐름) 또는AZURE_OPENAI_AUTH_TOKEN(Microsoft Entra ID 흐름)을 설정합니다.
호스트된 셸을 사용하여 첫 번째 명령 실행
호스트된 셸은 시작하는 가장 빠른 방법입니다. Azure OpenAI가 요청에 대한 컨테이너를 프로비전하고 관리할 수 있도록 환경을 container_auto 설정합니다. 모델은 프롬프트에 따라 도구를 호출할지 여부를 결정합니다.
다음 예제에서는 gpt-5.5를 사용자 고유의 모델 배포 이름으로 바꾸세요.
from openai import OpenAI
from azure.identity import DefaultAzureCredential, get_bearer_token_provider
endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/"
token_provider = get_bearer_token_provider(
DefaultAzureCredential(), "https://ai.azure.com/.default"
)
# Create the client against the Azure OpenAI v1 endpoint.
openai = OpenAI(base_url=endpoint, api_key=token_provider)
# Run a command in an auto-provisioned hosted container.
response = openai.responses.create(
model="gpt-5.5",
tools=[{"type": "shell", "environment": {"type": "container_auto"}}],
input="Run: python --version && echo 'hello from the shell'",
)
print(response.output_text)
팁
이러한 예제는 Microsoft Entra ID 사용합니다. 대신 API 키를 사용하려면 api_key 키 값(Python 및 JavaScript)으로 설정하거나, 클라이언트를 빌드할 때 AzureApiKeyCredential 전달하거나(Java) api-key(REST) 대신 Authorization: Bearer 헤더를 보냅니다.
참조: Azure OpenAI Responses API 사용 | OpenAI Python SDK | OpenAI Node SDK | OpenAI Java SDK
호스트된 런타임 세부 정보
호스트된 컨테이너는 각 요청 또는 컨테이너 세션에 대해 관리되는 Linux 환경을 제공합니다.
- 런타임은
Debian 12을 기반으로 하며 시간이 지남에 따라 변경될 수 있습니다. - 기본 작업 디렉터리는
/mnt/data입니다. 이 디렉터리가 항상 존재하며 사용자가 다운로드할 수 있는 아티팩트에서 지원되는 경로입니다. - Python
3.11미리 설치됩니다. - 호스트된 셸은 대화형 TTY 세션을 지원하지 않으며, 명령은
sudo와 함께 실행되지 않습니다. - 호스트된 컨테이너에는 아웃바운드 네트워크 액세스 권한이 없습니다.
워크플로에 필요한 경우 컨테이너 내에서 서비스를 실행할 수 있습니다.
요청 간에 컨테이너 다시 사용
반복 워크플로의 경우 컨테이너를 한 번 만들고 이후 응답 API 호출에서 참조합니다. 컨테이너는 활성 상태인 동안 요청 간에 파일과 상태를 유지합니다.
먼저 컨테이너를 만듭니다.
# Create a reusable container.
container = openai.containers.create(
name="analysis-container",
expires_after={"anchor": "last_active_at", "minutes": 20},
)
print(container.id)
그런 다음, 셸 요청에서 ID별로 컨테이너를 참조합니다.
# Reference the existing container in a shell request.
response = openai.responses.create(
model="gpt-5.5",
tools=[{
"type": "shell",
"environment": {
"type": "container_reference",
"container_id": container.id,
},
}],
input="List files in the container and show disk usage.",
)
print(response.output_text)
턴 간에 동일한 컨테이너에서 작업을 계속하려면 이전 응답의 previous_response_id와 동일한 container_id를 전달하세요.
로컬 셸 모드에서 명령 실행
로컬 셸 모드에서는 호스트된 컨테이너 대신 사용자 고유의 런타임에서 모델의 명령을 실행합니다. 실행 환경, 파일 시스템 액세스 또는 기존 내부 도구를 완전히 제어해야 하는 경우 이 모드를 사용합니다.
환경을 .로 local설정합니다. 모델은 실행할 명령을 설명하는 항목을 반환 shell_call 합니다.
response = openai.responses.create(
model="gpt-5.5",
instructions="The local shell environment is on Linux.",
input="Find the largest PDF file in the current directory.",
tools=[{"type": "shell", "environment": {"type": "local"}}],
)
print(response.model_dump_json(indent=2))
항목을 받으면 shell_call 요청된 명령을 실행하고 출력을 캡처한 다음 다음 요청과 같이 shell_call_output 결과를 반환합니다. 다음 실행기는 stdout, stderr 및 종료 결과를 캡처하고 시간 초과를 처리합니다.
import subprocess
from dataclasses import dataclass
@dataclass
class CmdResult:
stdout: str
stderr: str
exit_code: int | None
timed_out: bool
def run_command(cmd: str, timeout: float = 60) -> CmdResult:
process = subprocess.Popen(
cmd, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, text=True,
)
try:
out, err = process.communicate(timeout=timeout)
return CmdResult(out, err, process.returncode, False)
except subprocess.TimeoutExpired:
process.kill()
out, err = process.communicate()
return CmdResult(out, err, process.returncode, True)
응답에서의 셸 출력
호스트된 셸 및 로컬 셸은 동일한 출력 항목 유형을 사용합니다. 각 셸 실행은 항목 쌍으로 표시됩니다.
-
shell_call: 모델이 요청하는 명령입니다. -
shell_call_output: 명령 출력 및 종료 결과입니다.
모델은 shell_call 항목으로 명령을 요청합니다:
{
"type": "shell_call",
"call_id": "call_<id>",
"action": {
"commands": ["ls -l"],
"timeout_ms": 120000,
"max_output_length": 4096
},
"status": "in_progress"
}
shell_call_output 항목과 함께 결과를 반환합니다:
{
"type": "shell_call_output",
"call_id": "call_<id>",
"max_output_length": 4096,
"output": [
{
"stdout": "...",
"stderr": "",
"outcome": { "type": "exit", "exit_code": 0 }
}
]
}
shell_call에 max_output_length이 포함된 경우 shell_call_output에도 동일한 값을 포함합니다. 명령이 실행 제한 시간을 초과하면 timeout 결과를 반환하고 캡처한 부분 출력도 포함하세요.
아티팩트 다운로드
호스트된 셸은 다운로드 가능한 파일을 생성할 수 있습니다. 아티팩트 검색을 위해 아티팩트 아래에 /mnt/data작성한 다음 코드 인터프리터에서 사용하는 것과 동일한 컨테이너 및 파일 API를 사용하여 아티팩트 및 파일을 다운로드합니다.
데이터 보존 및 컨테이너 수명 주기
- 호스트된 컨테이너 세션은 유휴 시간 20분 후에 종료됩니다.
- 호스트된 컨테이너는 생성된 후 1시간 후에 삭제됩니다. 컨테이너가 삭제되면 컨테이너에 저장된 모든 데이터가 제거됩니다.
호스트된 컨테이너는 컨테이너가 활성 상태인 동안 임시 블록 스토리지를 통해 지원되는 임시 애플리케이션 상태를 컨테이너 파일 시스템에 쓸 수 있습니다. 컨테이너 데이터는 컨테이너가 만료되거나 삭제될 때 삭제됩니다.
일반적인 오류 처리
-
시간 제한: 명령이 실행 시간 제한을 초과하는 경우 결과를 반환
timeout하고 캡처한 부분 출력을 포함합니다. -
잘린 출력:
shell_call에max_output_length이 있으면shell_call_output에도 동일한 값을 설정합니다. - 대화형 명령: 셸 도구 실행은 비대화형입니다. 입력을 요청하는 명령에 의존하지 마세요.
- 0이 아닌 종료: 모델이 복구 단계를 추론할 수 있도록 0이 아닌 종료의 출력을 유지합니다.