TaskFlow 인박스 분류
이것은 TaskFlow를 핵심 런타임을 DSL로 변환하지 않고도 어떻게 사용할 수 있는지에 대한 구체적인 예제입니다.
목표
단일 소유자 플로우로 인박스 항목을 분류합니다:
- 업무 -> Slack에 게시하고 회신 대기
- 개인 -> 지금 소유자에게 알림
- 기타 -> 하루 마무리 요약을 위해 보관
패턴
- 인박스 배치를 위한 하나의 플로우를 생성합니다.
- 새 항목을 분류하기 위해 분리된 태스크를 하나 실행합니다.
- 라우팅 상태를
stateJson에 저장합니다. - 외부 회신이 필요할 때만
waiting상태로 전환합니다. - 분류 또는 사람의 입력이 완료되면 플로우를 재개합니다.
- 배치가 라우팅 완료되면 종료합니다.
제안된 stateJson 형태
{
"businessThreads": [],
"personalItems": [],
"eodSummary": []
}
Slack에서 차단되었을 때 제안된 waitJson:
{
"kind": "reply",
"channel": "slack",
"threadKey": "slack:thread-1"
}
최소 런타임 호출
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 child = taskFlow.runTask({
flowId: created.flowId,
runtime: "acp",
childSessionKey: "agent:main:subagent:classifier",
task: "Classify inbox messages",
status: "running",
startedAt: Date.now(),
lastEventAt: Date.now(),
});
if (!child.created) {
throw new Error(child.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: "route_items",
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,
});
관련 예제
skills/taskflow/examples/inbox-triage.lobster