명령
명령은 기기의 에이전트에게 도구 하나를 실행시키는 일이에요. actual·virtual 기기 모두 같아요. 도구 이름과 입력은 그 에이전트의 카탈로그(GET /devices/{id}/tools)가 정해요.
curl -s -X POST $OS/api/v1/devices/$DEV/commands \ -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \ -d '{"command":"list_dir","input":{"path":"."},"request_id":"job-42"}'POST /devices/{id}/commands 는 옛 경로 POST /resources/{id}/commands 와 같아요.
| 필드 | 뜻 |
|---|---|
command |
도구 이름 ^[a-z_]{1,64}$ |
input |
도구 입력. 에이전트가 자기 스키마로 검증해요 |
wait_ms |
이 시간 안에 끝나면 201, 아니면 202. 0~25000, 기본 25000 |
timeout_ms |
에이전트가 실행할 예산 (1000~120000) |
request_id |
멱등 키. 끝난 뒤 24시간 안에 같은 키·같은 입력이면 같은 명령을 돌려줘요. 다른 입력이면 409 REQUEST_ID_CONFLICT |
queue_ttl_ms |
오프라인이어도 줄에 넣고 기다릴 시간 (최대 1시간). 기본 0 — 오프라인이면 409 RESOURCE_OFFLINE |
store_image |
출력의 이미지를 Station 저장 객체로 옮겨요 |
201 이냐 202 냐
섹션 제목: “201 이냐 202 냐”| 상황 | 응답 |
|---|---|
wait_ms 안에 끝남 |
201 + CommandResult (출력 포함) |
| 아직 안 끝남 | 202 + Command + Location: /api/v1/commands/{id} + Retry-After: 5 |
wait_ms 안에 결과를 알 수 없게 됨 (unknown) |
504 COMMAND_OUTCOME_UNKNOWN — 같은 request_id 로 다시 보내요 |
| 줄이 꽉 참 (에이전트당 100건) | 429 RESOURCE_BUSY |
| 계정 잔액이 0 이하 | 402 INSUFFICIENT_CREDITS |
202 를 받았다면 셋 중 하나로 끝을 알아요:
- 롱폴 —
GET /commands/{id}?wait_ms=25000이 끝나거나 상태가 바뀔 때까지 기다려요. - 이벤트 —
command.completed를 SSE·WebSocket 으로 (이벤트와 웹훅). - 웹훅 — 같은 이벤트를 서명된 POST 로.
끝난 뒤 출력은 GET /commands/{id}/output 으로 24시간 받아요. 아직이면 409 COMMAND_IN_PROGRESS, 지났으면 410 OUTPUT_EXPIRED. 큰 바이트(예: 256 KiB 넘는 스크린샷)는 {이름}_blob 참조로 오고 GET /commands/{id}/blobs/{name} 으로 받아요.
호출자가 끊겨도 기기 작업은 계속돼요. 진행 중인 명령은 플랫폼 배포·재시작을 넘어 남고, 에이전트가 같은 프로세스로 다시 붙으면 결과까지 이어져요.
크레딧
섹션 제목: “크레딧”명령은 끝난 1건마다 Station 주인의 계정 크레딧을 단가표의 command 만큼 써요. 보내기 전에 잔액을 확인해서, 0 이하면 402 INSUFFICIENT_CREDITS 로 막아요 (details.balance). 충전은 크레딧.
queued → dispatched → running → succeeded · failed · timed_out · cancelled, 그 밖에 cancelling · expired(줄에서 기한이 지나 실행되지 않음) · unknown(실행됐는지 모름). 10종이에요.
ok는 도구가 처리됐다는 뜻이지 작업 목표를 이뤘다는 뜻이 아니에요. 출력을 보세요.unknown뒤에 늦게 온 답은late_status·late_at에 남고command.late_result이벤트가 나가요.
POST /commands/{id}/cancel — 줄에 있으면 바로 cancelled, 보낸 뒤면 cancelling → 에이전트의 답을 따라요. 취소는 되돌리기가 아니에요 — 이미 일어난 효과는 남아요.
GET /devices/{id}/commands,GET /stations/{id}/commands— 최신순,status필터. 기록의resource_id는 기기의device_id와 같은 값이에요.- 입력 원문은 남지 않아요 (지문만). 출력은 보관 대상일 때만 24시간.
- 화면·설치된 앱 목록처럼 플랫폼이 스스로 부르는 호출은 기록에 남지 않아요.