프롬프트 라이브러리
프롬프트를 코드가 아니라 워크스페이스에서 관리합니다. 버전과 레이블이 있고, 어떤 OpenAI SDK에서든 ID로 호출할 수 있습니다. 레이블을 옮기면 다음 요청부터 코드가 새 버전을 받으며 재배포가 필요 없습니다.
프롬프트 호출하기
일반 /v1/chat/completions, /v1/responses 또는 /v1/messages 엔드포인트를 그대로 쓰고, 요청 본문에 prompt_id와 prompt_variables를 추가합니다. SDK는 model과 messages를 필수로 요구하므로 모델 이름은 아무거나, 메시지는 빈 user 메시지 하나를 보내면 됩니다. OpenAI와 Anthropic SDK에서는 추가 필드를 extra_body에 넣습니다.
import os
from openai import OpenAI
client = OpenAI(base_url="https://synthorai.io/v1", api_key=os.environ["SYNTHORAI_API_KEY"])
reply = client.chat.completions.create(
model="any", # the version's model is used
messages=[{"role": "user", "content": ""}], # required by the SDK; dropped
extra_body={
"prompt_id": "support-reply",
"prompt_variables": {
"product": "Acme Cloud",
"customer_message": "My invoice shows two charges.",
},
},
)
print(reply.choices[0].message.content) HTTP로 직접 호출할 때는 이 필드들을 본문 최상위에 둡니다. 아래 호출은 staging 레이블이 가리키는 버전을 요청합니다.
curl https://synthorai.io/v1/chat/completions \
-H "Authorization: Bearer $SYNTHORAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "any",
"messages": [],
"prompt_id": "support-reply",
"prompt_label": "staging",
"prompt_variables": {"product": "Acme Cloud", "customer_message": "My invoice shows two charges."}
}' 필드
| 필드 | 타입 | 역할 |
|---|---|---|
prompt_id | string | 워크스페이스 안에서의 프롬프트 ID로, 프롬프트 페이지에 표시된 값과 같습니다. |
prompt_variables | object | 버전 안 {{name}} 변수에 넣을 값으로, 문자열·숫자·불리언을 텍스트로 넣습니다. 빠뜨린 변수는 버전의 기본값을 쓰고, 기본값이 없으면 호출이 실패합니다. |
prompt_version | integer | 특정 버전으로 고정합니다. 지정하지 않으면 production 레이블이 가리키는 버전을 씁니다. |
prompt_label | string | staging 같은 다른 레이블이 가리키는 버전을 호출합니다. 버전과 레이블 중 하나만 보내세요. |
요청이 어떻게 바뀌는지
- 버전의 메시지가 먼저, 그다음에 내 메시지가 옵니다. 대화를 이어 가려면 내 메시지를 보내면 됩니다. 이전 턴, 도구 호출, 도구 결과는 보낸 그대로 유지되고, SDK 때문에 보내는 빈 user 메시지만 제거됩니다.
- 요청의 모델은 버전의 모델로 바뀝니다. 버전에 모델이 없으면 보낸 모델을 그대로 씁니다.
- 내가 보낸 파라미터가 우선합니다. 버전의 temperature, max_tokens, top_p, JSON 모드는 요청에 같은 파라미터가 없을 때만 적용됩니다.
- 4개의
prompt_*필드는 게이트웨이에서 멈춥니다. 제공업체에는 일반 요청이 전달됩니다. /v1/responses에서는 메시지가input에 들어가고(문자열 input은 내 user 턴이 됩니다),max_tokens는max_output_tokens로, JSON 모드는text.format으로 바뀝니다.
/v1/messages에서
같은 네 개의 필드는 Anthropic SDK에서도 그대로 쓸 수 있습니다. 버전의 system 텍스트는 직접 보낸 system 앞에, 버전의 메시지는 직접 보낸 메시지 앞에 놓이며, temperature, top_p, max_tokens는 요청에서 지정하지 않은 경우에만 적용됩니다. 이 엔드포인트에는 JSON 모드에 해당하는 필드가 없어 그 설정은 전송되지 않습니다.
import os
from anthropic import Anthropic
client = Anthropic(base_url="https://synthorai.io", api_key=os.environ["SYNTHORAI_API_KEY"])
reply = client.messages.create(
model="any", # the version's model is used
max_tokens=1024,
messages=[{"role": "user", "content": ""}], # required by the SDK; dropped
extra_body={
"prompt_id": "support-reply",
"prompt_variables": {
"product": "Acme Cloud",
"customer_message": "My invoice shows two charges.",
},
},
)
print(reply.content[0].text) 도구 호출과 멀티턴 대화
라이브러리 프롬프트를 쓰지 않을 때와 똑같이 tools와 지금까지의 대화를 보내세요. 시스템 프롬프트와 첫 메시지는 버전이 맡고, 모델의 도구 호출과 내 도구 결과를 포함한 나머지 대화는 내 메시지가 담습니다.
# Round 2 of a tool loop: send the conversation so far, as without a prompt.
# The gateway puts the version's messages first and these after them.
reply = client.chat.completions.create(
model="any",
tools=tools,
messages=[
{"role": "user", "content": ""}, # the SDK placeholder, dropped
first.choices[0].message, # the model's tool call
{"role": "tool", "tool_call_id": call.id, "content": lookup_invoice(call)},
],
extra_body={"prompt_id": "support-reply", "prompt_variables": variables},
) 버전에 담는 도구와 출력 스키마
버전에는 함수 도구, 도구 선택 방식, 응답이 따라야 할 JSON 스키마를 담을 수 있으며, 호출하는 엔드포인트의 형식으로 기록됩니다. 요청에 담아 보낸 도구는 버전의 도구 뒤에 추가되고, 이름이 같으면 요청의 도구로 대체됩니다. 요청에 지정한 tool_choice와 응답 형식이 우선합니다.
파셜
파셜은 한 번만 저장해 두고 여러 프롬프트에서 {{>id}}로 포함해 쓰는 텍스트 블록입니다. 프롬프트 버전을 저장하면 각 포함 구문이 그 시점의 파셜 최신 버전으로 고정되어 {{>id@4}}처럼 표시되므로, 이후 파셜을 바꿔도 저장된 버전은 달라지지 않습니다. 더 새로운 파셜 버전이 생기면 프롬프트 페이지에 표시되고, 업데이트하면 프롬프트의 새 버전이 저장됩니다. 파셜 안의 변수는 호출 시 보낸 prompt_variables로 채워집니다. 파셜은 단독으로 호출할 수 없고, 저장된 버전이 포함하고 있는 파셜은 삭제할 수 없습니다.
버전과 레이블
저장할 때마다 다음 버전이 만들어지고, 저장된 버전은 바뀌지 않습니다. 모든 프롬프트에 production, staging, development 레이블이 있으며 직접 레이블을 추가할 수도 있습니다. production을 어떤 버전에 지정하면 배포, 이전 버전으로 되돌리면 롤백입니다. 코드는 같은 ID를 계속 호출합니다.
레이블 이동이나 삭제는 약 10초 안에 호출에 반영됩니다. 레이블 이동과 프롬프트 삭제는 관리자나 워크스페이스 소유자만 할 수 있습니다.
초안 실행해 보기
Prompts 페이지의 편집기는 왼쪽에서 초안을 쓰고 오른쪽에서 바로 실행해 볼 수 있습니다. 각 변수에 값을 넣고 Run을 누르면 초안이 렌더링되어 지정한 모델로 전송되고, 응답이 지연 시간, 비용과 함께 표시됩니다. 이 호출은 Playground 호출과 같은 방식으로 과금·기록되며, 버전을 저장하기 전까지 초안 자체는 저장되지 않습니다. Show the request는 모델을 호출하지 않고 엔드포인트별로 렌더링된 요청을 보여 줍니다.
배포 전에 버전 테스트하기
프롬프트의 테스트에는 테스트 세트를 저장할 수 있습니다. 각 행은 변수 값이며, 필요하면 user 메시지와 기대 응답을 함께 둘 수 있습니다. 응답이 통과해야 할 검사(특정 텍스트 포함, 패턴 일치, 기대 응답과 일치, 유효한 JSON, 출력 스키마 준수, 지연 시간이나 비용 상한, 직접 쓴 기준에 따라 모델이 판정)도 설정할 수 있습니다. 실행하면 선택한 버전과 비교 대상 버전을 행마다 호출해 두 응답을 나란히 보여 주고, 통과한 행 수와 각 버전의 비용, 지연 시간을 알려 줍니다. 각 호출은 Playground 호출과 같은 방식으로 과금·기록되며, 한 번의 실행은 하나의 트레이스로 묶입니다. 레이블을 옮길 때 대화상자에 해당 버전의 최근 실행 결과가 표시됩니다. 참고용이며 이동을 막지는 않습니다. 테스트 세트와 실행 응답은 암호화되어 저장되고, 응답은 30일간 보관됩니다.
점진적 배포
레이블은 호출의 일부를 다른 버전으로 보낼 수 있습니다(예: "production: v6, v7 10%"). 어느 버전을 받을지는 세션 ID로 정해지고, 세션이 없으면 최종 사용자, 그것도 없으면 요청 단위로 정해지므로 하나의 대화는 같은 버전에 머뭅니다. X-Synthorai-Prompt-Version로 어떤 버전이 응답했는지 알 수 있고, Prompts 페이지에서 두 버전을 나란히 비교할 수 있습니다. 관리자는 비율을 바꾸거나, 레이블을 후보 버전으로 옮기거나, 배포를 중지할 수 있습니다. prompt_version으로 버전을 고정한 호출은 대상이 아닙니다.
변경 웹훅
관리자는 Prompts 페이지에서 주소를 최대 3개까지 추가할 수 있으며, 프롬프트가 생성되거나, 버전이 추가되거나, 레이블이 이동하거나, 점진적 배포가 바뀌거나, 삭제될 때 POST를 받습니다. 모든 요청에는 서명이 붙습니다. X-Synthorai-Signature: t=…,v1=…는 주소를 추가할 때 한 번만 표시되는 시크릿으로 "타임스탬프, 마침표, 원본 본문"을 HMAC-SHA256한 값입니다. 버전의 텍스트는 해당 주소에서 켠 경우에만 전송됩니다. 전달에 실패하면 약 30분에 걸쳐 세 번 더 재시도하고, 이벤트 다섯 건을 연속으로 포기하면 주소가 꺼지며 다시 켤 때까지 전송되지 않습니다.
POST /hooks/prompts
X-Synthorai-Event: prompt.label_moved
X-Synthorai-Signature: t=1791140000,v1=5f2c…
{
"type": "prompt.label_moved",
"created_at": "2026-10-05T03:12:44Z",
"prompt": "support-reply",
"kind": "prompt",
"label": "production",
"from": 6,
"version": 7,
"by": 42
}
# Verify: hex(HMAC-SHA256(secret, "1791140000" + "." + raw_body)) == v1 가져오기, 내보내기, OpenAI의 저장된 프롬프트
새 프롬프트 › 가져오기는 붙여넣은 Chat Completions 또는 Responses 요청 본문이나 LiteLLM .prompt 파일을 첫 버전으로 읽어 들입니다(메시지, 모델, 파라미터, 도구, 출력 스키마). 프롬프트의 내보내기는 모든 버전을 담은 JSON 파일 하나를 내려받으며, 같은 방법으로 다시 가져올 수 있습니다. 워크스페이스로 복사는 소속된 다른 워크스페이스로 복사합니다. OpenAI의 저장된 프롬프트는 2026-11-30에 중단되며 꺼내 올 방법도 없습니다. 여기서 기존 pmpt_… ID로 프롬프트를 다시 만들면, 그 ID로 prompt를 보내는 /v1/responses 요청은 코드 변경 없이 라이브러리에서 응답됩니다. version이 숫자면 라이브러리의 해당 버전이, 없으면 production이 사용됩니다.
모델을 호출하지 않고 렌더링하기
POST /v1/prompts/{id}/render는 모델을 호출하지 않고, 호출 시 전송될 요청과 확정된 버전을 돌려줍니다. prompt_variables와, 필요하면 prompt_version 또는 prompt_label, 그리고 format(chat(기본값), responses, messages 중 하나)을 보냅니다. 과금되지 않고 Logs에도 나타나지 않지만, 키의 속도 제한에는 포함됩니다. 특정 버전이 실제로 무엇을 보내는지 확인하거나, prompt_* 필드를 지원하지 않는 엔드포인트를 호출할 때 쓰면 됩니다.
curl https://synthorai.io/v1/prompts/support-reply/render \
-H "Authorization: Bearer $SYNTHORAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"format": "chat",
"prompt_variables": {"product": "Acme Cloud", "customer_message": "My invoice shows two charges."}
}'
{
"prompt_id": "support-reply",
"version": 6,
"format": "chat",
"request": {
"model": "claude-sonnet-5",
"temperature": 0.3,
"messages": [
{"role": "system", "content": "You answer billing mail for Acme Cloud."},
{"role": "user", "content": "My invoice shows two charges."}
]
}
} 응답 헤더
X-Synthorai-Prompt-Version은 어느 버전이 응답했는지 알려 줍니다. 레이블로 호출한 경우 이 헤더 말고는 알 방법이 없습니다. 라이브러리를 읽을 수 없으면 게이트웨이는 마지막으로 읽은 사본으로 최대 24시간 동안 응답하고 X-Synthorai-Prompt-Stale: 1을 붙입니다. 그 사이에 옮긴 레이블은 라이브러리를 다시 읽을 수 있게 된 뒤에 반영됩니다.
오류
이 오류들은 모델을 호출하기 전에 반환되므로 과금되지 않습니다. 오류 형식은 호출한 엔드포인트를 따릅니다.
| 상태 코드 | 코드 | 발생 조건 |
|---|---|---|
| 400 | prompt_variable_missing | 값도 기본값도 없는 변수가 있습니다. 메시지에 변수 이름이 나옵니다. |
| 400 | prompt_invalid | 필드 형식이 잘못되었습니다. 버전과 레이블을 함께 보냈거나, 변수 값이 객체나 배열이거나, 변수가 64개를 넘거나 합계가 64KB를 넘는 경우입니다.렌더링된 프롬프트가 1MB를 넘어도 같은 방식으로 거부됩니다. 보낼 내용이 하나도 남지 않는 호출도 마찬가지입니다. 버전의 메시지가 모두 빈 값으로 렌더링되고 요청에도 메시지가 없는 경우입니다. |
| 404 | prompt_not_found | API 키의 워크스페이스에 이 ID의 프롬프트가 없거나, 해당 버전이 없거나, 레이블이 아직 어떤 버전도 가리키지 않는 경우입니다. |
| 409 | prompt_unreadable | 저장된 버전을 더 이상 읽을 수 없습니다. 새 버전을 저장하세요. |
| 503 | prompt_unavailable | 라이브러리를 일시적으로 읽을 수 없고, 게이트웨이에 이 프롬프트의 최근 사본도 없습니다. 다시 시도하세요. |
버전별 통계
모든 호출에는 사용한 프롬프트와 버전이 기록됩니다. Prompts 페이지에서 최근 7일, 30일 또는 90일 동안의 버전별 호출 수, 오류 수, 지출, 토큰, 지연 시간, 첫 토큰까지의 시간을 볼 수 있고, 호출 수를 누르면 해당 호출이 Logs에서 열립니다. 새 버전을 staging에 두고 production과 나란히 돌려 비교한 뒤 production을 옮기세요.
Logs에서는 prompt = support-reply과 prompt_version = 7로 필터링할 수 있고, 요청 상세에는 사용한 프롬프트와 버전이 표시됩니다. 내보낸 레코드에도 들어 있습니다. 파일과 webhook에서는 run.prompt_id와 run.prompt_version, OTLP 스팬에서는 gen_ai.prompt.name과 gen_ai.prompt.version입니다.
함께 보기: 프롬프트 · Chat Completions · Responses API