워크플로우
워크플로우(workflow) 는 여러 AI 작업을 순서대로 이어 붙여 한 번에 실행하는 기능입니다.
예를 들어 "① 글 초안 작성 → ② 그 초안을 음성으로 변환" 처럼, 앞 작업의 결과를 뒤 작업이 이어받아 쓸 수 있어요. 각각을 따로 호출할 필요 없이, 한 번의 요청으로 처리됩니다.
각 단계를 블럭(block) 이라고 부릅니다. 블럭들이 위에서 아래로 차례대로 실행돼요(선형 체인). 중간에 하나라도 실패하면 거기서 멈춥니다.
블럭 만들기
각 블럭은 아래 세 가지로 구성됩니다.
{
"id": "draft",
"model": "modoo-text",
"input": { "prompt": "신규 카페 홍보 문구를 써줘" }
}
id— 이 블럭의 이름(뒤 블럭에서 결과를 가리킬 때 사용)model— 사용할 AI 모델input— 이 블럭에 넣을 입력값
앞 블럭의 결과 이어받기
뒤 블럭에서는 {{블럭id.필드}} 형태로 앞 블럭의 결과를 가져다 쓸 수 있습니다.
예를 들어 draft 블럭이 만든 글(text)을 다음 블럭이 음성으로 바꾸려면 이렇게 씁니다.
[
{
"id": "draft",
"model": "modoo-text",
"input": { "prompt": "신규 카페 홍보 문구를 써줘" }
},
{
"id": "voice",
"model": "modoo-tts-minimax",
"input": { "text": "{{draft.text}}" }
}
]
여기서 {{draft.text}} 는 "draft 블럭이 만든 글을 여기에 넣어라"라는 뜻입니다.
블럭 종류별로 이어받을 수 있는 결과 필드
블럭마다 다음 블럭에서 참조할 수 있는 결과 필드가 정해져 있습니다.
| 블럭 종류 | 참조 가능한 필드 |
|---|---|
| 텍스트 생성 / 음성 인식(STT) | text |
| 이미지 분석 / 문서 분석 | content |
| 음성 합성(TTS) | audio_url |
| 이미지 생성 | image_url, image_urls, fileKeys |
| 비디오 생성 | video_url, fileName |
음성·비디오 결과는 다음 블럭의 입력으로 이어지지 않습니다(종단). 즉, 음성이나 영상을 만드는 블럭은 워크플로우의 마지막 단계로 두세요.
실행 전 호환성 검증 (안심하고 쓰세요)
워크플로우를 실행하기 전에, 시스템이 블럭 연결이 올바른지 미리 확인해 줍니다. 잘못된 연결 때문에 크레딧을 낭비하지 않도록 막아 주는 안전장치예요.
다음과 같은 경우 실행을 시작하지 않고 400 invalid_workflow 오류와 함께 친절한 이유를 알려줍니다.
- 아직 실행되지 않은(뒤에 있는) 블럭의 결과를 가져오려 할 때
- 존재하지 않는 결과 필드를 가리킬 때
- 서로 종류가 맞지 않는 연결을 시도할 때(예: 음성 결과를 글 입력으로 넣기)
"다음 초안을 다듬어줘:\n{{draft.text}}" 처럼 문장 안에 결과를 끼워 넣는 경우는 항상 텍스트로 허용됩니다. 걱정 없이 쓰세요.
과금 안내
워크플로우는 블럭마다 개별로 크레딧이 차감됩니다. 응답의 total_charge가 전체 합계이고, 각 결과의 charge가 해당 블럭의 차감액입니다.
엔드포인트
기본 URL은 https://modoo.devdive.me입니다. 모든 요청에는 인증 헤더가 필요합니다.
Authorization: Bearer sk-modoo-...
POST /v1/workflows/runs — 실행하고 결과 저장 (권장)
워크플로우를 실행하고 결과를 저장합니다. 나중에 다시 조회할 수 있어 가장 추천하는 방식이에요.
# 이 요청은: 워크플로우를 실행하고 결과를 저장합니다.
curl https://modoo.devdive.me/v1/workflows/runs \
-H "Authorization: Bearer sk-modoo-..." \
-H "Content-Type: application/json" \
-d '{
"blocks": [
{ "id": "draft", "model": "modoo-text", "input": { "prompt": "카페 홍보 문구" } },
{ "id": "voice", "model": "modoo-tts-minimax", "input": { "text": "{{draft.text}}" } }
]
}'
응답 예시 — run_id로 나중에 다시 조회할 수 있고, total_charge가 전체 차감 크레딧입니다.
{
"run_id": "run_abc123",
"status": "succeeded",
"total_charge": 0.15,
"results": [
{ "id": "draft", "model": "modoo-text", "output": { "text": "지금 오픈!" }, "charge": 0.05 },
{ "id": "voice", "model": "modoo-tts-minimax", "output": { "audio_url": "https://.../voice.mp3" }, "charge": 0.10 }
]
}
POST /v1/workflows/run — 실행만 하고 결과는 바로 받기 (저장 안 함)
결과를 저장하지 않고 바로 응답으로만 돌려받습니다. 한 번 쓰고 말 때 간편해요.
# 이 요청은: 워크플로우를 실행하고 결과만 즉시 받습니다(저장 안 함).
curl https://modoo.devdive.me/v1/workflows/run \
-H "Authorization: Bearer sk-modoo-..." \
-H "Content-Type: application/json" \
-d '{
"blocks": [
{ "id": "draft", "model": "modoo-text", "input": { "prompt": "카페 홍보 문구" } }
]
}'
응답 예시
{
"results": [
{ "id": "draft", "model": "modoo-text", "output": { "text": "지금 오픈!" }, "charge": 0.05 }
],
"total_charge": 0.05
}
POST /v1/workflows/stream — 블럭별 진행 상황 실시간 보기
블럭이 하나씩 진행될 때마다 실시간으로 상황을 알려줍니다. 긴 워 크플로우의 진행 상태를 화면에 보여줄 때 좋아요. (이 런은 저장됩니다.)
이 방식도 SSE(Server-Sent Events) 라, 서버가 data: ... 형태의 줄을 계속 보내줍니다. 각 줄에는 어떤 일이 일어났는지 알려주는 type이 들어 있어요.
이벤트 type | 언제 오나요 | 함께 오는 정보 |
|---|---|---|
block_start | 한 블럭이 시작될 때 | index, block_id, model |
block_done | 한 블럭이 끝났을 때 | output, charge, total_charge |
block_error | 한 블럭이 실패했을 때 | block_id, error |
done | 워크플로우 전체가 끝났을 때 | run_id, status, total_charge, results, error |
# 이 요청은: 블럭별 진행 상황을 실시간으로 받습니다.
curl https://modoo.devdive.me/v1/workflows/stream \
-H "Authorization: Bearer sk-modoo-..." \
-H "Content-Type: application/json" \
-d '{
"blocks": [
{ "id": "draft", "model": "modoo-text", "input": { "prompt": "카페 홍보 문구" } },
{ "id": "voice", "model": "modoo-tts-minimax", "input": { "text": "{{draft.text}}" } }
]
}'
응답은 아래처럼 여러 줄이 순서대로 도착합니다.
data: {"type": "block_start", "index": 0, "block_id": "draft", "model": "modoo-text"}
data: {"type": "block_done", "output": {"text": "지금 오픈!"}, "charge": 0.05, "total_charge": 0.05}
data: {"type": "block_start", "index": 1, "block_id": "voice", "model": "modoo-tts-minimax"}
data: {"type": "block_done", "output": {"audio_url": "https://.../voice.mp3"}, "charge": 0.10, "total_charge": 0.15}
data: {"type": "done", "run_id": "run_abc123", "status": "succeeded", "total_charge": 0.15, "results": [...], "error": null}
GET /v1/workflows/runs/{run_id} — 저장된 실행 결과 다시 보기
앞서 저장된 워크플로우 실행 결과를 run_id로 다시 조회합니다.
# 이 요청은: 저장된 워크플로우 실행 결과를 다시 가져옵니다.
curl https://modoo.devdive.me/v1/workflows/runs/run_abc123 \
-H "Authorization: Bearer sk-modoo-..."
응답 예시
{
"run_id": "run_abc123",
"status": "succeeded",
"total_charge": 0.15,
"results": [
{ "id": "draft", "model": "modoo-text", "output": { "text": "지금 오픈!" }, "charge": 0.05 },
{ "id": "voice", "model": "modoo-tts-minimax", "output": { "audio_url": "https://.../voice.mp3" }, "charge": 0.10 }
],
"error": null,
"created_at": "2026-07-01T09:00:00Z"
}
결과에 담긴 음성·이미지·영상 URL은 시간이 지나면 만료됩니다. URL을 오래 보관하지 말고, 필요할 때 이 조회로 최신 URL을 다시 받아 쓰세요.