본문으로 건너뛰기

워크플로우

워크플로우(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 오류와 함께 친절한 이유를 알려줍니다.

  • 아직 실행되지 않은(뒤에 있는) 블럭의 결과를 가져오려 할 때
  • 존재하지 않는 결과 필드를 가리킬 때
  • 서로 종류가 맞지 않는 연결을 시도할 때(예: 음성 결과를 글 입력으로 넣기)
문장 속에 끼워 넣는 건 언제나 OK

"다음 초안을 다듬어줘:\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을 오래 보관하지 말고, 필요할 때 이 조회로 최신 URL을 다시 받아 쓰세요.


다음으로​