TaskFlow은(는) 무엇을 하나요?
작업이 하나의 프롬프트나 분리된 실행을 넘어서 지속되어야 하지만, 여전히 하나의 소유자 세션, 하나의 반환 컨텍스트, 그리고 작업을 검사하거나 재개할 수 있는 하나의 장소를 원할 때 TaskFlow를 사용하세요.
사용 시기
- 하나의 소유자가 있는 다단계 백그라운드 작업
- 분리된 ACP 또는 서브에이전트 작업을 기다리는 작업
- 소유자에게 하나의 명확한 업데이트를 내보내야 하는 작업
- 단계 사이에 작은 지속 상태가 필요한 작업
- 재시작 및 리비전 충돌을 깔끔하게 처리해야 하는 플러그인 또는 도구 작업
TaskFlow가 소유하는 것
- 플로우 아이덴티티
- 소유자 세션 및 요청자 출처
currentStep,stateJson,waitJson- 연결된 하위 작업 및 상위 플로우 ID
- 완료, 실패, 취소, 대기, 차단 상태
- 충돌 없는 변경을 위한 리비전 추적
분기 처리나 비즈니스 로직은 소유하지 않습니다. 이는 Lobster, acpx 또는 호출 코드에서 처리하세요.
현재 런타임 형태
표준 플러그인/런타임 진입점:
api.runtime.tasks.flowapi.runtime.taskFlow는 여전히 별칭으로 존재하지만,api.runtime.tasks.flow가 표준 형태입니다.
바인딩:
api.runtime.tasks.flow.fromToolContext(ctx)— 이미 신뢰할 수 있는 도구 컨텍스트에sessionKey가 있는 경우 사용api.runtime.tasks.flow.bindSession({ sessionKey, requesterOrigin })— 바인딩 레이어가 이미 세션 및 전달 컨텍스트를 확인한 경우 사용
관리형 플로우 라이프사이클:
createManaged(...)runTask(...)setWaiting(...)— 사람이나 외부 시스템을 기다릴 때resume(...)— 작업을 계속할 수 있을 때finish(...)또는fail(...)requestCancel(...)또는cancel(...)— 전체 작업을 중단해야 할 때
설계 제약 조건
- 코드가 오케스트레이션을 소유하는 경우 관리형 TaskFlow를 사용하세요.
- 분리된 ACP/서브에이전트 작업을 위해 코어 런타임이 생성하는 단일 작업 미러링된 플로우가 있습니다. 이 스킬은 주로 관리형 플로우에 관한 것입니다.
stateJson을 지속 상태 저장소로 취급하세요. 별도의setFlowOutput또는appendFlowOutputAPI는 없습니다.- 생성 후 모든 변경 메서드는 리비전 검사를 거칩니다. 각 성공적인 변경 후 최신
flow.revision을 전달하세요. runTask(...)는 하위 작업을 플로우에 연결합니다. 상위 오케스트레이션이 필요할 때 수동으로 분리된 작업을 생성하는 대신 이 메서드를 사용하세요.
예시 형태
const taskFlow = api.runtime.tasks.flow.fromToolContext(ctx);
const created = taskFlow.createManaged({
controllerId: "my-plugin/inbox-triage",
goal: "triage inbox",
currentStep: "classify",
stateJson: {
businessThreads: [],
personalItems: [],
eodSummary: [],
},
});
const classify = taskFlow.runTask({
flowId: created.flowId,
runtime: "acp",
childSessionKey: "agent:main:subagent:classifier",
runId: "inbox-classify-1",
task: "Classify inbox messages",
status: "running",
startedAt: Date.now(),
lastEventAt: Date.now(),
});
if (!classify.created) {
throw new Error(classify.reason);
}
const waiting = taskFlow.setWaiting({
flowId: created.flowId,
expectedRevision: created.revision,
currentStep: "await_business_reply",
stateJson: {
businessThreads: ["slack:thread-1"],
personalItems: [],
eodSummary: [],
},
waitJson: {
kind: "reply",
channel: "slack",
threadKey: "slack:thread-1",
},
});
if (!waiting.applied) {
throw new Error(waiting.code);
}
const resumed = taskFlow.resume({
flowId: waiting.flow.flowId,
expectedRevision: waiting.flow.revision,
status: "running",
currentStep: "finalize",
stateJson: waiting.flow.stateJson,
});
if (!resumed.applied) {
throw new Error(resumed.code);
}
taskFlow.finish({
flowId: resumed.flow.flowId,
expectedRevision: resumed.flow.revision,
stateJson: resumed.flow.stateJson,
});
조건문은 런타임 위에 유지
플로우 런타임은 상태 및 작업 연결에 사용하세요. 결정은 작성 레이어에서 유지:
business-> Slack에 게시하고 대기personal-> 지금 소유자에게 알림later-> 하루 요약 버킷에 추가
운영 패턴
- 재개에 필요한 최소 상태만 저장하세요.
- 사람이 읽을 수 있는 대기 사유는
blockedSummary에, 구조화된 대기 메타데이터는waitJson에 저장하세요. - 오케스트레이터가 하위 작업의 간결한 상태를 확인해야 할 때
getTaskSummary(flowId)를 사용하세요. - 호출자가 플로우를 즉시 스케줄링 중단하려는 경우
requestCancel(...)을 사용하세요. - 활성 상태인 연결된 하위 작업도 취소하려는 경우
cancel(...)을 사용하세요.
예제
skills/taskflow/examples/inbox-triage.lobster참조skills/taskflow/examples/pr-intake.lobster참조skills/taskflow-inbox-triage/SKILL.md에서 구체적인 라우팅 패턴 참조