챗으로 만들기
아래 글 전체를 복사해 평소 쓰는 챗(ChatGPT·Claude·Gemini 등)에 붙여넣어 보내세요. 아래 칸에 원하는 기능을 적어 두면 복사본 맨 끝(내 요청)에 같이 들어갑니다. 챗이 휩셋 JSON을 돌려주면 그대로 복사해 확장 패널 휩셋 선택 드롭다운의 📥 가져오기에 붙여넣으면 됩니다. 글에 적힌 <<var.key>>는 패널 빌더에선 {{var.key}}로 보입니다. 고칠 곳이 있으면 패널이 목록을 주고, 그 목록을 챗에 다시 붙여넣으면 됩니다.
지금부터 휩휩(WhipWhip)의 휩셋을 설계해서 JSON 객체 하나로 써 주세요. 이 안내를 끝까지 먼저 읽으세요. 맨 끝 "내 요청" 아래에 제가 원하는 것을 적습니다. 꼭 필요한 정보가 빠졌을 때만 짧은 질문 하나를 하고, 그렇지 않으면 바로 JSON으로 답해 주세요.
휩휩이 무엇인가
휩휩은 브라우저 확장입니다. 제가 쓰는 웹챗(ChatGPT·Claude·Gemini·Grok·Perplexity) 위에 패널을 띄우고, 저장해 둔 절차를 그 챗 안에서 대신 실행합니다. 입력창에 글을 쓰고, 보내고, 답을 기다리고, 답을 읽어 일부를 저장하고, 결과를 보여 줍니다.
- 휩셋은 휩을 모은 이름 있는 묶음입니다. 당신이 쓸 것이 이것입니다.
- 휩은 버튼 하나입니다. 누르면 그 휩의 카드를 위에서 아래로 차례대로 실행합니다.
- 카드는 한 단계입니다. 프롬프트 쓰기, 보내기, 답을 변수에 저장하기, 저에게 묻기, 다른 대화로
옮기기, 결과 보여 주기 같은 것입니다. 모든 카드에는
card이름과config설정이 있습니다. - 변수는 이 휩셋의 휩들이 함께 쓰는 이름 있는 값입니다. 값은 실행이 끝나도 남기 때문에, 한 휩이 저장한 것을 다른 휩이 나중에 읽을 수 있습니다.
- 태그는 역할입니다. 특정 대화 하나에 붙이는 이름입니다(예:
author,critic). 휩은 대화에 역할을 붙이고, 나중에 그 대화로 돌아갈 수 있습니다. 서로 다른 두 챗 사이에 일을 넘기는 방법이 이것입니다. 패널은 지금 대화의 역할에 속한 휩만 보여 줍니다 — 태그 없는 대화에서는 메인 목록이 뜹니다.
휩휩은 API를 부르지 않습니다. 모든 일이 실제 챗 페이지에서, 제가 직접 입력한 것과 똑같이 일어납니다. 그래서 휩은 사람이 그 페이지에서 할 수 있는 일을 카드 하나씩 할 수 있을 뿐입니다.
카드가 어떻게 이어지나
챗과 대화하기. prompt_write는 입력창에 글을 넣습니다(보내지는 않습니다). submit은 그 글을
보내고 답이 다 나올 때까지 기다립니다. submit 뒤에는 답을 쓸 수 있습니다.
답 남기기. var_save에 "valueSource": "var.last.assistant"를 주면 가장 최근 답 전체를 변수에
저장합니다. 결과를 남기는 기본 방법입니다. ask_and_extract는 답에서 짧은 이름 붙은 값(제목,
점수, 분류)을 뽑을 때 씁니다 — 프롬프트 끝에 값을 태그로 덧붙이라는 지시를 더하고 그 값을 읽습니다.
긴 답 전체를 담는 데 쓰지 마세요. extract_response는 이 대화의 마지막 답을 별도 탭에서 정해 둔 JSON 모양으로 정리해 옵니다.
드물게만 쓰세요. validate는 최근 답이 형식(JSON, 정규식, 비어 있지 않음)을 지켰는지 보고, 아니면
챗에게 다시 요청합니다.
저에게 묻기. 두 가지입니다.
user_input변수를 프롬프트에 토큰으로 넣습니다. 휩이 실행되기 전에 휩휩이 그 휩에 필요한user_input변수마다 작은 입력 폼을 보여 줍니다. 기본이고 보통 가장 좋습니다.input_prompt는 실행 도중, 그 카드가 있는 자리에서 묻습니다. 그 순간에만 의미가 있는 질문 (예: 답을 읽은 뒤 "이 스크랩 이름은?")이거나,"alwaysAsk": true로 이미 채워진 값을 확인받을 때 씁니다.
choice_prompt는 선택지에서 고르게 합니다. 고정 목록(options에 한 줄에 하나)이나 목록 변수의
항목에서 고를 수 있습니다.
결과 보여 주기. show_result_modal은 변수로 만든 글을 창으로 띄웁니다. 제가 복사할 것 같으면
"copyButton": "copy_body"를 주세요.
대화 옮겨 다니기. new_chat은 같은 서비스에서 새 대화를 엽니다. open_service는 다른 서비스로
갑니다. open_url은 주소를 엽니다. tag_current_chat은 실행이 서 있는 대화에 역할을 붙입니다.
go_to_role은 그 역할을 가진 대화로 실행을 옮기고, "closeCurrent": "true"면 떠나는 탭을 닫습니다.
역할은 어떤 휩이 go_to_role로 가기 전에 먼저 tag_current_chat으로 붙어 있어야 합니다.
역할 대화는 휩이 엽니다. 탭마다 역할을 미리 앉히는 "시작" 휩을 두지 마세요. 역할이 필요한 휩이
그 자리에서 대화를 엽니다: 지금 대화에 역할을 붙이고(tag_current_chat) → new_chat("openMode": "new_tab") →
그 대화에서 할 일을 역할 설명과 함께 한 메시지로 보내고(prompt_write → submit) → 새 대화에 역할을
붙입니다(tag_current_chat).
휩이 어느 목록에 서나. scopeTags가 없는 휩은 메인 목록(태그 없는 대화)에 뜹니다 — 셋의 입구와
대화를 여는 휩이 여기 섭니다. scopeTags: ["critic"]인 휩은 그 역할 대화에서만 뜹니다 — 그 대화의 답을
읽어 무언가 하는 휩이 여기 섭니다.
셋의 모양은 넷 중 하나입니다.
- 한 대화 — 태그 없이 지금 대화에서만 도는 셋(다듬기, 번역).
- 가벼운 휩셋 — 태그 없이, 제가 간직하는 값 하나(문체, 이력서, 화풍)를 두고 도는 휩 3~4개. "…정하기"
휩은 그 값을 늘 묻고(
input_prompt에"alwaysAsk": true), 나머지 휩은 값이 비었을 때만 묻고<<var.key>>로 프롬프트에 싣습니다. 그 값은"scope": "set"변수라 한 번 정하면 어느 대화에서든 씁니다. 아래 글쓰기 도우미 예시가 이 모양입니다. - 곁가지 — 메인은 제가 일하는 대화입니다. 휩이 곁가지 대화를 열어 반론·근거를 받고, 곁가지의 휩이
결과를 들고
go_to_role(closeCurrent)로 메인에 돌아와 탭을 닫습니다. 아래 예시가 이 모양입니다. 메인에 붙이는 태그(예시의author)는 "원고를 쓰는 대화"라는 역할입니다 — 일회용 표시가 아닙니다. 곁가지를 여는 휩은 답을 읽는var_save에"refuseIfEmpty": true를 줘서 빈 대화에선 태그를 붙이기 전에 멈춥니다. - 지휘실 — 메인 대화가 진행을 쥐고, 역할 대화를 필요할 때마다 새로 열어 일을 시킵니다(공부 코치).
목록. "valueType": "array" 변수는 레코드 목록을 담습니다. append_item은 레코드를 더하고
(fields는 이름/값 쌍 목록, autoId는 레코드마다 id를 붙입니다), upsert_item은 id로 더하거나
바꾸고, patch_item은 레코드 하나의 일부 필드를 바꾸고, remove_item은 하나를 지웁니다.
derive_index는 목록을 글로 바꿔(항목마다 한 줄, <<item.field>> 토큰이 든 템플릿으로) 다른 변수에
저장합니다. 그래야 프롬프트나 결과 창이 그 목록을 보여 줄 수 있습니다. 여러 번 실행에 걸쳐 무언가를
기억하는 셋(노트, 라이브러리, 기록)은 목록으로 만듭니다.
변수.
source: "user_input"— 제가 줍니다(실행 전 폼, 또는input_prompt).source: "set_by_action"— 카드가 씁니다:var_save,input_prompt,choice_prompt,ask_and_extract,extract_response,validate(그variable),derive_index, 목록 카드.source: "constant"—defaultValue에 적은 고정 글."scope": "set"— 값이 워크스페이스 하나가 아니라 셋에 속합니다. 이 셋을 쓰는 탭·워크스페이스는 전부 같은 값을 봅니다. 한 번 정해 두고 계속 쓰는 값(문체, 이력서, 화풍)에 쓰세요.user_input과set_by_action에만 붙습니다 —constant에는 못 붙입니다.var_flush로 지워지지 않습니다. 셋을 공유하거나 게시해도 값은 기본으로 안 실리고, 제가 체크해야 실립니다. 작업 하나에 딸린 값에는scope를 빼세요.- 제가 이미 가진 글(완성된 프롬프트 등)은 AI를 거치지 않고
input_prompt로 그대로 받습니다.selectedVars에 칸을 여럿 주면 칸마다 차례로 묻습니다. 빈 칸이면 뒤가 의미 없을 땐"requireAnswer": true를 켜세요. 예: 프롬프트 공장의 «내 프롬프트 4개 보내기»는 칸 넷에 붙여 넣은 프롬프트를 그대로p1~p4("scope": "set")에 담고, 화가 대화로 가서 하나씩 보냅니다. - 키는 영문자·숫자·
_만 씁니다. 라벨은 제가 보는 이름이니 제 언어로 쓰세요. - 카드가 쓰는 변수는 전부
variables에 선언해야 합니다.
토큰
카드 글 안에서 변수는 **<<var.key>>**로 씁니다 — 양쪽에 꺾쇠 두 개씩입니다. 목록 템플릿 안에서는
<<item.field>>입니다. <<now>>는 오늘 날짜입니다.
중괄호로 토큰을 쓰지 마세요. <<…>>는 휩휩이 알아서 바꿉니다.
JSON 모양
{
"format": "whipwhip.authoring/1",
"name": "…", 셋 이름, 제 언어로
"description": "…", 선택, 셋이 하는 일과 쓰는 법
"tags": [ { "name": "writer" } ], 역할. A–Z a–z 0–9 _ - 로 3–10자
"variables": [ { "key": "…", "label": "…", "source": "…", "required": true } ],
"whips": [
{
"label": "…", 버튼 글, 짧게
"description": "…", 선택
"preflightStyle": "form", 선택: "form"(기본) 또는 "none"
"scopeTags": [ "writer" ], 선택: 이 휩이 속한 역할 대화
"actions": [ { "card": "prompt_write", "config": { "text": "…" } } ]
}
]
}
id, usedVars, requiresVars, producesVars, askInline, 키, 서명, 버전은 쓰지 마세요.
휩휩이 채웁니다.
카드 레퍼런스
prompt_write
채팅창에 내용을 입력하거나 수정합니다.
text— 글, 필수, <<var.key>> 토큰 가능mode— 다음 중 하나replace·append·prependpreflight— true 또는 false. 프롬프트의 <<var.key>> 토큰에 대해 실행 전 입력 폼을 표시합니다
submit
작성된 내용을 전송하고, 대기를 끄지 않았다면 AI의 응답을 기다립니다.
skipWait— true 또는 false. 전송 직후 다음 액션으로 넘어갑니다. 휩이 응답을 읽지 않을 때 사용합니다 — 예: 같은 프롬프트를 여러 탭에 뿌리는 경우.
input_prompt
사용자에게 필요한 정보를 입력받습니다.
title— 글selectedVars—[{ "key": …, "question": … }], 필수alwaysAsk— true 또는 false. 변수에 이미 값이 있어도 이 입력창을 띄워, 미리 채워진(또는 AI가 뽑은) 값을 확정 전에 보고 고칠 수 있게 합니다.requireAnswer— true 또는 false. 켜면 비워 둔 채로 확인할 수 없습니다 — 뒤 스텝이 빈 값으로는 의미가 없을 때
ask_and_extract
AI에게 묻고, 답에서 필요한 값을 골라 변수에 담습니다.
text— 글, 필수, <<var.key>> 토큰 가능preflight— true 또는 false. 프롬프트의 <<var.key>> 토큰에 대해 실행 전 입력 폼을 표시합니다varsToExtract—[{ "key": …, "description": … }], 필수
extract_response
이 대화의 마지막 AI 답을 정해 둔 JSON 모양으로 정리해 변수에 담습니다. 임시 탭에서 정리하며, ChatGPT 밖에선 그 대화가 기록에 남습니다.
key— 변수 키, 필수. 가져온 값을 담을 변수입니다.schema— 글, 필수. AI가 돌려줄 JSON의 모양. 예: {"title": "제목", "tags": ["태그"]}promptSuffix— 글. 추출 프롬프트에 추가되는 선택적 텍스트입니다.retries— 숫자. 유효하지 않은 JSON일 때 다시 요청할 횟수입니다.
validate
응답이 형식을 지켰는지 보고 아니면 다시 요구합니다. 형식만 봅니다 — 내용이 맞는지는 판정할 수 없습니다.
source— 다음 중 하나last_assistant·var. 직전 응답 또는 저장된 변수. 변수는 검사만 합니다 — 다시 물어도 과거 값은 안 바뀝니다.key— 변수 키, 쓰이는 조건:source=varrule— 다음 중 하나json·regex·non_empty·whipset, 필수. JSON: JSON으로 읽을 수 있는지(꼭 있어야 할 키 지정 가능). 패턴 일치: 정한 패턴과 맞는지. 비어있지 않음: 빈 답이 아닌지. 휩셋: 챗이 쓴 휩휩 휩셋 JSON인지 — 틀리면 고칠 곳 목록을 실어 다시 요구합니다.pattern— 글, 쓰이는 조건:rule=regexrequiredKeys— 글, 쓰이는 조건:rule=json. 쉼표로 구분한 최상위 키 목록.retries— 숫자. 실패로 끝내기 전 교정 프롬프트를 보낼 횟수. 0 = 검사만.correction— 글, <<var.key>> 토큰 가능. 형식이 안 맞을 때 보냅니다. 비우면 기본 문구를 씁니다.variable— 변수 키
send_to_services
같은 글을 고른 AI들에 보냅니다(나머지는 뒤쪽 새 탭). 답은 기다려 모으거나, 태그만 붙이거나, 태그된 대화에서 읽습니다.
servicesVar— 변수 키, 필수. AI 서비스 id의 JSON 배열이 담긴 변수. 보통 "AI 서비스" 소스 + 여러 개 선택으로 채웁니다.text— 글, 필수, <<var.key>> 토큰 가능. 모든 AI에 똑같이 보낼 글. 변수 토큰을 쓸 수 있습니다.tagPrefix— 글. 주면 AI마다 "이름_약자" 태그(약자 gpt·gem·cla·grk·ppx)를 대화에 붙여 다음에 이어서 물을 수 있게 합니다. 이름은 영문 6자·한글 3자까지.key— 변수 키, 필수. AI마다 제목과 답(또는 실패 사유)이 적힌 글이 저장됩니다. 보내고 태그만이면 보내지 못한 AI의 사유만 담깁니다.mode— 다음 중 하나collect·send·read. 답을 기다려 모으기 = 모든 답을 기다려 한 변수에 · 보내고 태그만 = 보내고 끝(답은 각 탭에서) · 무리 대화에서 읽기 = 보내지 않고 태그된 대화들의 마지막 답을 읽음
var_save
입력창 글, AI 답 같은 내용을 변수에 담아 둡니다.
valueSource— 아래 값 출처 중 하나, 또는var.<변수 키>, 필수. 값을 읽어올 위치를 선택합니다.key— 변수 키, 필수. 가져온 값을 담을 변수입니다.valueFilter— 다음 중 하나""·code, 다음 값에 따라 쓰임valueSourcerefuseIfEmpty— true 또는 false, 다음 값에 따라 쓰임valueSource. 읽은 내용이 비어 있으면 빈 값으로 이어가지 않고 이유를 말하며 멈춥니다.
var_flush
이 휩셋의 모든 변수 값을 비웁니다(변수 목록은 그대로). 모아 둔 목록도 비워지니 주의하세요.
설정 없음 — "config": {}.
append_item
목록 변수에 항목을 하나 더합니다 (예: 모은 메모 목록에 새 메모).
key— 변수 키, 필수. 바꿀 목록 변수. 변수 편집에서 값 타입이 "목록"이어야 합니다.fields—[{ "name": …, "value": … }], 필수, <<var.key>> 토큰 가능. 추가할 레코드의 필드(이름 → 값). 값에 <<var.x>> 토큰 사용 가능, 따옴표·개행은 자동 처리됩니다.autoId— true 또는 false. id를 직접 넣지 않으면 새 항목마다 안정적으로 증가하는 id를 붙입니다.idPrefix— 글, 쓰이는 조건:autoId=true. 숫자 앞에 붙습니다. 예: "memo-" → memo-1, memo-2 …
upsert_item
"id" 필드로 매칭해 배열 변수의 항목을 삽입하거나 갱신합니다.
key— 변수 키, 필수. 바꿀 목록 변수. 변수 편집에서 값 타입이 "목록"이어야 합니다.fields—[{ "name": …, "value": … }], 필수, <<var.key>> 토큰 가능. 삽입/갱신할 레코드의 필드. "id" 필드를 포함하세요 — 교체할 기존 항목을 매칭합니다.
patch_item
id로 매칭한 항목의 지정 필드만 수정하고 나머지 필드는 유지합니다 (예: 상태만 전환).
key— 변수 키, 필수. 바꿀 목록 변수. 변수 편집에서 값 타입이 "목록"이어야 합니다.itemId— 글, 필수, <<var.key>> 토큰 가능. 부분수정할 항목의 "id". <<var.x>> 토큰을 지원합니다.fields—[{ "name": …, "value": … }], 필수, <<var.key>> 토큰 가능. 이 필드들만 수정되고 항목의 나머지 필드는 유지됩니다. 값에 <<var.x>> 토큰 사용 가능.
remove_item
"id"로 배열 변수의 항목을 제거합니다.
key— 변수 키, 필수. 바꿀 목록 변수. 변수 편집에서 값 타입이 "목록"이어야 합니다.itemId— 글, 필수, <<var.key>> 토큰 가능. 제거할 항목의 "id". <<var.x>> 토큰을 지원합니다.
derive_index
배열 변수에서 항목당 한 줄씩 요약/인덱스 문자열을 만듭니다.
sourceKey— 변수 키, 필수. 요약할 배열 변수.key— 변수 키, 필수. 만들어진 요약 목록을 받을 변수.mode— 다음 중 하나join·count. 인덱스 문자열(기본), 또는 필터 후 남은 항목 수만.itemTemplate— 글, 쓰일 때 필수, <<item.field>> 토큰 가능, 다음 값에 따라 쓰임mode. 항목마다 이 모양으로 한 줄씩 만들어 줄바꿈으로 잇습니다. <<item.field>> 토큰 사용, 예: <<item.id>> — <<item.title>>.filterField— 글. 이 필드가 아래 값과 맞는 항목만 포함. 비우면 전체 포함.filterOp— 다음 중 하나eq·ne, 다음 값에 따라 쓰임filterField. 필드가 없는 항목은 어느 쪽이든 빈 값으로 칩니다.filterValue— 글, <<var.key>> 토큰 가능, 다음 값에 따라 쓰임filterField. 필터 필드와 비교할 값. <<var.x>> 토큰 지원.sortField— 글. 이 필드로 정렬한 뒤 만듭니다. 숫자를 알아보므로 memo-2가 memo-10보다 앞섭니다. 비우면 넣은 순서 그대로.sortDir— 다음 중 하나asc·desc, 다음 값에 따라 쓰임sortFieldlimit— 숫자. 최대 이 개수만 유지. 비우면 전체.limitFrom— 다음 중 하나end·start, 다음 값에 따라 쓰임limit
go_to_role
태그가 붙은 대화로 이동합니다.
tagName— 태그 이름tagCandidates— 태그 이름 목록. 이 단계가 갈 수 있는 태그를 고르세요. 비우면 위에서 고른 태그로만 갑니다. 고른 태그가 모두 대화에 붙어 있어야 실행됩니다.tagVar— 변수 키. 고른 태그 이름이 담긴 변수(예: 선택 단계가 채움). 후보를 고른 경우에만 쓰입니다.closeCurrent— 다음 중 하나false·true
go_to_start
휩을 누른 탭으로 돌아옵니다. 지금 탭을 닫을 수도 있어요 — 곁가지에서 묻고 돌아올 때 씁니다.
closeCurrent— 다음 중 하나true·false
new_chat
현재 서비스에서 새 대화를 엽니다.
isTemp— 다음 중 하나false·trueopenMode— 다음 중 하나current·new_tab·background
open_service
다른 AI 서비스로 전환합니다 (ChatGPT, Gemini, Claude…).
service— 다음 중 하나chatgpt·gemini·claude·grok·perplexity, 필수openMode— 다음 중 하나current·new_tab·background
open_url
https:// 주소로 이동합니다.
target— 글, 필수openMode— 다음 중 하나current·new_tab·background
tag_current_chat
현재 대화에 태그를 붙여 관리합니다.
tagName— 태그 이름, 필수runOnly— true 또는 false. 실행이 끝나면 태그를 뗍니다 — 대화는 워크스페이스 목록에 남습니다
choice_prompt
사용자에게 옵션 목록을 보여주고, 고른 값을 변수에 담습니다.
label— 글, <<var.key>> 토큰 가능optionsSource— 다음 중 하나static·variable·services. 선택지를 가져올 위치를 지정합니다. "AI 서비스"는 ChatGPT·Claude·Gemini·Grok·Perplexity를 채웁니다.options— 글, 쓰일 때 필수, 다음 값에 따라 쓰임optionsSource. 각 줄이 버튼이 됩니다. 선택한 줄이 변수에 저장됩니다.dynamicOptionsVar— 변수 키, 쓰일 때 필수, 쓰이는 조건:optionsSource=variable. 선택지가 담긴 변수 (한 줄에 하나). 실행할 때 읽습니다.optionLabel— 글, <<item.field>> 토큰 가능, 쓰이는 조건:optionsSource=variable. 선택지마다 보일 글의 모양. <<item.field>> 토큰 사용, 예: <<item.id>> — <<item.title>>.optionValueField— 글, 쓰이는 조건:optionsSource=variable. 선택된 값으로 쓸 항목 필드(기본 "id"). 뒤의 항목 수정/삭제에 항목 id로 넘깁니다.filterField— 글, 쓰이는 조건:optionsSource=variable. 이 필드가 아래 값과 맞는 항목만 선택지로 띄웁니다. 비우면 전체. 배열 변수에만 걸립니다.filterOp— 다음 중 하나eq·ne, 다음 값에 따라 쓰임filterField. 필드가 없는 항목은 어느 쪽이든 빈 값으로 칩니다.filterValue— 글, <<var.key>> 토큰 가능, 다음 값에 따라 쓰임filterField. 필터 필드와 비교할 값. <<var.x>> 토큰 지원.multiple— true 또는 false. 체크리스트로 띄우고 확인을 누르면 체크한 값들을 JSON 배열로 저장합니다.lockCurrentService— true 또는 false, 쓰이는 조건:optionsSource=services,multiple=true. 여러 개 선택일 때, 휩을 실행한 탭의 AI를 "지금 탭"으로 표시하고 체크한 채 잠급니다.warnInConversation— true 또는 false, 쓰이는 조건:optionsSource=services,multiple=true. 여러 개 선택일 때, 실행한 탭이 이미 대화 중이면 그 AI만 앞 맥락을 안고 답한다고 체크리스트 위에 알립니다.continueGroup— 글, 쓰이는 조건:optionsSource=services,multiple=true. 여러 개 선택일 때, 실행한 탭이 "이름_약자" 태그 무리에 속하면 맨 위에 "이어서 묻기" 행을 기본으로 켜고 그 AI들을 미리 체크합니다. "여러 AI에 보내기"의 태그 이름과 같게 둡니다.rememberAs— 글, 쓰이는 조건:multiple=true. 이름을 주면 이번 선택을 기억해 다음 실행에서 미리 체크합니다. 어느 탭·워크스페이스에서 실행해도 같은 기억을 씁니다.key— 변수 키, 필수. 선택한 항목이 저장될 변수 키입니다.
show_result_modal
변수에 저장된 값을 활용해 결과창을 띄웁니다.
title— 글, <<var.key>> 토큰 가능body— 글, 필수, <<var.key>> 토큰 가능copyButton— 다음 중 하나none·copy_body
import_whipset
변수에 든, 챗이 쓴 휩셋 JSON을 가져옵니다. 저장 전에 미리보기로 확인받습니다.
key— 변수 키, 필수. 보통 앞의 "형식 검증" 카드(휩셋 규칙)가 저장한 변수입니다.
값 출처(var_save.valueSource)
builtin.date_today · builtin.date_iso · builtin.time_now · builtin.timestamp · builtin.day_of_week · builtin.page_url · builtin.page_title · builtin.page_domain · builtin.language · builtin.random_uuid · builtin.selection · composer · var.last.user · var.last.assistant
흔한 실수
<<var.x>>대신 중괄호로 토큰 쓰기.- 아무 카드도 쓰지 않는
set_by_action변수, 또는 글에는 쓰면서 선언하지 않은 변수. submit없이 답 읽기(var_save의var.last.assistant).- 실제로 보내야 하는데
prompt_write뒤에submit을 빠뜨리기. "valueType": "array"가 아닌 변수에 목록 카드 쓰기.- 어떤 휩도
tag_current_chat으로 붙이지 않는 역할로go_to_role하기, 또는tags에 선언하지 않은 태그. - 10자를 넘거나, 공백이 있거나,
main인 태그 이름. - 카드에 없는 필드를 쓰거나 카드 이름을 지어내기.
- 긴 답 전체를
ask_and_extract로 담기 —var_save의var.last.assistant를 쓰세요. - 모든 걸 하는 거대한 휩 하나. 버튼이 분명한 휩 몇 개가 낫습니다.
예시
대화 하나: 초안을 다듬어 보여 주기
{
"format": "whipwhip.authoring/1",
"name": "초안 다듬기",
"description": "거친 초안을 또렷하게 고쳐 쓰고 결과를 보여 줍니다.",
"tags": [],
"variables": [
{ "key": "draft", "label": "초안", "source": "user_input", "required": true },
{ "key": "polished", "label": "다듬은 글", "source": "set_by_action", "required": false }
],
"whips": [
{
"label": "다듬기",
"actions": [
{ "card": "prompt_write", "config": { "text": "아래 초안을 또렷하고 간결하게 고쳐 써 줘. 내 뜻과 말투는 지켜 줘. 고친 글만 답해.\n\n<<var.draft>>", "mode": "replace" } },
{ "card": "submit", "config": {} },
{ "card": "var_save", "config": { "valueSource": "var.last.assistant", "key": "polished" } },
{ "card": "show_result_modal", "config": { "title": "다듬은 글", "body": "<<var.polished>>", "copyButton": "copy_body" } }
]
}
]
}
역할 둘: 내 대화의 답을 곁가지에서 검토받기
{
"format": "whipwhip.authoring/1",
"name": "검토받고 고치기",
"description": "쓰던 대화에서 '이 답 검토받기'를 누르면 새 탭에서 검토자가 답합니다. 검토 대화에서 '검토 반영'을 누르면 원래 대화로 돌아와 고칩니다.",
"tags": [ { "name": "author" }, { "name": "reviewer" } ],
"variables": [
{ "key": "draft", "label": "원고", "source": "set_by_action", "required": false },
{ "key": "review", "label": "검토", "source": "set_by_action", "required": false }
],
"whips": [
{
"label": "이 답 검토받기",
"actions": [
{ "card": "var_save", "config": { "valueSource": "var.last.assistant", "key": "draft", "refuseIfEmpty": true } },
{ "card": "tag_current_chat", "config": { "tagName": "author" } },
{ "card": "new_chat", "config": { "isTemp": "false", "openMode": "new_tab" } },
{ "card": "prompt_write", "config": { "text": "이 대화에서 너는 까다로운 검토자야. 아래 원고의 약한 지점을 가장 약한 것부터 한 줄에 하나씩 짚어 줘. 고쳐 쓰지는 마.\n\n[원고]\n<<var.draft>>", "mode": "replace" } },
{ "card": "submit", "config": {} },
{ "card": "tag_current_chat", "config": { "tagName": "reviewer" } }
]
},
{
"label": "검토 반영",
"scopeTags": [ "reviewer" ],
"actions": [
{ "card": "var_save", "config": { "valueSource": "var.last.assistant", "key": "review" } },
{ "card": "input_prompt", "config": { "title": "검토", "selectedVars": [ { "key": "review", "question": "이 검토로 고칠까요? 뺄 줄은 먼저 지우세요." } ], "alwaysAsk": true } },
{ "card": "go_to_role", "config": { "tagName": "author", "closeCurrent": "true" } },
{ "card": "prompt_write", "config": { "text": "이 검토를 반영해 방금 답을 고쳐 줘. 고친 전문만 답해.\n\n<<var.review>>", "mode": "replace" } },
{ "card": "submit", "config": {} }
]
}
]
}
쌓이는 목록: 답 스크랩 노트
{
"format": "whipwhip.authoring/1",
"name": "답 스크랩 노트",
"tags": [],
"variables": [
{ "key": "clip", "label": "스크랩한 답", "source": "set_by_action", "required": false },
{ "key": "clip_title", "label": "제목", "source": "set_by_action", "required": false },
{ "key": "notes", "label": "노트", "source": "set_by_action", "valueType": "array", "required": false },
{ "key": "notes_index", "label": "노트 목록", "source": "set_by_action", "required": false },
{ "key": "notes_full", "label": "노트 전문", "source": "set_by_action", "required": false },
{ "key": "summary", "label": "요약", "source": "set_by_action", "required": false }
],
"whips": [
{
"label": "이 답 저장",
"actions": [
{ "card": "var_save", "config": { "valueSource": "var.last.assistant", "key": "clip" } },
{ "card": "input_prompt", "config": { "title": "이 답 저장", "selectedVars": [ { "key": "clip_title", "question": "짧은 제목을 붙여 주세요" } ], "inputStyle": "inline", "alwaysAsk": true } },
{ "card": "append_item", "config": { "key": "notes", "autoId": true, "idPrefix": "note-", "fields": [ { "name": "title", "value": "<<var.clip_title>>" }, { "name": "text", "value": "<<var.clip>>" }, { "name": "date", "value": "<<now>>" } ] } },
{ "card": "derive_index", "config": { "sourceKey": "notes", "key": "notes_index", "itemTemplate": "<<item.id>> — <<item.title>> (<<item.date>>)" } },
{ "card": "show_result_modal", "config": { "title": "노트", "body": "<<var.notes_index>>" } }
]
},
{
"label": "노트 요약",
"actions": [
{ "card": "derive_index", "config": { "sourceKey": "notes", "key": "notes_full", "itemTemplate": "### <<item.title>>\n<<item.text>>" } },
{ "card": "new_chat", "config": { "openMode": "current" } },
{ "card": "prompt_write", "config": { "text": "이 노트들에 공통으로 흐르는 것과 합치면 무엇이 되는지 정리해 줘.\n\n<<var.notes_full>>", "mode": "replace" } },
{ "card": "submit", "config": {} },
{ "card": "var_save", "config": { "valueSource": "var.last.assistant", "key": "summary" } },
{ "card": "show_result_modal", "config": { "title": "요약", "body": "<<var.summary>>", "copyButton": "copy_body" } }
]
}
]
}
가벼운 휩셋: 어느 대화에서든 같은 문체
{
"format": "whipwhip.authoring/1",
"name": "글쓰기 도우미",
"description": "문체를 한 번 정해 두면, 어느 대화에서든 버튼 하나로 다듬고 길이를 바꿉니다.",
"tags": [],
"variables": [
{ "key": "style", "label": "문체", "source": "user_input", "required": false, "scope": "set" },
{ "key": "length", "label": "길이", "source": "set_by_action", "required": false }
],
"whips": [
{
"label": "문체 정하기",
"preflightStyle": "none",
"actions": [
{ "card": "input_prompt", "config": { "title": "문체", "selectedVars": [ { "key": "style", "question": "어떤 문체로 쓸까요? (예: 담백한 존댓말, 짧은 문장)" } ], "inputStyle": "inline", "alwaysAsk": true } },
{ "card": "prompt_write", "config": { "text": "이 대화에서 앞으로 쓰는 글은 이 문체로 써줘: <<var.style>>\n알겠으면 «확인»이라고만 답해줘.", "mode": "replace" } },
{ "card": "submit", "config": {} }
]
},
{
"label": "다듬기",
"preflightStyle": "none",
"actions": [
{ "card": "input_prompt", "config": { "title": "문체", "selectedVars": [ { "key": "style", "question": "어떤 문체로 쓸까요? (예: 담백한 존댓말, 짧은 문장)" } ], "inputStyle": "inline" } },
{ "card": "prompt_write", "config": { "text": "방금 쓴 글을 다듬어줘. 뜻과 내용은 그대로 두고 어색한 문장·맞춤법·반복만 고쳐. 문체: <<var.style>>\n다듬은 글만 보여줘.", "mode": "replace" } },
{ "card": "submit", "config": {} }
]
},
{
"label": "길이 조정",
"preflightStyle": "none",
"actions": [
{ "card": "input_prompt", "config": { "title": "문체", "selectedVars": [ { "key": "style", "question": "어떤 문체로 쓸까요? (예: 담백한 존댓말, 짧은 문장)" } ], "inputStyle": "inline" } },
{ "card": "choice_prompt", "config": { "label": "어느 쪽으로 바꿀까요?", "optionsSource": "static", "options": "더 짧게\n더 길게", "key": "length" } },
{ "card": "prompt_write", "config": { "text": "방금 쓴 글을 <<var.length>> 고쳐줘. 핵심 내용은 지키고, 문체: <<var.style>>\n고친 글만 보여줘.", "mode": "replace" } },
{ "card": "submit", "config": {} }
]
}
]
}
출력 규칙
- 제가 어떤 휩을 어떤 순서로 누를지 먼저 생각하고, 동작하는 가장 작은 셋을 설계하세요.
- 이름·라벨·질문·프롬프트·결과 제목은 제가 요청을 쓴 언어로 쓰세요. 카드 이름, 필드 이름, 변수 키, 태그 이름은 이 안내에 적힌 그대로 둡니다.
- 휩셋 전체를 담은 JSON 코드블록 하나로 답하세요. 블록 뒤에 어떤 버튼부터 누르면 되는지 짧은 문장 두 개까지만 덧붙여도 됩니다.
- 제가 휩휩이 알려 준 고칠 곳 목록을 붙여넣으면, 전부 고쳐서 완전한 JSON을 다시 보내 주세요. 고친 부분만 보내지 마세요.