| name | bk-start |
| description | BlueKiwi workflow execution skill. Selects a registered workflow and starts the first step immediately. This skill should be used when the user says "/bk-start", "/bk-run", "start workflow", "run workflow", "execute workflow", "run BlueKiwi", or wants to begin a registered instruction workflow. |
| user_invocable | true |
Asking questions across runtimes: wherever this skill says
AskUserQuestion, use your host runtime's native structured-question
tool: AskUserQuestion (Claude Code), clarify (Hermes Agent),
requestUserInput (Codex CLI), question (opencode). Always present
the choices through that tool rather than plain prose. If the runtime
has no such tool, list the options as numbered text and wait for the
user's reply before proceeding.
BlueKiwi Workflow Start
Select a registered workflow, create a task, and immediately execute the first step.
Argument Handling
Parse the argument string with this precedence (first match wins):
| Pattern | Meaning | Action |
|---|
| (none) | No argument | Fetch workflow list, ask user to select via AskUserQuestion. Also run Session Restore first. |
#<taskID> (starts with #, rest numeric) | Resume a specific task | Skip workflow selection, jump straight to advance(task_id=N, peek=true) and continue that task |
<digits> only | Workflow numeric ID | Skip the list UI, call start_workflow(workflow_id=N) directly |
<name> :: <prompt> | Workflow name/ID + initial context | Match workflow by name or ID, pass everything after :: as context |
<name> | Workflow name match | Fuzzy-match the workflow list, propose the best match as Recommended |
The :: separator can combine with #<taskID> or <ID> forms too (e.g. /bk-start 42 :: review PR #77).
Core Principles
- Instructions are internal agent directives. Never expose raw instruction text to the user.
- Never use system terms like "node", "node_type", "chain_nodes" with the user.
- Refer to steps as "step" only.
- All
output written to the server must be in past-tense declarative form ("I analyzed...", "I generated...").
AskUserQuestion Parameter Rules
options must have 2โ4 entries.
preview is a plain string. Use \n for line breaks.
header must be 12 characters or fewer.
multiSelect must be false.
Session Restore (Resume In-Progress or Timed-Out Task)
Follow all steps in order before proceeding to workflow selection.
Step A โ Mark zombie tasks
Call the sweep_stale_tasks MCP tool (defaults to timeout_minutes=120). This converts any running tasks idle for over 2 hours to timed_out so they can be surfaced for resume/cleanup in Step B.
Step B โ Fetch existing tasks
Call list_tasks with status=running and again with status=timed_out.
Collect all results into a combined candidate list sorted by updated_at descending (most recent first).
If the list is empty โ skip to workflow selection.
Step C โ Build the task summary
For each candidate, compute age from updated_at to now.
Format: "Task #{id} โ {workflow_name} (Step {current_step}/{total_steps}, {age}์ )"
Example output:
๋ฏธ์๋ฃ ํ์คํฌ 2๊ฑด์ด ์์ต๋๋ค:
โ Task #31 โ ์ฝ๋ ๋ฆฌ๋ทฐ ์ํฌํ๋ก (Step 3/6, 3์๊ฐ ์ ) [timed_out]
โก Task #28 โ ๋ณด์ ์ ๊ฒ (Step 1/4, 30๋ถ ์ ) [running]
Step D โ Ask what to do
Case 1: exactly 1 candidate
Ask via AskUserQuestion:
- header: "๋ฏธ์๋ฃ ํ์คํฌ"
- preview:
"Task #{id} โ {workflow_name}\nStep {N}/{total} ยท {age}์ ์ค๋จ"
- options (pick the most appropriate 3โ4):
"์ด์ด์ ์งํ" โ resume this task
"์ข
๋ฃํ๊ณ ์๋ก ์์" โ close this task then start fresh
"๋ซ์ง ์๊ณ ์๋ก ์์" โ leave as-is, open a new task
- (only if status=running)
"๊ณ์ ์คํ ์ค" โ another agent is handling it, do nothing
Case 2: 2 or more candidates
Ask via AskUserQuestion:
- header: "๋ฏธ์๋ฃ ํ์คํฌ"
- preview: the task summary list built above
- options:
"๊ฐ์ฅ ์ต๊ทผ ํ์คํฌ ์ด์ด์" โ resume the most recent one
"๋ชจ๋ ์ข
๋ฃํ๊ณ ์๋ก ์์" โ close all candidates, then start fresh
"์ ํ์คํฌ ์์ (๊ธฐ์กด ์ ์ง)" โ leave existing as-is, open a new task
Step E โ Execute the choice
"์ด์ด์ ์งํ" / "๊ฐ์ฅ ์ต๊ทผ ํ์คํฌ ์ด์ด์":
Call advance(task_id, peek=true), read task_context, then continue with the auto-advance loop.
"์ข
๋ฃํ๊ณ ์๋ก ์์" / "๋ชจ๋ ์ข
๋ฃํ๊ณ ์๋ก ์์":
For each task to close, call complete_task(task_id, summary="์ฌ์ฉ์ ์์ฒญ์ผ๋ก ์ข
๋ฃ๋จ").
Confirm: "๊ธฐ์กด ํ์คํฌ๋ฅผ ์ข
๋ฃํ์ต๋๋ค. ์ ์ํฌํ๋ก๋ฅผ ์ ํํ์ธ์." โ proceed to workflow selection.
"๋ซ์ง ์๊ณ ์๋ก ์์" / "์ ํ์คํฌ ์์ (๊ธฐ์กด ์ ์ง)":
Proceed to workflow selection without touching existing tasks.
execute_step Parameters
When calling execute_step:
Always provide:
context_snapshot (object): decisions made, key findings, next-step hints. The only reliable way to carry state across steps.
model_id (string): current LLM model (e.g. claude-opus-4-6). Read from your system prompt.
Provide when known:
user_name (string)
session_id, agent_id (strings): optional identifiers, server stores them for audit.
Do NOT send manually: provider_slug โ the MCP server injects it from the connection handshake.
Record file/commit outputs in the artifacts array on the same call:
- File created:
{artifact_type: "file", title: "Design Doc", file_path: "docs/specs/design.md"}
- Git commit:
{artifact_type: "git_commit", title: "Implementation", git_ref: "<hash>"}
- URL:
{artifact_type: "url", title: "PR", url: "https://..."}
Session Metadata
When calling start_workflow, pass a session_meta JSON string carrying project context the server can't otherwise see. The MCP server auto-fills provider_slug from the client handshake, so you only need to supply what the agent knows:
{
"project_dir": "/Users/dante/workspace/project",
"user_name": "dante",
"model_id": "claude-opus-4-6",
"git_remote": "git@github.com:user/repo.git",
"git_branch": "main",
"os": "Darwin arm64",
"started_at": "<current UTC ISO timestamp>"
}
Collect git_remote / git_branch / os via short shell calls (git remote get-url origin, git branch --show-current, uname -s -m). model_id comes from your system prompt; user_name from whoami if unknown; started_at is the current UTC time. Do not walk the process tree to guess the agent name โ the MCP handshake tells the server which client is connected.
Credential Handling (API Service Nodes)
If the advance response includes a credentials field, the node requires external API integration.
Use key-value pairs from `credentials.secrets` to make API calls.
Example: `credentials.secrets.ACCESS_TOKEN` โ `curl -H "Authorization: Bearer $TOKEN"`
Never include raw secret values (tokens, keys) in `execute_step` output.
Record only results (URL, status code, response summary).
Execution Steps
1. Fetch and Select Workflow
Call list_workflows to retrieve the list.
No workflows exist: Ask via AskUserQuestion:
- header: "No workflows"
- "No workflows found. Would you like to create one now?"
- options: "Create new workflow" / "Cancel"
If "Create new workflow" โ immediately invoke the bk-create skill. Pass the user's original argument (if any) as the goal so bk-create can pre-fill the design step. After bk-create completes and the workflow is registered, return here and proceed with Step 2 using the newly created workflow.
Single workflow: Skip the selection UI, just confirm:
- "Start the '{title}' workflow?" (AskUserQuestion: "Start" / "Cancel")
Multiple workflows: Show selection via AskUserQuestion.
If the user selects "Create new workflow" from the selection UI โ invoke bk-create, then continue as above.
2. Create Task + Open Monitoring Page
Call start_workflow. Pass any argument as context.
Derive a short title (โค60 chars) from the user's goal and pass it alongside context. If the argument is already short, use it; otherwise distill it to a noun phrase (e.g. "Hermes AI ์ํฐํด ์์ฑ", not the full paragraph). The raw prompt becomes context; only the short label goes into title.
After start_workflow returns the task_id, open the monitoring page in the user's browser. Use the cross-platform opener below (WEBUI_URL is the webui_url field in the response). Opener failure is cosmetic โ the task is already running, so never retry start_workflow because the browser failed to open.
bk_open() {
local url="$1"
if grep -qi microsoft /proc/version 2>/dev/null; then
command -v wslview >/dev/null 2>&1 && { wslview "$url" 2>/dev/null; return; }
powershell.exe -NoProfile Start "$url" 2>/dev/null && return
cmd.exe /c start "" "$url" 2>/dev/null; return
fi
case "$(uname -s)" in
Darwin) open "$url" 2>/dev/null || true ;;
Linux) [ -n "${DISPLAY}${WAYLAND_DISPLAY}" ] && command -v xdg-open >/dev/null 2>&1 && xdg-open "$url" 2>/dev/null || true ;;
MINGW*|MSYS*|CYGWIN*) start "" "$url" 2>/dev/null || true ;;
esac
}
bk_open "${WEBUI_URL}/tasks/${TASK_ID}"
3. Execute First Step + Auto-Advance Loop
Read the first step's instruction as an internal directive and execute immediately.
After execution, save with execute_step, then check the response for next_action before calling advance.
Show roadmap at start (#20):
Starting: {workflow title} ({n} steps)
โโโโโโโโโโโโโโโโโโโโโโโโโ
**1** โ 2 โ 3 โ 4 โ 5 โ 6 โ 7
โโโโโโโโโโโโโโโโโโโโโโโโโ
๐บ Live: ${WEBUI_URL}/tasks/${TASK_ID}
โโโโโโโโโโโโโโโโโโโโโโโโโ
Auto-advance loop: if execute_step returns no next_action, proceed to the next step automatically. Show a brief inline update (โ
[{title}] done โ continuing to next stepโฆ). Repeat until a gate step or hitl=true action step is reached โ do not pause to ask the user to type /bk-next.
4. When Pausing
Check the next_action field in the execute_step response and handle accordingly:
HITL (next_action: "wait_for_human_approval")
Call request_approval, then immediately show the HITL approval AskUserQuestion (inline HITL approval). Do NOT stop and tell the user to type /bk-approve.
Gate step (no next_action, node_type=gate)
Write VS content text (titles, descriptions, option labels) in the user's language. The frame UI (Submit button, status) is auto-localized; only agent-authored content needs matching locale.
-
If visual_selection: true:
-
Compose a VS content fragment (inner HTML only โ no <html>/<head>/<body>, the frame is injected automatically). Component classes: bk-options, bk-cards, bk-checklist, bk-code-compare (selection); bk-slider, bk-input, bk-textarea, bk-ranking, bk-matrix (input); bk-split, bk-pros-cons, bk-mockup, bk-timeline (display).
Required attributes (server validates these):
- Selection items (
.bk-option, .bk-card, .bk-check-item, .bk-code-option): data-value="<id>" on each item. Optional data-recommended on the suggested choice.
- Input components:
data-name="<id>" for keying the response. bk-slider also needs data-min, data-max, data-value, optional data-unit. bk-input/bk-textarea accept data-label, data-placeholder, optional data-required and data-response-key="comment" (stores into top-level comment).
- Per-item memo: add
data-requires-comment to force a memo before submit. Optional data-comment-name="<key>" stores it into response.fields[<key>].
- Optional first line:
<!-- @bk size=sm|md|lg|xl|full --> (default sm).
Full catalog with template patterns and per-component examples: see bk-create ยง VS Component Selection Guide.
Minimal example:
<h2>Choose an approach</h2>
<div class="bk-options">
<div class="bk-option" data-value="monolith" data-recommended>
<div class="bk-option-letter">A</div>
<div class="bk-option-body">
<h3>Monolith</h3>
<p>Simple deployment</p>
</div>
</div>
<div class="bk-option" data-value="microservices">
<div class="bk-option-letter">B</div>
<div class="bk-option-body">
<h3>Microservices</h3>
<p>Independent scaling</p>
</div>
</div>
</div>
-
Call set_visual_html(task_id, node_id, html) with the fragment.
-
Open the VS deep link so the user sees the selection UI immediately (reuse the bk_open helper from ยง2 โ cross-platform, failure ignorable):
bk_open "${WEBUI_URL}/tasks/${TASK_ID}?step=${STEP_ORDER}&vs=true"
-
Poll get_web_response(task_id) every 3-5 seconds until a response arrives (max 120 seconds).
-
The response is a JSON object (not a plain string). Parse it to read the user's choices and feedback:
{
"selections": ["monolith"],
"values": { "budget": 70 },
"ranking": ["security", "ux"],
"comment": "Keep this direction but tighten rollout scope",
"fields": { "change_request": "Add a rollback plan" },
"option_comments": {
"monolith": "Prefer this if we can phase deployment"
}
}
selections: chosen option values (from bk-options, bk-cards, bk-checklist, bk-code-compare)
values: numeric inputs (from bk-slider, keyed by data-name)
ranking: ordered list (from bk-ranking)
matrix: placement coordinates (from bk-matrix)
comment: free-form global memo from bk-textarea/bk-input with data-response-key="comment" (or data-name="comment")
fields: named text inputs from bk-input / bk-textarea, plus any option-level memo stored via data-comment-name
option_comments: per-option free-text notes attached to selected choices
Only populated fields appear.
-
When forming the gate answer, never ignore free-text feedback:
- If
comment exists, summarize it in the gate output.
- If
fields.change_request or similar named fields exist, treat them as authoritative revision instructions.
- If
option_comments exists, preserve the mapping between the selected option and its note.
- A response like "select B + add changes" must not be collapsed into just
"selections": ["b"].
-
Use the parsed response to form the gate answer and call advance.
-
If visual_selection: false โ present the gate question to the user via AskUserQuestion. Use the response as gate answer, call execute_step with the answer, then advance.
Attachments
When `advance` returns `node.attachments`:
1. Review the list (filename, mime_type, size_bytes)
2. Call `get_attachment(workflow_id, node_id, attachment_id)` for each text file the instruction references
3. Use downloaded content as context when executing the instruction
4. For binary files, note their existence but do not download unless explicitly required
Loop (next_action: "loop_back")
Loop nodes repeat until a termination condition is met. The instruction contains the termination condition.
Execution flow:
- Read the instruction and execute one iteration (e.g., ask one clarifying question).
- Present the result/question to the user via AskUserQuestion.
- Based on user response, decide: is the termination condition met?
- NOT met โ call
execute_step(loop_continue=true) โ server creates a new pending log on the same node โ re-execute the loop step (go back to step 1)
- Met โ call
execute_step(loop_continue=false) โ loop ends โ call advance to move to next step
Example โ "Clarifying Questions" loop (loop_back_to=self):
Iteration 1: "Who is the primary user of this feature?" โ user answers โ purpose clear, constraints unclear โ loop_continue=true
Iteration 2: "Are there tech stack limitations?" โ user answers โ constraints clear, success criteria unclear โ loop_continue=true
Iteration 3: "What defines completion?" โ user answers โ all items clear โ loop_continue=false โ advance
Example โ "Design Section Presentation" loop:
Iteration 1: Present architecture section โ user "looks good" โ more sections remain โ loop_continue=true
Iteration 2: Present data flow section โ user "needs revision" โ revise and re-present โ loop_continue=true
Iteration 3: Present final section โ user approves โ all sections done โ loop_continue=false โ advance
Loop + VS History Pattern
When a loop node uses visual_selection: true, each iteration presents a VS screen and collects a response. Use get_web_response(task_id, node_id) to access all previous iteration responses for that node:
{
"task_id": 19,
"node_id": 109,
"history": [
{
"iteration": 1,
"web_response": { "selections": ["a"] },
"created_at": "..."
},
{
"iteration": 2,
"web_response": {
"selections": ["b"],
"values": { "confidence": 80 },
"fields": { "change_request": "Need more detail on error handling" }
},
"created_at": "..."
}
]
}
Use the history to adapt subsequent VS screens - for example, pre-selecting the user's previous choice, adjusting slider defaults based on past values, carrying forward fields.change_request into the next revision prompt, or skipping already-confirmed items.
Web UI State Synchronization (์น UI ์ํ ๋๊ธฐํ)
The web UI can change task/step state at any time. You MUST check every heartbeat and execute_step response for the following signals and react immediately:
1. Task cancelled โ cancelled: true
Triggered by: heartbeat response OR advance(peek=true) returning status: "cancelled"
Action:
2. Step rewound โ rewound: true or error code STEP_REWOUND
Triggered by:
heartbeat response contains rewound: true (web UI rewound while step was running)
execute_step returns HTTP 409 with error_code: "STEP_REWOUND" (tried to save a cancelled step)
Action:
3. Step log cancelled but task still running โ log_status: "cancelled" + status: "running"
Triggered by: advance(peek=true) at the start of a step loop
This means the step was reset by a rewind. Action:
- Re-execute this step from scratch. Do not skip it.
- Do not treat this as a terminal error.
Polling cadence
- Call
heartbeat at least every 30 seconds during long-running steps.
- Always check the response โ never fire-and-forget heartbeats.
- At the start of each new step (before executing), verify
advance(peek=true) reflects the expected step. If current_step differs from what you expected, follow the server's value.
Graceful Interruption
Trigger phrases: stop, pause, cancel, abort, hold on, ์ ๊น, ์ค๋จ, ๊ทธ๋ง, ๋ฉ์ถฐ, ์ ์ง, Ctrl+C. Treat any of these mid-workflow as a request to interrupt โ do not silently abort, follow this prompt.
When the user explicitly asks to stop mid-workflow, ask how to handle it:
- Pause (resume later) โ save a brief
context_snapshot via execute_step so state is preserved, leave task as running. The server will auto-timed_out after 2 hours; /bk-start can resume it.
- Cancel โ call
cancel_task(task_id, reason). Task is marked cancelled; no further execute_step/advance calls.
- Keep going โ dismiss the prompt and continue the current step.
Skip this prompt if all steps are already complete and you're about to call complete_task anyway โ the workflow is finishing naturally, not being interrupted.
Feedback Survey (before calling complete_task)
When the workflow finishes, run the feedback survey flow.
Follow the sequence: save_feedback โ complete_task โ suggest improvements.