조직 업무 만들기
POST /v1/works로 업무 설명(명세, spec)을 보냅니다. UpServe는 조직에 새 팀(팀장과 담당 AI 1명)을 만들고, 그 팀을 업무에 맞게 전문화합니다. 구성을 조립하고, 시험하고, 팀에 발행합니다. 이 과정은 준비(preparation) 로 따라가며, 준비가 끝나면 쓸 수 있습니다.
- 결과는 조직의 UpServe 화면에 있는 팀이며 Deployment가 아닙니다. 이 API로 그 팀에 일을 맡기는 경로는 아직 없습니다.
- 조직 Project만 쓸 수 있습니다. 개인 공간의 Project는 모든 업무 경로가
404 NOT_FOUND입니다. - 다른
/v1경로와 같이 Private Beta 동안은 허용된 Project만 호출할 수 있습니다. 업무용으로 Project를 허용할 때 그 조직의 전문화 구성 실행도 함께 켭니다. 준비가RECIPE_ACCESS_DENIED로 끝나면 문의하세요.
시작 전에
| scope | 허용하는 작업 |
|---|---|
works:read | 준비 조회와 목록 |
works:write | 업무 접수, 명세 수정, 질문 답 |
works:approve | 고객 서비스에서 받은 사람의 범위 확인 답 제출(키마다 고르는 명시적 별도 위임) |
- works scope가 하나 이상 있고 나머지가
usage:read뿐인 키는 Deployment 없이 만들 수 있습니다. 그 밖의 scope를 섞은 키는 지금처럼 Deployment가 하나 이상 필요합니다. - 팀의 관리자는 키를 만든 OWNER입니다. 그 사람이 OWNER가 아니게 되면 키도 쓸 수 없습니다.
- 준비의 질문 문장은 관리자의 언어를 따릅니다. 한국어 사용자면 한국어, 그 밖에는 영어입니다.
- 준비 비용은 실행 비용과 같은 방식으로 청구되고 Project의 일·월 지출 한도에 들어갑니다. 팀은 자율 기상을 끈 채 만들어지므로 스스로 비용을 쓰지 않습니다.
usage:read가 있으면GET /v1/usage의preparations에서 준비 비용을 실행 비용과 따로 볼 수 있습니다. 사용량을 보세요.
흐름
POST /v1/works로 업무를 보냅니다. (works:write,Idempotency-Key필수)- 상태가 끝날 때까지
GET /v1/preparations/{preparation_id}를 읽습니다. (works:read) - 상태가
NEEDS_INPUT이면POST /v1/preparations/{preparation_id}/answers로 질문에 답합니다. - 상태가
SUCCEEDED이고team_id가 있으면 준비가 끝난 것입니다.
curl -s -X POST "$BASE/v1/works" \
-H "Authorization: Bearer $UPSERVE_API_KEY" \
-H "Idempotency-Key: work-0001" \
-H "Content-Type: application/json" \
-d @work.json{
"spec": {
"purpose": "Turn each incoming quote request into a quote from the approved catalog.",
"success_criteria": ["Every request line has a source or a question for a person."],
"sources": [{"ref": "synthetic:catalog", "revision": "1"}],
"allowed_actions": ["READ_APPROVED_CATALOG", "CREATE_QUOTE"],
"delivery": {"channel": "EMAIL", "target_ref": "synthetic:approved-operator"}
}
}응답은 202이고, Location: /v1/preparations/{preparation_id} 헤더와 준비 자체가 옵니다.
{
"kind": "PREPARATION_VIEW",
"contract_version": 1,
"preparation_kind": "SPECIALIZE",
"work_id": "22222222-2222-4222-8222-222222222222",
"revision": 1,
"preparation_id": "33333333-3333-4333-8333-333333333333",
"preparation_revision": 2,
"owner": {"kind": "ORGANIZATION", "id": "11111111-1111-4111-8111-111111111111"},
"status": "QUEUED",
"stage": "CREATE",
"support": "SUPPORTED",
"reason_codes": [],
"missing_fields": [],
"questions": [],
"next_actions": [],
"retryable": false,
"spec": {"purpose": "Turn each incoming quote request into a quote from the approved catalog."},
"usage": {"status": "PENDING", "cost_su": null}
}202와QUEUED는 접수이지 준비 완료가 아닙니다. 준비를 계속 읽으세요.- 준비에는 웹훅이나 SSE 이벤트가 없습니다. 10~30초 정도 간격으로 조회하세요.
- 전체 응답 schema는 OpenAPI 파일의
WorkPreparationPreparationView입니다.
요청 본문
| 필드 | 설명 |
|---|---|
spec | 업무 설명입니다. spec.purpose만 필수입니다. 나머지(성공 기준, 입출력, 예시, 자료, 연결, 허용 행동, 시작 조건, 결과 전달, 사람 판단, 사실, 가정)를 채울수록 결과가 좋아집니다. |
work_id, expected_revision | 이 Project가 만든 업무를 고칠 때만 씁니다. 둘을 함께 보내거나 둘 다 빼세요. |
- 모르는 필드는
422 INVALID_INPUT으로 거절합니다. 소유자, 지원 프로필, 레시피를 보내지 마세요. 소유자는 늘 키의 조직이고 구성은 UpServe가 고릅니다. connections에는 참조 이름만 넣습니다. 명세에 자격증명을 넣지 마세요.- 규칙에 어긋난 명세는
422 INVALID_SPEC이고, 어긋난 필드나 규칙이details.reason에 옵니다.
준비 상태
status | 의미 |
|---|---|
NEEDS_INPUT | 빠진 것이 있습니다. questions에 답하세요. |
READY | 명세가 다 찼습니다. 바로 접수됩니다. |
QUEUED, RUNNING | 접수되어 진행 중입니다. stage가 단계를 보여 줍니다: CREATE, ASSEMBLE, VALIDATE, BIND, PUBLISH. |
REQUIRES_ACTION | 넓어진 범위를 사람이 확인해야 합니다(아래 참고). |
CANCEL_REQUESTED | 닫는 중입니다. 예를 들어 범위 확인에서 지금 구성을 유지하기로 한 경우입니다. |
SUCCEEDED | 준비가 끝났습니다. team_id가 그 팀입니다. |
FAILED | 끝났습니다. 사유는 reason_codes에 있습니다. |
CANCELED | 발행하지 않고 끝났습니다. |
next_actions는 조회한 시점에 다음에 할 수 있는 일입니다. 권한이 아닙니다. 요청마다 다시 검사합니다.- 조직 준비에는 다시 시도나 취소 경로가 없어서
next_actions에RETRY나CANCEL이 나오지 않습니다. unsupported_actions는 업무를 지원하지 못할 때allowed_actions중 UpServe가 할 수 없는 행동입니다.
질문에 답하기
{
"expected_preparation_revision": 1,
"answers": [{"question_id": "delivery-target", "value": "synthetic:approved-recipient"}]
}expected_preparation_revision에는 읽은preparation_revision을 넣습니다. 그 사이 준비가 바뀌었으면409 REVISION_CONFLICT입니다. 다시 읽고 지금 질문에 답하세요.- 한 요청에 답을 20개까지 넣을 수 있습니다. 모두 함께 반영되거나 하나도 반영되지 않습니다.
- 열려 있지 않은 질문에 답하면
409 QUESTION_NOT_FOUND, 더는 답을 받지 않는 준비에 답하면409 INVALID_TRANSITION입니다. - 응답은
200과 바뀐 준비입니다. 명세가 다 차면 같은 요청에서 바로 접수됩니다.
범위 확인
범위 확인은 이미 발행된 업무의 명세를 고쳤고, 새 구성이 지금 구성보다 할 수 있는 일이 많을 때(새 도구, 새 외부 행동, 비용 증가)만 나옵니다. 새 업무의 첫 발행에서는 묻지 않습니다. 이때 준비는 REQUIRES_ACTION이고, changes와 package_hash를 담은 질문 Q_SCOPE_EXPANSION 하나가 있으며, next_actions는 CONFIRM_SCOPE입니다.
바뀌는 점을 고객 서비스의 사람에게 보여 주고 그 결정을 보냅니다.
{
"expected_preparation_revision": 7,
"answers": [{"question_id": "Q_SCOPE_EXPANSION", "value": {"decision": "APPLY", "package_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}}],
"actor": {"subject": "customer-user-42"}
}- 키에
works:write와works:approve가 모두 있어야 합니다.works:approve가 없으면403 ACTION_NOT_RESOLVABLE_BY_CALLER입니다. - 이 답 하나만,
actor.subject(고객 서비스가 확인한 사람의 불투명 ID)와 질문의package_hash를 함께 보냅니다. 아니면422 INVALID_INPUT입니다. APPLY면 같은 준비가 이어서 돕니다(QUEUED, 단계PUBLISH).KEEP이면 지금 구성을 유지하고 준비를 닫습니다.- 사람이 본 뒤 후보가 바뀌었으면
409 PACKAGE_CHANGED입니다. 새 질문을 다시 보여 주세요. 7일 기한이 지나면409 INVALID_TRANSITION입니다. - UpServe는 결정한 사람을 키와 따로 기록합니다. 응답에는 나오지 않습니다.
준비 목록
GET /v1/preparations는 이 Project의 준비를 최신순으로 items와 next_cursor에 담아 돌려줍니다. (works:read)
limit은 1~100(기본 20)입니다. 다음 쪽은 직전 응답의next_cursor를cursor에 넣습니다.work_id를 주면 한 업무의 준비만 봅니다.- 같은 조직이어도 다른 Project의 준비는 목록에 나오지 않습니다.
업무 명세 고치기
work_id와 읽은 expected_revision, 새 명세를 담아 POST /v1/works를 다시 보냅니다.
- 이 Project가 만든 업무만 고칠 수 있습니다. 그 밖의
work_id는404 NOT_FOUND입니다. - 읽은 뒤 업무가 바뀌었으면
409 REVISION_CONFLICT입니다. - 아직
NEEDS_INPUT이나READY인 열린 준비는 새 준비로 바뀝니다. 이미QUEUED이후인 준비가 있으면409 PREPARATION_IN_PROGRESS이고details.preparation_id가 옵니다. 그 준비가 끝나길 기다리세요.
멱등과 한도
- 모든 쓰기에는
Idempotency-Key가 필요합니다. 같은 키와 같은 본문을 다시 보내면 같은 응답이 옵니다. 같은 키에 다른 본문은409 IDEMPOTENCY_CONFLICT입니다. - 키는 Project 범위입니다. 같은 조직의 다른 Project가 같은 키 값을 써도 섞이지 않습니다.
- 쓰기는 Turn, Run 접수와 같은 접수 속도 한도에 들어갑니다. 조회는 조회 한도에 들어갑니다. 한도와 데이터를 보세요.
준비가 실패했을 때
FAILED로 끝난 준비는 다시 시도되지 않습니다. 원인을 해결한 뒤 새 Idempotency-Key로 업무를 다시 보내거나, work_id로 고쳐 보냅니다.
reason_codes | 의미 | 다음 행동 |
|---|---|---|
PROJECT_BUDGET_EXCEEDED | Project의 일 또는 월 지출 한도에 닿았습니다. 팀을 만들기 전에 멈춥니다. | 한도 창이 지난 뒤 다시 보내거나 한도를 올려 달라고 요청합니다. |
AUTHORIZATION_REVOKED | 키가 폐기됐거나, 키를 만든 사람이 더는 조직 OWNER가 아닙니다. | 유효한 키로 다시 보냅니다. |
TEAM_CREATE_REFUSED | 팀이나 담당 AI를 만들지 못했습니다. 예를 들어 조직의 담당 AI 수 한도에 닿은 경우입니다. | 조직의 UpServe 화면에서 원인을 해결한 뒤 다시 보냅니다. |
RECIPE_ACCESS_DENIED | 그 조직에 전문화 구성 실행이 켜져 있지 않습니다. | 켜 달라고 문의한 뒤 다시 보냅니다. |
UpServe가 지원할 수 없는 명세는 support가 UNSUPPORTED로 끝나고, 어떤 행동이 안 되는지 unsupported_actions에 나옵니다. 이 경로의 HTTP 오류는 오류와 재시도에 있습니다.