Qwen 3.7 Plus는 스크린샷을 보고 클릭할 픽셀 좌표를 반환하는 ScreenSpot Pro 벤치마크에서 79.0점을 기록했습니다. 이 기능을 이용하면 채팅 모델을 “화면을 보고 다음 행동을 결정한 뒤 실행하는” 컴퓨터 사용 에이전트로 만들 수 있습니다. 이 글에서는 Python, Qwen 3.7 Plus, Playwright로 브라우저 에이전트를 구현하는 전체 흐름을 다룹니다.
구현 범위는 네 가지입니다. 에이전트 루프 설계, 안정적인 JSON 작업을 반환하도록 만드는 프롬프트, Playwright 실행 코드, 그리고 실제 적용 전 확인해야 할 비용 및 안전 장치입니다. 모델 배경이 필요하다면 Qwen 3.7 Plus 개요를 먼저 확인하세요. 멀티모달 요청 형식은 Qwen 3.7 Plus API 가이드에서 다룹니다. 구현 중에는 Apidog로 모델 호출을 테스트합니다.
요약
컴퓨터 사용 에이전트는 다음 루프를 반복합니다.
- 현재 화면을 스크린샷으로 캡처합니다.
- 목표와 스크린샷을 Qwen 3.7 Plus에 보냅니다.
- 모델에서
click,type,scroll,done같은 구조화된 작업을 받습니다. - Playwright 같은 자동화 드라이버로 작업을 실행합니다.
- 다시 스크린샷을 찍고 목표 완료 여부를 확인합니다.
Qwen 3.7 Plus는 GUI 기반 좌표 반환과 저렴한 멀티모달 비용 덕분에 이 패턴에 적합합니다. 실제 구현에서 중요한 부분은 모델 선택보다 루프 제한, 좌표 스케일링, 토큰 비용 제어, 샌드박스 실행입니다.
컴퓨터 사용 에이전트가 하는 일
구현 관점에서 에이전트는 네 단계 파이프라인입니다.
| 단계 | 역할 | 구현 예시 |
|---|---|---|
| 인식 | 현재 화면 캡처 | page.screenshot() |
| 결정 | 다음 작업 생성 | Qwen 3.7 Plus 호출 |
| 실행 | 클릭, 입력, 스크롤 수행 | Playwright mouse/keyboard API |
| 확인 | 상태 변화 검증 | 새 스크린샷으로 다음 루프 실행 |
모델은 “결정”만 담당합니다. 화면 캡처, 실행, 검증, 중단 조건은 모두 애플리케이션 코드에서 제어해야 합니다.
<video src="https://assets.apidog.com/blog-next/2026/06/V1tXD8Bnm5DAtobB.mp4" poster="https://img.spacergif.org/v1/1920x1080/0a/spacer.png" width="1920" height="1080" loop="" autoplay="" muted="" playsinline="" preload="metadata"></video>
<svg xmlns="http://www.w3.org/2000/svg">
<path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
</svg>
<svg xmlns="http://www.w3.org/2000/svg">
<path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
</svg>
<svg xmlns="http://www.w3.org/2000/svg">
<rect width="7" height="22" rx="1.5" ry="1.5"></rect>
<rect width="7" height="22" rx="1.5" ry="1.5"></rect>
</svg>
<span>0:00</span>
/<span>1:26</span>
1×
<svg xmlns="http://www.w3.org/2000/svg">
<path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
</svg>
<svg xmlns="http://www.w3.org/2000/svg">
<path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
</svg>
Qwen 3.7 Plus가 적합한 이유
Qwen 3.7 Plus를 컴퓨터 사용 에이전트에 적용하기 좋은 이유는 세 가지입니다.
- GUI 좌표 반환: 화면 요소를 해석하고 실행 가능한 좌표를 반환할 수 있습니다.
- GUI 및 CLI 워크플로 처리: 버튼 클릭과 셸 명령 실행을 함께 다루는 하이브리드 에이전트에 적용할 수 있습니다.
- 멀티모달 비용: 백만 입력 토큰당 0.40달러로, 반복적인 스크린샷 호출을 포함하는 루프를 실험하기에 상대적으로 저렴합니다.
텍스트 전용 플래그십 모델과의 차이는 Qwen 3.7 Plus vs Max 비교에서 확인할 수 있습니다.
결정 단계 구현: JSON 작업만 받기
가장 먼저 해야 할 일은 모델 출력을 실행 가능한 형태로 제한하는 것입니다. 자연어 설명은 자동 실행하기 어렵습니다. 대신 작은 작업 어휘와 JSON 스키마를 사용합니다.
지원할 작업은 다음 정도로 시작하면 충분합니다.
{"action": "click", "x": 100, "y": 200}
{"action": "type", "text": "hello"}
{"action": "scroll", "dy": 500}
{"action": "done", "reason": "goal completed"}
Python 예시는 다음과 같습니다.
import os
import json
import base64
from openai import OpenAI
client = OpenAI(
api_key=os.environ["DASHSCOPE_API_KEY"],
base_url="https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
)
SYSTEM = """당신은 GUI 에이전트입니다. 스크린샷과 목표를 보게 됩니다.
단 하나의 JSON 작업으로만 응답하세요:
{"action": "click", "x": <정수>, "y": <정수>}
{"action": "type", "text": "<문자열>"}
{"action": "scroll", "dy": <정수>}
{"action": "done", "reason": "<문자열>"}
좌표는 주어진 스크린샷의 픽셀 단위입니다."""
def next_action(goal, png_bytes):
b64 = base64.b64encode(png_bytes).decode()
resp = client.chat.completions.create(
model="qwen3.7-plus",
messages=[
{"role": "system", "content": SYSTEM},
{
"role": "user",
"content": [
{"type": "text", "text": f"Goal: {goal}"},
{
"type": "image_url",
"image_url": {
"url": f"data:image/png;base64,{b64}"
},
},
],
},
],
)
return json.loads(resp.choices[0].message.content)
모델 식별자는 변경될 수 있으므로 배포 전 Model Studio 문서에서 정확한 모델 ID를 확인하세요.
Playwright로 전체 루프 만들기
브라우저 자동화에는 Playwright를 사용할 수 있습니다. 핵심은 스크린샷 해상도와 브라우저 뷰포트 크기를 일치시키는 것입니다. 그래야 모델이 반환한 좌표를 별도 스케일링 없이 그대로 클릭할 수 있습니다.
from playwright.sync_api import sync_playwright
MAX_STEPS = 15
VIEWPORT = {"width": 1280, "height": 800}
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page(viewport=VIEWPORT)
page.goto("https://example.com")
goal = "Open the pricing page and find the cheapest plan"
for step in range(MAX_STEPS):
# 1. 현재 화면 캡처
shot = page.screenshot()
# 2. 모델에 다음 작업 요청
action = next_action(goal, shot)
print(step, action)
# 3. 완료 여부 확인
if action["action"] == "done":
break
# 4. 작업 실행
if action["action"] == "click":
page.mouse.click(action["x"], action["y"])
elif action["action"] == "type":
page.keyboard.type(action["text"])
elif action["action"] == "scroll":
page.mouse.wheel(0, action["dy"])
# 5. UI 안정화 대기
page.wait_for_timeout(800)
browser.close()
이 구조가 컴퓨터 사용 에이전트의 최소 구현입니다. 에이전트는 한 번에 하나의 기본 작업만 수행하고, 각 작업 후 새 화면을 기준으로 다시 판단합니다.
데스크톱 앱에도 같은 패턴을 적용할 수 있습니다. Playwright 대신 데스크톱 자동화 라이브러리를 사용하고, OS 창 스크린샷을 모델에 전달하면 됩니다.
JSON 파싱 실패에 대비하기
운영 코드에서는 모델이 항상 완벽한 JSON을 반환한다고 가정하면 안 됩니다. 최소한 한 번의 복구 재시도를 넣는 것이 좋습니다.
def safe_next_action(goal, png_bytes):
try:
return next_action(goal, png_bytes)
except json.JSONDecodeError:
# 실제 구현에서는 같은 스크린샷으로
# "JSON으로만 응답하세요" 프롬프트를 붙여 한 번 재시도합니다.
raise RuntimeError("모델이 유효한 JSON 작업을 반환하지 않았습니다.")
더 안정적으로 만들려면 다음 검증도 추가하세요.
ALLOWED_ACTIONS = {"click", "type", "scroll", "done"}
def validate_action(action):
if action.get("action") not in ALLOWED_ACTIONS:
raise ValueError(f"지원하지 않는 작업: {action}")
if action["action"] == "click":
if not isinstance(action.get("x"), int) or not isinstance(action.get("y"), int):
raise ValueError(f"잘못된 click 좌표: {action}")
if action["action"] == "type":
if not isinstance(action.get("text"), str):
raise ValueError(f"잘못된 type 작업: {action}")
if action["action"] == "scroll":
if not isinstance(action.get("dy"), int):
raise ValueError(f"잘못된 scroll 작업: {action}")
return action
루프에서는 다음처럼 사용합니다.
action = validate_action(next_action(goal, shot))
비용 및 신뢰성 관리
비용의 대부분은 스크린샷에서 발생합니다. 각 이미지가 토큰으로 변환되며, 1280px 너비의 화면은 수천 개의 입력 토큰이 될 수 있습니다. 15단계 루프라면 한 번의 작업에도 여러 번의 멀티모달 호출이 발생합니다.
비용을 줄이려면 다음을 적용하세요.
- 이미지 축소: 모델이 읽을 수 있는 최소 해상도로 전송합니다.
- 영역 자르기: 전체 화면 대신 관련 패널이나 브라우저 영역만 보냅니다.
-
단계 제한:
MAX_STEPS를 반드시 둡니다. - 실행 후 검증: 클릭이 성공했다고 가정하지 말고 다음 스크린샷에서 상태 변화를 확인합니다.
- 불필요한 반복 방지: 같은 작업이 반복되면 중단하고 사람에게 넘깁니다.
관련 내용은 에이전트 토큰 비용 절감 가이드와 에이전트 워크플로 연결 노트에서 더 자세히 다룹니다.
에이전트가 멈췄을 때의 처리
자주 발생하는 실패와 대응 방법은 다음과 같습니다.
1. 모델이 JSON 대신 설명문을 반환함
대응:
- 시스템 프롬프트에 “JSON으로만 응답”을 명확히 넣습니다.
- 파싱 실패 시 같은 입력으로 한 번만 재시도합니다.
- 두 번째 실패 시 루프를 중단합니다.
2. 클릭 좌표가 빗나감
대응:
- 같은 좌표를 반복 클릭하지 않습니다.
- 다음 스크린샷에서 화면 변화가 없으면 새 판단을 요청합니다.
- 뷰포트와 스크린샷 크기가 같은지 확인합니다.
3. 루프가 같은 행동을 반복함
대응:
- 최근 작업 N개를 저장합니다.
- 동일한 패턴이 반복되면 중단합니다.
- 마지막 스크린샷과 작업 로그를 사람에게 보여줍니다.
예시:
recent_actions = []
def is_repeating(action):
recent_actions.append(action)
if len(recent_actions) > 4:
recent_actions.pop(0)
return len(recent_actions) == 4 and all(a == recent_actions[0] for a in recent_actions)
안전 장치
컴퓨터 사용 에이전트는 실제 UI를 클릭합니다. 따라서 다음 규칙을 기본값으로 두세요.
- 샌드박스 또는 일회용 브라우저 프로필에서 실행합니다.
- 로그인된 프로덕션 세션에서는 실행하지 않습니다.
- 삭제, 전송, 결제 같은 파괴적 작업은 사람의 확인을 요구합니다.
- 모든 작업을 스크린샷과 함께 기록합니다.
- 에이전트가 접근 가능한 도메인과 기능을 제한합니다.
최소 로그 구조는 다음과 같이 둘 수 있습니다.
import time
def log_step(step, goal, action, screenshot_path):
record = {
"time": time.time(),
"step": step,
"goal": goal,
"action": action,
"screenshot": screenshot_path,
}
print(json.dumps(record, ensure_ascii=False))
Apidog로 에이전트 호출 테스트하기
Playwright를 연결하기 전에 먼저 확인할 것은 하나입니다.
모델이 매번 유효한 작업 JSON을 반환하는가?
Apidog에서 Qwen 3.7 Plus 요청을 구성하고 샘플 스크린샷을 보내세요. 그런 다음 반환된 원시 JSON을 확인하면서 시스템 프롬프트를 조정합니다.
테스트 순서는 다음과 같습니다.
- Model Studio API 엔드포인트를 Apidog에 등록합니다.
- 환경 변수로 API 키를 저장합니다.
- 샘플 스크린샷을 base64 이미지 URL로 전달합니다.
- 응답이 정해진 JSON 스키마를 따르는지 확인합니다.
- 실패 케이스를 저장하고 프롬프트를 개선합니다.
- 실제 루프 구현 전 mock 응답으로 Playwright 코드를 테스트합니다.
전체 에이전트 루프가 여러 호출을 연결할 때는 Apidog의 AI 에이전트 디버거를 사용해 어느 단계에서 문제가 발생했는지 추적할 수 있습니다.
디자인에서 UI 코드를 생성하는 방법은 Qwen 3.7 Plus를 사용한 스크린샷-투-코드 가이드를 참고하세요.
에이전트 뒤의 모델 호출을 테스트하고 디버그하려면 Apidog를 다운로드하세요.
자주 묻는 질문
컴퓨터 사용 에이전트란 무엇인가요?
스크린샷으로 화면을 인식하고, 모델로 다음 작업을 결정한 뒤, 자동화 드라이버로 실행하는 소프트웨어입니다. 목표가 완료될 때까지 이 과정을 반복합니다.
Qwen 3.7 Plus가 제 데스크톱을 직접 제어하나요?
아니요. 모델은 작업을 반환할 뿐입니다. 실제 클릭, 입력, 스크롤은 Playwright 또는 데스크톱 자동화 라이브러리가 실행합니다.
각 단계의 비용은 얼마인가요?
주요 비용은 스크린샷 입력에서 발생합니다. 단일 화면 이미지는 수천 개의 입력 토큰이 될 수 있으며, 백만 입력 토큰당 0.40달러 기준으로 계산됩니다. 축소, 자르기, 루프 제한이 핵심 절감 수단입니다.
운영 환경에서 사용할 만큼 신뢰할 수 있나요?
제한적이고 잘 정의된 작업이며 각 단계 후 검증이 있다면 사용할 수 있습니다. 중요한 시스템을 개방형으로 제어하는 용도라면 사람의 확인과 샌드박스가 필요합니다.
좌표를 스케일링해야 하나요?
스크린샷 해상도와 뷰포트가 같다면 필요 없습니다. 다르다면 반환 좌표를 실제 실행 화면 비율에 맞게 변환해야 합니다.
결론
Qwen 3.7 Plus 기반 컴퓨터 사용 에이전트는 복잡한 구조가 아닙니다. 스크린샷을 찍고, 모델에서 JSON 작업을 받고, Playwright로 실행하고, 다시 확인하는 짧은 루프입니다.
실제 구현에서는 다음을 우선 적용하세요.
- 작업 스키마를 작게 유지합니다.
- JSON 출력만 허용합니다.
- 단계 수를 제한합니다.
- 클릭 후 반드시 새 화면으로 검증합니다.
- 샌드박스에서 실행합니다.
- 모델 호출은 Apidog에서 먼저 테스트합니다.
에이전트가 클릭을 시작하기 전에 “결정 단계”가 안정적인지 확인하는 것이 가장 중요합니다.


Top comments (0)