pylot-workers
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesepylot-workers — Worker API Reference
pylot-workers — Worker API 参考文档
Every operator has this skill loaded as a baseline. Worker-driving skills
(, , ) use these
endpoints to spawn and drive a repo devbox worker via the gateway.
speckit-runnerdeps-runner-procrelease-train-runner-procAll calls require .
Gateway base: (or ).
Mission ID: .
Authorization: Bearer $PYLOT_DISPATCH_TOKEN$PYLOT_API$PYLOT_GATEWAY_URL$PYLOT_JOB_ID每个Operator都会加载该技能作为基准模块。驱动worker的技能(如、、)通过网关调用这些接口来生成并驱动仓库devbox worker。
speckit-runnerdeps-runner-procrelease-train-runner-proc所有调用都需要携带请求头。
网关基础地址:(或)。
任务ID:。
Authorization: Bearer $PYLOT_DISPATCH_TOKEN$PYLOT_API$PYLOT_GATEWAY_URL$PYLOT_JOB_ID1. Spawn a worker
1. 生成Worker
bash
SPAWN_RESP=$(curl -s --max-time 90 -X POST \
-H "Authorization: Bearer $PYLOT_DISPATCH_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"repo\": \"$REPO\"}" \
"${PYLOT_API}/missions/${PYLOT_JOB_ID}/workers")
WID=$(echo "$SPAWN_RESP" | python3 -c 'import sys,json; print(json.load(sys.stdin).get("worker_id",""))' 2>/dev/null)Returns (201) or an error body.
is the worker row id used in all subsequent calls.
{"ok": true, "worker_id": <number>}WIDbash
SPAWN_RESP=$(curl -s --max-time 90 -X POST \
-H "Authorization: Bearer $PYLOT_DISPATCH_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"repo\": \"$REPO\"}" \
"${PYLOT_API}/missions/${PYLOT_JOB_ID}/workers")
WID=$(echo "$SPAWN_RESP" | python3 -c 'import sys,json; print(json.load(sys.stdin).get("worker_id",""))' 2>/dev/null)返回(状态码201)或错误响应体。
是后续所有调用中使用的worker行ID。
{"ok": true, "worker_id": <number>}WID2. Queue a prompt
2. 提交任务提示
bash
PROMPT_RESP=$(curl -s --max-time 30 -X POST \
-H "Authorization: Bearer $PYLOT_DISPATCH_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"prompt\": \"$PROMPT\"}" \
"${PYLOT_API}/missions/${PYLOT_JOB_ID}/workers/${WID}/prompt")
TURN_SEQ=$(echo "$PROMPT_RESP" | python3 -c 'import sys,json; print(json.load(sys.stdin).get("turn_seq",""))' 2>/dev/null)Returns (202) or 409 if the worker is busy.
Always capture — it's the handle for polling.
{"ok": true, "turn_seq": <number>}turn_seqbash
PROMPT_RESP=$(curl -s --max-time 30 -X POST \
-H "Authorization: Bearer $PYLOT_DISPATCH_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"prompt\": \"$PROMPT\"}" \
"${PYLOT_API}/missions/${PYLOT_JOB_ID}/workers/${WID}/prompt")
TURN_SEQ=$(echo "$PROMPT_RESP" | python3 -c 'import sys,json; print(json.load(sys.stdin).get("turn_seq",""))' 2>/dev/null)返回(状态码202),若worker正忙则返回409。
务必捕获——它是轮询状态的唯一标识。
{"ok": true, "turn_seq": <number>}turn_seq3. Poll to idle
3. 轮询至空闲状态
Poll until AND .
turn_state == "idle"turn_seq == TURN_SEQbash
WORKER_EXIT=""; POLL_EL=0; POLL_MAX="${PYLOT_WORKER_POLL_MAX:-2400}"
while [ "$POLL_EL" -lt "$POLL_MAX" ]; do
sleep 15; POLL_EL=$((POLL_EL + 15))
ST=$(curl -s --max-time 20 \
-H "Authorization: Bearer $PYLOT_DISPATCH_TOKEN" \
"${PYLOT_API}/missions/${PYLOT_JOB_ID}/workers/${WID}")
ST_LINE=$(echo "$ST" | python3 -c '
import sys, json
try: d = json.load(sys.stdin)
except: d = {}
ec = d.get("last_exit_code")
print("%s|%s|%s" % (d.get("turn_state",""), d.get("turn_seq",""), "" if ec is None else ec))
' 2>/dev/null)
W_STATE="${ST_LINE%%|*}"; W_REST="${ST_LINE#*|}"; W_SEQ="${W_REST%%|*}"; W_EC="${W_REST##*|}"
if [ "$W_STATE" = "idle" ] && [ "$W_SEQ" = "$TURN_SEQ" ]; then WORKER_EXIT="$W_EC"; break; fi
donelast_output$STexit_code=-1持续轮询,直到且。
turn_state == "idle"turn_seq == TURN_SEQbash
WORKER_EXIT=""; POLL_EL=0; POLL_MAX="${PYLOT_WORKER_POLL_MAX:-2400}"
while [ "$POLL_EL" -lt "$POLL_MAX" ]; do
sleep 15; POLL_EL=$((POLL_EL + 15))
ST=$(curl -s --max-time 20 \
-H "Authorization: Bearer $PYLOT_DISPATCH_TOKEN" \
"${PYLOT_API}/missions/${PYLOT_JOB_ID}/workers/${WID}")
ST_LINE=$(echo "$ST" | python3 -c '
import sys, json
try: d = json.load(sys.stdin)
except: d = {}
ec = d.get("last_exit_code")
print("%s|%s|%s" % (d.get("turn_state",""), d.get("turn_seq",""), "" if ec is None else ec))
' 2>/dev/null)
W_STATE="${ST_LINE%%|*}"; W_REST="${ST_LINE#*|}"; W_SEQ="${W_REST%%|*}"; W_EC="${W_REST##*|}"
if [ "$W_STATE" = "idle" ] && [ "$W_SEQ" = "$TURN_SEQ" ]; then WORKER_EXIT="$W_EC"; break; fi
done最终响应中的字段包含worker的任务输出(仅保留末尾16 KB内容)。
若devbox在任务执行中途崩溃,执行器的过期任务清理器会将设为-1,因此轮询不会无限期挂起。
$STlast_outputexit_code4. Stop the worker
4. 停止Worker
bash
curl -s --max-time 30 -X POST \
-H "Authorization: Bearer $PYLOT_DISPATCH_TOKEN" \
"${PYLOT_API}/missions/${PYLOT_JOB_ID}/workers/${WID}/stop" >/dev/null 2>&1 || trueIdempotent. Always call stop when the skill is done — even if the turn failed.
The harvest backstop also stops workers, but explicit stop is faster and cheaper.
bash
curl -s --max-time 30 -X POST \
-H "Authorization: Bearer $PYLOT_DISPATCH_TOKEN" \
"${PYLOT_API}/missions/${PYLOT_JOB_ID}/workers/${WID}/stop" >/dev/null 2>&1 || true该操作具有幂等性。无论任务是否成功,技能执行完成后务必调用停止接口。
回收兜底机制也会停止worker,但显式调用停止接口速度更快、成本更低。
Drive loop pattern
驱动循环模式
spawn → prompt(phase1) → poll-to-idle → check output →
prompt(phase2) → poll-to-idle → check output →
...
stop → emit [pylot] outcome= markerBetween phases, read from the final poll response to detect
phase-level failures before sending the next prompt.
last_outputEmit the outcome marker AFTER stopping the worker:
[pylot] outcome="<summary>" status=<success|partial|failed|blocked>生成 → 提交任务提示(阶段1) → 轮询至空闲 → 检查输出 →
提交任务提示(阶段2) → 轮询至空闲 → 检查输出 →
...
停止Worker → 输出 [pylot] outcome= 标记在不同阶段之间,从最终轮询响应中读取,以便在提交下一个任务提示前检测当前阶段是否失败。
last_output停止Worker后再输出结果标记:
[pylot] outcome="<summary>" status=<success|partial|failed|blocked>