모델 연결 전에 Computer Use API 컨트롤러 테스트하기

Python 오프라인 테스트 19개로 동작 검증, 스크린샷 호출 ID, 폼 완료 조건을 확인합니다. 실제 API 연동이 검증되지 않은 어댑터와 테스트 범위를 구분합니다.

모델 연결 전에 Computer Use API 컨트롤러 테스트하기

Computer Use 통합에서는 모델이 지원되는 동작을 반환하는지, 앱이 그 동작을 실행하고 완료를 제대로 판단하는지를 따로 확인해야 합니다. 이 글은 두 번째 문제부터 다룹니다. Python 컨트롤러와 오프라인 테스트 19개는 API 키, 브라우저 세션, 모델 비용 없이 실행할 수 있습니다.

컨트롤러 자료 받기. Python 3.9.6에서 통과했고 새로 압축을 푼 사본에서도 재실행했습니다. 포함된 run_live.py는 실행하거나 실제 공급자와 검증하지 않았습니다. 실제 API 화면, 사용량 측정, 엔드포인트 호환 결과는 없습니다.

먼저 테스트 실행하기

Python 3.9 이상과 표준 라이브러리면 됩니다. api-kit에서 실행하세요.

python3 -B -m unittest discover -s . -p 'test_*.py' -v

15개는 컨트롤러, 4개는 수신 기록 검사입니다. 모델 응답과 런타임을 모두 모의 구현으로 대체하며 네트워크나 브라우저를 사용하지 않습니다. 스크린샷 대신 쓰는 바이트는 유효한 이미지가 아니므로 실제 API에 전송할 수 없습니다.

파일역할
controller.py동작 검증, 관찰 반환, 완료 시 중단
test_controller.py합성 응답과 모의 런타임 테스트
test_receiver.py메모리의 수신 기록 변화 검사
run_live.py추후 Playwright·HTTPS Responses 연결용 미검증 어댑터
README.md실행 방법과 실제 연결 전제 조건

모델·실행·검증 분리하기

모델이 다음 동작을 고르고 런타임이 브라우저를 조작합니다. 별도의 검증기는 앱의 결과를 확인합니다. QA 실습 폼에서는 매번 다른 @example.test 주소를 사용합니다.

시작 전과 실행 중 /submissions를 비교합니다. 기존 기록이 순서대로 그대로 있고, 예상한 주소 하나만 새로 추가돼야 완료입니다. 과거 기록, 중복, 다른 주소, 성공 배너만으로는 통과하지 않습니다. 이는 실습 폼 전용 조건입니다. 실제 서비스는 저장된 초안 ID처럼 자체 작업에 맞는 결과를 검증해야 합니다.

하나의 도구 프로토콜 따르기

코드는 OpenAI Computer Use 가이드의 구조화된 동작 흐름을 참고합니다. 초기 스크린샷을 보내고 computer_call의 순서 있는 동작을 받아 지원되는 것을 실행합니다. 이어 일치하는 call_id를 넣어 computer_call_output으로 이미지를 반환하며, 다음 요청에는 previous_response_id를 전달합니다.

ID는 관찰과 해당 동작 요청을 연결합니다. 이미지만 보내고 ID를 틀리게 넣으면 올바른 도구 결과가 아닙니다. 공식 문서를 참고했다는 사실만으로, 실행하지 않은 어댑터가 특정 모델과 호환된다고 볼 수는 없습니다.

실제 연결 전 모델, 엔드포인트, 도구 스키마를 함께 확인하세요. 텍스트 요청 성공은 Computer Use 지원을 증명하지 않습니다. 기본 공급자나 모델을 정하지 않았으며 Ofox 경로 호환성도 주장하지 않습니다.

실행 전에 동작 검사하기

왼쪽 클릭, 최대 200자 입력, 지정된 단일 키, 제한된 스크롤, 스크린샷만 지원합니다. 좌표는 현재 이미지 크기 안에 있어야 합니다. 불리언, 유한하지 않은 수, 잘못된 구조는 거부합니다. 응답당 최대 12개 동작, 기본 최대 4회 모델 호출이며 모르는 동작은 중단합니다.

응답 하나에 computer call 하나만 받습니다. 중복 호출 ID, 완료되지 않은 응답, 남아 있는 안전 확인은 자동 승인하지 않고 멈춥니다. 모든 동작이나 일반적인 승인 시스템을 구현한 코드는 아닙니다.

각 동작 전후로 완료를 검사해 비동기 저장이 끝난 뒤 같은 배치에서 또 클릭하지 않게 합니다. 참조 어댑터도 클릭과 키 입력 후 수신 기록을 짧게 확인합니다. 로컬 논리 검증과 실제 브라우저 연동 성공은 별개입니다.

한 동작이 처리되는 과정 따라가기

컨트롤러는 모델 응답과 브라우저 실행기 사이의 애플리케이션 코드입니다. 지원하지 않는 동작을 거부하고 요청과 관찰을 연결하며, 애플리케이션 근거로 완료가 확인되면 멈춥니다. 이 경계를 만드는 개발자를 위한 예제이며 바로 운영할 완성형 에이전트는 아닙니다.

아래는 로컬 컨트롤러의 형식에 맞춘 합성 교육용 응답입니다. 좌표는 가상의 100×100 뷰포트 기준이며 QA 페이지 버튼 위치가 아닙니다.

{
  "id": "response_demo_1",
  "status": "completed",
  "output": [{
    "type": "computer_call",
    "call_id": "call_demo_1",
    "actions": [{"type": "click", "button": "left", "x": 10, "y": 20}]
  }]
}

바깥의 status는 응답 생성이 끝났다는 의미입니다. 클릭 실행이나 폼 저장 완료를 뜻하지 않습니다. 컨트롤러는 동작 묶음을 검사하고 허용된 동작을 순서대로 실행한 뒤 수신 결과를 확인합니다. 계속 진행할 때 스크린샷 결과의 call_id는 call_demo_1, previous_response_id는 response_demo_1을 가리킵니다. 서로 다른 식별자를 바꾸어 쓰면 요청과 결과의 연결이 깨집니다.

모델과 브라우저 없이 작은 예제 실행하기

다음 코드를 controller.py 옆에 walkthrough.py로 저장하고 python3 -B walkthrough.py를 실행합니다. 자료에 포함된 실제 컨트롤러와 단순한 모의 런타임을 사용합니다. 첫 동작 후 완료로 표시하여 두 번째 클릭이 건너뛰어지는 것을 볼 수 있습니다.

from controller import run

class DemoRuntime:
    width, height = 100, 100

    def __init__(self):
        self.actions = []
        self.done = False

    def screenshot(self):
        return b"offline-placeholder-not-a-real-png"

    def assert_allowed(self):
        pass  # Fake only: a real runtime must enforce its allowed surface.

    def complete(self):
        return self.done

    def perform(self, action):
        self.actions.append(action)
        self.done = True  # Simulated outcome, not receiver verification.

runtime = DemoRuntime()

def transport(payload):
    return {
        "id": "response_demo_1",
        "status": "completed",
        "output": [{
            "type": "computer_call",
            "call_id": "call_demo_1",
            "actions": [
                {"type": "click", "x": 10, "y": 20},
                {"type": "click", "x": 30, "y": 40}
            ]
        }]
    }

result = run(transport, runtime, "Synthetic controller walkthrough")
assert len(runtime.actions) == 1
print(result["status"], result["turns"], len(runtime.actions))

로컬에서 확인한 출력은 verified 1 1입니다. 성공 상태, 한 번의 합성 응답, 실행한 동작 하나를 뜻합니다. 그러나 verified는 일부러 단순하게 만든 DemoRuntime.complete()를 신뢰한 결과로, 폼이 실제로 저장됐다는 증거가 아닙니다. 실제 연결에서는 독립적인 결과 확인으로 대체해야 합니다. 이미지 자리표시자 바이트도 유효한 PNG가 아니므로 실제 API에 보내면 안 됩니다.

모의 완료 조건을 수신 기록으로 바꾸기

동봉된 브라우저 어댑터의 조건은 더 엄격합니다. 이전 기록이 그대로이고 이번 고유 주소에 해당하는 새 기록 하나만 추가되어야 합니다.

전후 변화판정이유
이전 기록+이번 주소 1개수락일치하는 추가 1개
변화 없음계속 확인하거나 미확정으로 종료저장 근거가 아직 없음
이전 기록+새 기록 두 사본거부중복 제출
이전 기록 변경+이번 주소거부기준 기록 변동
이전 기록+다른 주소거부입력 불일치

수신 측 네 테스트는 올바른 추가, 다른 주소, 초과 기록, 기존 기록 변경을 메모리 데이터로 검사합니다. 변화 없음은 어댑터의 계속 확인 규칙이며 다섯 번째 테스트가 아닙니다. 실제 시스템은 지연, 동시 작업, 읽기 실패도 처리해야 합니다. 격리된 연습 규칙을 동시 사용자가 있는 운영 시스템과 혼동하면 안 됩니다. QA 실습은 같은 전후 근거를 사람이 모으는 방법을 설명합니다.

19개 테스트가 확인하는 범위

잘못된 구조와 좌표, 미지원 입력, 호출·이미지 연결, 호출 횟수 제한, 중복 호출, 조기 중단, 정확한 기록 변화를 검사합니다. 완료 후 남은 동작을 멈추고 중복·다른 주소를 거부하는 회귀 테스트도 있습니다.

완료 상태이고 유효한 ID가 있는 응답은 동작 없는 최종 응답까지 사용량을 감사 기록에 남깁니다. 실행 실패 시 시도한 동작도 기록합니다. 합성 사용량은 실제 청구가 아니며 모든 시작 실패에 결과 파일을 보장하지도 않습니다. 모델 정확도, 시각 이해, 실제 작업 성공률은 알 수 없습니다.

처음 실패한 지점부터 중단 원인 찾기

메시지확인할 경계다음 단계
Coordinates outside current viewport좌표 검증현재 실제 이미지 크기와 비교
Unsupported action type지원 동작미구현 동작을 실행하지 말고 유형 확인
Missing or repeated call id호출 연결응답 ID, 호출 ID, 재시도 기록 확인
Safety check requires human review승인 대기중단. 예제에는 승인 UI가 없음
Model stopped before receiver verification완료 판단모델 설명 대신 수신 기록 확인
Turn limit reached반복 상한재시도 전에 이미 제출됐는지 확인

실행 전에 전체 묶음을 검사하므로 뒤에 미지원 동작이 있어도 첫 동작 이전에 멈춥니다. 다만 실행이 시작된 뒤 후속 동작에서 실패하면 앞 동작의 영향은 남을 수 있습니다. 감사 기록은 시도와 정상 반환을 구분할 뿐 이미 발생한 영향을 되돌리지 못합니다. 재시작 전에 수신 결과를 읽으세요.

연결 문제는 Computer Use 권한 점검을 참고하세요. 폼이 아닌 작업에는 다른 완료 기준이 필요합니다. 경쟁사 표 예제에서는 이메일 기록 대신 출처 URL을 보존한 파싱 가능한 근거 파일이 결과물입니다.

실제 실행의 전제 조건

오프라인 테스트는 다루고 있는 컨트롤러 로직만 확인합니다. 실제 실행기를 연결하기 전에 공급자의 도구 프로토콜과 독립적으로 확인할 수 있는 완료 조건을 정해야 합니다.

run_live.py는 새 Playwright Chromium 컨텍스트, 로컬 실습 페이지의 오리진, 명시적으로 설정한 HTTPS Responses 주소를 사용합니다. 개인 브라우저 프로필에는 연결하지 않습니다. 일반 페이지 요청의 대상은 실습 페이지의 오리진으로 제한합니다. 예상하지 않은 오리진이나 새 탭이 감지되면 중단하지만, 범용 보안 샌드박스는 아닙니다.

Playwright 설치 문서에 따라 독립 환경을 만들고 실제 패키지·브라우저 버전을 기록하세요. 이 어댑터의 실제 실행 의존성은 검증된 버전으로 고정하지 않았습니다. COMPUTER_RESPONSES_URL, COMPUTER_MODEL, COMPUTER_API_KEY는 환경 변수로 전달하고 키를 파일에 넣지 않습니다.

브라우저와 비용 사용 허가가 필요하며 기존 접근 거부를 우회해서는 안 됩니다. 매번 새 가상 주소와 출력 폴더를 사용합니다. 4회 호출과 출력 토큰 제한은 금액 예산이 아닙니다. 공급자 요금과 계정의 지출 한도를 별도로 확인하세요. 실패한 모델 요청은 자동으로 재시도하지 않습니다. 시간 초과에도 과금될 수 있으므로 재시도 전 사용량과 수신 기록을 살펴봅니다.

실제 연동 검증에 필요한 기록

실제 연동을 검증하려면 모델 ID, 호스트, 버전, 작업, 민감 정보를 제거한 응답과 사용량 기록, 호출 ID, 화면, 수신 결과를 남깁니다. 로그와 화면을 공유하기 전에는 민감 정보가 포함됐는지 검토하세요. 깨끗한 환경에서 새 주소로 한 번 더 실행하고 두 결과와 실제 사용량을 따로 보고하세요. 실패한 도구를 텍스트 출력으로 바꾼 뒤 성공이라고 부를 수 없습니다. 현재 확인된 결과는 오프라인 테스트 19개입니다.

자주 묻는 질문

검증된 실제 API 연동 예제로 봐도 되나요?
아닙니다. 컨트롤러와 수신 기록의 오프라인 테스트 19개는 통과했지만 어댑터는 실행하지 않았습니다. 공급자 호환성, 실제 브라우저, 비용은 미검증입니다.
API 키 없이 테스트할 수 있나요?
가능합니다. 표준 라이브러리 테스트는 합성 응답과 모의 런타임을 사용하며 공급업체나 브라우저에 연결하지 않습니다.
verified 상태는 무엇을 뜻하나요?
전달된 런타임이 완료를 보고했다는 의미입니다. 본문 예제에서는 모의 결과이며 실제 연결에서는 독립적인 애플리케이션 근거가 필요합니다.
반복 횟수를 제한하면 비용도 보장되나요?
아닙니다. 반복 횟수와 금액은 다릅니다. 실제 요율, 사용량 기록, 계정 측 지출 제한을 따로 확인해야 합니다.