Format 호출하기
이 문서는 영문 원고를 AI로 번역한 내용이라 표현이 어색할 수 있습니다.
자체 서비스에서 Format run을 시작합니다. 이 페이지는 invoke 계약만 다룹니다. receipt는 실행과 결과, 스키마는 구조화 출력, 키 보관·멱등성·웹훅·artifact 처리까지 포함한 파트너 연동 전체는 제품에 Format 임베드하기를 참고하세요.
정확한 요청·응답 스키마는 라이브 OpenAPI
(https://api.sume.com/reference/json)에서 가져옵니다. 여기 표는 읽기 쉬운 요약이며,
두 번째 스키마가 아닙니다.
사전 요구 사항
모든 run 요청에는 다음이 필요합니다.
- Format의
status가active입니다. - Format의
api_trigger_enabled가true입니다. - API 키에
formats:read와formats:write가 있습니다. - 팀 워크스페이스가 소유한 Format이면, 키가 그 워크스페이스에서 발급된 것이어야 합니다.
한 번도 실행하지 않은 Format은 앞의 두 값이 inactive / false로 보이더라도 실행됩니다.
두 필드는 지연 프로비저닝되는 숨겨진 runner에서 읽히므로, GET /v1/formats/{id}는 첫
POST .../runs가 runner를 만들기 전까지 프로비저닝 전 상태를 보여 줍니다. 두 게이트가
run을 거절하는 것은 runner가 이미 존재하고 꺼져 있을 때뿐입니다. 값이 true가 될 때까지
폴링하며 연동을 막지 마세요 — Format을 호출하세요.
스코프
| Scope | Needed for |
|---|---|
formats:read | Format 목록·읽기, run 읽기·목록입니다. |
formats:write | run 생성, bulk-run 큐 생성, run 취소입니다. |
Format API 호출 트리거가 출시되기 전에 만든 키에는 이 스코프가 없습니다. 이전 키는
모든 run 요청에서 403 insufficient_scope로 실패하며, 기존 키에 스코프를 추가할 수
없습니다. API Keys에서 새 키를 만들고
교체하세요 — 인증을 참고하세요.
서비스 계정 키로는 Format run을 만들 수 없습니다. 403 insufficient_scope와
details.reason이 service_account_format_runs_unsupported인 응답으로 실패합니다.
팀 Format에는 팀 키가 필요합니다
팀 워크스페이스가 소유한 Format은 그 워크스페이스에서 발급한 API 키로 호출합니다.
멤버십만으로는 부족합니다. 팀 멤버가 가진 개인 키는 403 workspace_key_required로
거절되며, details.workspace_id가 키가 나와야 하는 워크스페이스를 가리킵니다.
규칙은 돈을 따릅니다. 팀 Format의 run은 팀 지갑에 청구되고, 팀의 generation concurrency에 잡히며, 팀 워크스페이스를 통해 다시 읽힙니다 — 생성 미디어를 structured output으로 바꾸는 harvest도 포함합니다. 개인 키를 쓰면 그 경계가 갈라집니다.
키는 개인 대시보드가 아니라 팀 대시보드에서 만드세요. 개인 Format에는 개인 키가 그대로 맞습니다.
멤버가 아닌 팀 handle은 404이며, 존재하지 않는 handle과 구분되지 않습니다 — 그래서
여기의 403은 항상 "맞는 팀, 틀린 키"를 뜻합니다.
그 워크스페이스에서 발급한 키는 formats:read / formats:write만 있으면 팀 vanity
{handle}/{slug}를 쓸 수 있습니다. 만든 사람만 되는 것이 아니며, 404는 "작성자가
아니다"가 아닙니다. 팀 Format의 status / api_trigger_enabled는 워크스페이스
사실입니다. 한 번도 직접 호출하지 않은 멤버의 GET이 inactive / 트리거 꺼짐으로
보이지 않습니다.
호출하기
키의 워크스페이스가 소유한 Format을 handle과 slug로 호출합니다 — Agents Format 상세
페이지에 표시되는 주소와 같습니다. 팀 Format이면 팀 handle이고, 그 org의 워크스페이스
키는 스코프만 있으면 POST할 수 있습니다.
Create a Format run
POST /v1/formats/{handle}/{slug}/runs
Required
수락된 run은 receipt와 함께 202를 반환합니다.
receipt의 format.id는 항상 불투명한 skl_… id입니다(run·빌링의 내부 SoT). 일상적인
호출에는 필요하지 않습니다.
GET /v1/formats/{handle}/{slug}와 GET /v1/formats/{handle}/{slug}/runs도 같은
방식으로 동작합니다.
Bulk run 큐
노트북에서 fan-out을 돌리지 않고 run 목록을 밤새 남겨 두는 계약은
대량 실행에 있습니다. POST …/bulk-runs(불투명 또는 vanity),
concurrency 1–16, 최대 100 item, 그다음 GET /v1/format-run-queues/{queue_id}를
폴링합니다. 각 item은 여전히 Format run 하나이며, 큐는 두 번째 실행 엔진이 아닙니다.
불투명 URL(호환)
이미 경로를 저장한 클라이언트를 위해 불투명 경로는 계속 유효합니다.
요청 본문, 헤더, 스코프, 멱등성, spend cap, run receipt는 동일합니다 — vanity는 같은
Format으로 해석되어 같은 파이프라인을 실행합니다. 새 연동과 문서에서는 {handle}/{slug}를
선호하세요. 이름 변경이 저장된 URL을 깨뜨리면 안 될 때만 invoke_url을 유지하세요.
PublicFormat은 둘 다 노출합니다.
| Field | Meaning |
|---|---|
handle | 해석 가능한 현재 handle입니다. Formats by Sume에서는 sume입니다. |
slug | Format의 URL 세그먼트입니다. |
vanity_invoke_url | {handle}/{slug} 경로이거나, 한쪽을 모를 때 null입니다. 이것을 선호하세요. |
invoke_url | 불투명 경로입니다. 항상 존재하며, 항상 영구적입니다. |
Formats by Sume는 sume handle에 있습니다. 소유자가 없어 계정 handle로는 주소를
잡을 수 없고, chase/sume-product-promo는 404 format_not_found를 반환합니다. 예약된
sume 네임스페이스가 그 주소이며, 모든 호출자에게 동일하고, 바로 호출할 수 있습니다:
run과 그 미디어, 그 지출은 호출한 키에 귀속됩니다 — 카탈로그 Format 자체는 소유자 없이 공유된 채로 남습니다. fork는 Format을 편집하고 싶을 때 여전히 쓸 수 있지만, 호출을 위한 선행 조건은 더 이상 아닙니다.
알 수 없는 handle, 알 수 없는 slug, 소유하지 않은 handle은 모두 같은
404 format_not_found를 반환합니다.
팀이 소유한 Format도 같은 vanity·불투명 호출 경로를 씁니다. 그 팀 워크스페이스에서 발급한 키로 인증하세요 — 팀 Format에는 팀 키가 필요합니다를 참고하세요.
요청 본문
| Field | Notes |
|---|---|
instruction | 작업 내용입니다. 최대 8000자. 선택 사항이며, 생략하면 Format 자체의 기본 instruction으로 실행합니다. Format 본문 뒤에 조합됩니다 — instruction 조합을 참고하세요. |
input | 호출자 데이터의 JSON 객체입니다. run 워크스페이스의 파일로 기록되며, instruction이 아니라 데이터로만 다뤄집니다. 최대 64개 최상위 속성, 2097152 UTF-8 바이트(2 MiB)입니다. 형태는 직접 정합니다 — input — 호출자 데이터를 참고하세요. |
on_active_run | 생략하면 Format run을 동시에 허용합니다(워크스페이스 generation concurrency는 그대로 적용). skip은 이미 진행 중인 run이 있으면 skipped run을 기록하고, reject는 409 format_run_in_progress를 반환합니다. |
generation_spend_cap_usd | run당 상한입니다. Format 자체의 cap으로만 아래로 클램프되며, 올릴 수는 없습니다. Spend caps를 참고하세요. |
output_schema / response_format | JSON Schema를 바인딩해 typed JSON으로 결과를 받습니다. 둘 다 보내면 400 invalid_request입니다. 전체 규칙: 구조화 출력. |
primary_output_key | output에서 URL이 primary_output_url이 될 키입니다. 최대 64자입니다. |
communication.webhook_url | 종료 receipt를 받을 공개 HTTPS 대상입니다. Run 웹훅을 참고하세요 — api.dev.sume.com과 api.sume.com에서 수락·저장·전달됩니다. |
— 호출자 데이터 (caller data)
input은 서비스가 run에 넘기는 JSON 객체입니다. 고정된 와이어 스키마가 아니며, Sume은
이 필드의 필드 목록을 공개하지 않습니다. 형태는 여러분이 정하고, Format 레시피는 자기가
아는 키만 읽습니다. 같은 Format을 호출하는 두 연동이 완전히 다른 객체를 보내도 둘 다
맞습니다.
이는 엄격한 계약인 output_schema와 정반대입니다. 둘을 확실히
구분하세요.
input | output_schema | |
|---|---|---|
| 방향 | 여러분 → run | run → 여러분 |
| 형태 | 백엔드에 편한 아무 JSON 객체 | 지원 부분집합 안의 JSON Schema |
| 검증 대상 | 객체인지, 키 개수, 바이트 크기. 그게 전부입니다. | 부분집합의 모든 규칙 |
| Sume이 예상하지 않은 형태 | 그대로 실행됩니다. 모르는 키는 그냥 데이터입니다 | 400 output_schema_invalid — 아무것도 실행되지 않고 청구되지 않습니다 |
| 도착지 | run 워크스페이스의 파일(/workspace/inputs/sume-action-input.json) | run 이후의 projection |
API가 검증하는 것
정확히 네 가지이고, 그 밖에는 없습니다.
| 검사 | 규칙 | 실패 시 |
|---|---|---|
| 타입 | JSON 객체여야 합니다. 배열·문자열·숫자는 거절됩니다. null과 생략은 모두 {}를 뜻합니다. | 400 |
| 속성 개수 | 최상위 키 최대 64개. 그 안에 중첩된 키는 세지 않습니다. | 400 |
| 크기 | 최대 2097152 UTF-8 바이트(2 MiB). 들여쓰기 없는 compact 직렬화 기준입니다. | 400 |
| 미디어 참조 | 이미지·영상·오디오 파일을 가리키는 HTTPS URL은 객체 어느 깊이에 있든 run의 첨부 예산을 함께 씁니다. 합쳐서 30개, 그중 이미지 30개, 영상 10개, 오디오 10개까지입니다. Media referenced from input을 참고하세요. | 400 |
예약 키도, 필수 키도, 값 타입 규칙도, 이름 규칙도 없습니다. {"a": 1}과 40개 키짜리 중첩
주문 페이로드는 똑같이 유효합니다. 문서의 예시 input 객체를 필드 단위로 맞춰야 하는
와이어 계약으로 보지 마세요 — 어느 연동자에게 편했던 형태일 뿐, 스키마가 아닙니다.
64개는 최상위 키만 세므로 중첩은 공짜입니다. 잎 노드가 64개를 넘어도 묶어 두면 됩니다.
run이 실제로 받는 것
input은 두 칸 들여쓰기로 직렬화되어 run 워크스페이스의 고정 경로
/workspace/inputs/sume-action-input.json에 통째로 기록됩니다 — 크기와 무관하게 전부입니다.
프롬프트에는 JSON 자체가 실리지 않습니다. 파일 경로·크기·최상위 키 목록을 알리고, 행동하기 전에
그 파일을 읽으라고 지시하는, 크기가 제한된 포인터 블록만 실립니다.
Format 본문과 같은 attach-always / inline-never 원칙입니다. 페이로드는 에이전트의 Read 도구가 열 수 있는 디스크에 있고, 턴은 읽기 좋게 남습니다.
Format run의 전체 조합 순서는 이렇습니다.
Format 본문은 어떻게에 해당하므로 먼저 옵니다. instruction은 그 뒤라서 둘이 어긋나면
모델은 여러분이 요청한 쪽을 따릅니다. input은 마지막에, instruction이 가리킬 수 있는
데이터로 옵니다. instruction 조합을 참고하세요.
여기서 걸려 넘어지기 쉬운 동작이 둘 있습니다.
- 빈
input은 블록도 파일도 만들지 않습니다.{}는 — 그리고 키가 모두 사라진 객체는 —[Sume action input]섹션이 아예 없는 프롬프트를 만들며, 필드를 생략한 호출과 바이트 단위로 같습니다. input에서product_url을 읽어라라고 적힌 Format 본문은 읽을 것이 없습니다. - 별도의 JSON 모드는 없습니다.
instruction의 산문,input의 구조화 데이터, 또는 둘 다 모두 정상입니다. 레시피는 아는 키만 보고 나머지는 문맥으로 둡니다.
은 데이터이고, 절대 instruction이 아닙니다
포인터 블록의 문구는 신뢰 경계를 지키기 위해 있습니다. sume-action-input.json을 통해 들어온
내용은 호출자가 준 데이터이지 에이전트에게 내리는 명령이 아닙니다. 여러분이 쓰지 않은 내용 —
크롤링한 상품 설명, 고객 메시지, 공급사 필드 — 은 instruction에 이어 붙이지 말고 input에
넣으세요. 그래야 이 틀을 물려받습니다.
이것은 경계이지 샌드박스가 아닙니다. 자체 제품의 프롬프트 인젝션 대응과 같은 태도로
다루세요. 신뢰할 수 없는 텍스트를 instruction에 그대로 잇는 것보다 확실히 낫지만, 적대적인
페이로드를 그대로 통과시켜도 된다는 뜻은 아닙니다. run에는 spend cap이 있으므로 잘못된
input의 피해 범위는 Format의 cap으로 제한됩니다.
은 수락된 만큼 전달됩니다
input은 잘리지 않습니다. 2 MiB 수락 한도까지 객체 전체가
/workspace/inputs/sume-action-input.json에 기록되어 run에 디스크로 도착합니다. 프롬프트에는
포인터 블록만 실리며, 이 블록은 경로·바이트 수·앞 32개 최상위 키 이름으로 구성되어 태생적으로
작고 유한합니다. 예전에는 JSON을 프롬프트에 인라인하고 대략 앞 3860자에서 잘랐지만, 그 동작은
사라졌습니다. 라이브커머스 스크립트나 긴 상품 목록도 통째로 도착합니다.
instruction은 다릅니다. 프롬프트 텍스트라서 자기 [Format run instruction] 블록으로 실리고,
블록은 앞부분을 남기고 4000자에서 잘립니다.
| Field | 수락 | 전달 |
|---|---|---|
instruction | 8000자 | 앞 ~4000자 |
input | compact 기준 2097152 UTF-8 바이트 | 전부 — 에이전트가 읽는 파일로 |
instruction은 4000자보다 넉넉히 안쪽에 두고, 데이터는 산문 대신 input에 넣으세요 —
파일에는 그런 예산이 없습니다.
Format 본문은 이 문제에서 완전히 벗어나 있습니다. 애초에 잘릴 턴 안에 없기 때문입니다. 턴에는
[Format attached: …] 포인터가 실리고 Agent가 그 파일을 여므로, 본문은 크기와 무관하게 문장
중간에서 잘린 조각이 아니라 통째로 도착합니다 — 여기에는 어떤 상한도 없습니다. Format을
저작한다면 Format 개요의 “SKILL.md 크기는 얼마여야 하나”를 참고하세요.
은 structured output까지 가지 않습니다
양쪽을 설계하기 전에 알아 둘 값입니다. output은 에이전트가 만들지 않습니다. run이 만든
미디어와 마지막 텍스트로부터 사후에 projection되며, 여러분의 input은 projection의 입력에
없습니다. 보낸 값 — 주문 id, SKU, 자체 로케일 — 은 run이 마무리 텍스트에서 스스로 되풀이하지
않는 한 output에 담길 수 없습니다.
그러니 output_schema로 자기 식별자를 돌려받으려 하지 마세요. 식별자는 여러분 쪽에 run.id나
Idempotency-Key로 키를 잡아 두고, output에는 run이 만든 것만 담으세요. 전체 동작은
파싱은 run 이후에 일어납니다에
있습니다.
멱등성
매 호출에 Idempotency-Key를 보내세요. 같은 본문으로 재전송하면 200과 원래 run이
돌아옵니다. 다른 본문 — 다른 instruction 포함 — 으로 재전송하면 409입니다.
Spend caps
모든 Format에는 generation spend cap이 있으며, run은 자신의 유효 cap을 넘길 수 없습니다. Format의 cap은 run이 따로 지정하지 않았을 때 물려받는 값입니다.
현재 값은 PublicFormat.generation_spend_cap_usd_micros에서 읽습니다. 항상 숫자입니다.
cap을 한 번도 지정하지 않은 Format은 플랫폼 기본값 $400을 쓰며, 출력 종류와 무관합니다.
Format을 등록할 때 generation_spend_cap_usd로 직접 설정하세요 — 0보다 크고
500 이하인 유한한 숫자입니다. null로 지우면 Format은 $400 기본값으로 돌아갑니다.
run 요청의 generation_spend_cap_usd는 플랫폼 최대치 $500까지 그 run만의
천장을 지정합니다. Format 자체의 cap보다 큰 값도 그대로 적용되며 아래로 클램프되지
않습니다 — 등록 당시보다 긴 프로덕션이라면 run 단위로 예산을 올릴 수 있습니다.
500을 넘으면 조용히 깎이는 대신 400입니다. 생략하면 run은 Format의 cap을 받습니다.
API 위 run은 unattended입니다
Format 본문은 대화형 채팅용으로 쓰이며, 사람을 기다리며 멈출 수 있습니다 — "비디오를 만들기 전에 이 미리보기 스틸을 승인하세요"는 Agents UI의 의도된 품질 게이트입니다.
API에는 물어볼 사람이 없습니다. 그래서 API run의 프롬프트에는 그 승인이 이미 허용됨이며 Format의 spend cap 안에서 유료 단계까지 계속해야 한다고 알려 줍니다. Scheduled run도 같습니다. 대화형 Agents UI만 여전히 멈추고 기다립니다.
정말로 끝낼 수 없는 run은 completed가 아니라 failed로 돌아옵니다.
status: "completed"를 실제 결과로 취급하세요. 중간에 멈춘 run을 대신 넘겨주지
않습니다.
401 vs 403 vs 404
HTTP 클래스가 첫 분기이고, error.code가 두 번째입니다. 키가 없으면 401 unauthorized입니다. 알려진 키에 formats:read / formats:write가 없으면 403 insufficient_scope이며, 절대 404 format_not_found가 아닙니다. 기존 키에 스코프를
덧붙일 수는 없습니다. API Keys에서 새 키를
만들고 교체하세요.
| HTTP | error.code | When | Authority |
|---|---|---|---|
| 401 | unauthorized | 키 없음, 잘못된 키, 자격 증명 두 개, 폐기됨, 알 수 없음. next_action은 authenticate. | Official: RFC 9110 §15.5.2. Product SoT: OpenAPI 401. |
| 403 | insufficient_scope | 유효한 키에 formats:read / formats:write가 없음. details.required_scope가 이름을 가리킴. next_action은 authenticate. | Official: RFC 9110 §15.5.4; RFC 6750 insufficient_scope. |
| 403 | insufficient_scope | Format run 또는 패키지 쓰기의 서비스 계정 키 (details.reason은 service_account_format_runs_unsupported 또는 service_account_format_authoring_unsupported). | Product SoT: 같은 코드, details.reason으로 구분. 새 403 코드를 만들지 않음. |
| 403 | workspace_key_required | 팀 워크스페이스 멤버이지만 키가 그 워크스페이스에서 발급되지 않음. details.workspace_id가 가리킴. | Product SoT. 멤버에게 팀 키를 만들라고 말하기 위해 404와 구분. |
| 404 | format_not_found | 알 수 없음, 보관됨, 이 키의 워크스페이스 밖, 또는 멤버가 아닌 팀 handle. 맞는 handle 위의 멤버 팀 키는 이 404가 아님. | Product SoT / #2393. 의도적 테넌시 숨김 — "다른 곳에 Format이 있다"거나 "작성자가 아니다"가 아님. |
| 404 | format_run_not_found | 알 수 없는 run id이거나 다른 소유자의 run. | Product SoT / #2393. 같은 숨김. |
| 404 | format_run_queue_not_found | 알 수 없는 bulk-run 큐이거나 다른 소유자의 큐. | Product SoT. |
| 404 | previous_run_not_found | previous_run_id를 모르거나 내 것이 아님. | Product SoT. Format 주소는 유효했고 continuity id가 아니었음. |
| 404 | format_content_not_found | 이 키에 Format은 있지만 그 패키지 경로는 없음. | Product SoT. |
오류
| Code | Status | What to do |
|---|---|---|
unauthorized | 401 | 없거나, 잘못되었거나, 폐기되었거나, 알 수 없는 API 키. next_action은 authenticate. |
insufficient_scope | 403 | 키에 formats:read / formats:write가 없습니다. 이 기능 이전에 발급된 키에는 없습니다 — 새 키를 만드세요. next_action은 authenticate. format_not_found가 아닙니다. |
workspace_key_required | 403 | Format이 팀 워크스페이스 소유인데 키가 그 워크스페이스에서 발급되지 않았습니다. details.workspace_id에서 만든 키를 쓰세요. next_action은 authenticate. |
format_not_found | 404 | 알 수 없거나, 보관되었거나, 이 키의 워크스페이스 밖이거나, 멤버가 아닌 팀 handle입니다. 맞는 {handle}/{slug} 위의 멤버 팀 키는 200이며 이 404가 아닙니다. |
format_not_forkable | 409 | Format 카드가 아니라 내장 기능을 주소로 잡았습니다. Formats by Sume 또는 직접 만든 Format을 호출하세요. |
format_api_trigger_disabled | 409 | 이 Format의 API 호출 트리거가 꺼져 있습니다. |
format_inactive | 409 | Format이 비활성입니다. API run을 받으려면 active로 설정하세요. |
format_run_in_progress | 409 | on_active_run: "reject"이고 이미 진행 중인 run이 있습니다. |
idempotency_conflict | 409 | 그 Idempotency-Key가 다른 페이로드로 이미 사용되었습니다. |
output_schema_invalid | 400 | output_schema가 지원 부분집합 밖입니다. details.violations[]가 각 문제를 가리킵니다 — 지원 스키마를 참고하세요. |
다음
- 구조화 출력 — 스키마를 바인딩하고 typed JSON을 받기
- 대량 실행 — concurrency 창으로 run을 최대 100개까지 큐에 넣기
- 실행과 결과 — receipt, 폴링, 취소
- 제품에 Format 임베드하기 — 파트너 연동 전체