Was macht TaskFlow?
Verwende TaskFlow, wenn ein Job länger als eine Prompt oder einen einzelnen entkoppelten Lauf überdauern muss, du aber dennoch eine einzige Besitzersitzung, einen gemeinsamen Rückgabekontext und einen zentralen Ort zur Überprüfung oder Wiederaufnahme der Arbeit haben möchtest.
Wann verwenden
- Mehrschrittige Hintergrundarbeit mit einem Besitzer
- Arbeit, die auf entkoppelte ACP- oder Unteraufgaben wartet
- Jobs, die möglicherweise eine klare Rückmeldung an den Besitzer senden müssen
- Jobs, die einen kleinen persistierten Zustand zwischen Schritten benötigen
- Plugin- oder Tool-Arbeit, die Neustarts und Revisionskonflikte sauber überstehen muss
Was TaskFlow verwaltet
- Flussidentität
- Besitzersitzung und Ursprung des Anforderers
currentStep,stateJsonundwaitJson- Verknüpfte Unteraufgaben und deren übergeordnete Fluss-ID
- Zustände: fertig, fehlgeschlagen, abgebrochen, wartend, blockiert
- Revisionsverfolgung für konfliktsichere Mutationen
Es verwaltet keine Verzweigungen oder Geschäftslogik. Das gehört in Lobster, acpx oder den aufrufenden Code.
Aktuelle Runtime-Form
Kanonischer Plugin-/Runtime-Einstiegspunkt:
api.runtime.tasks.flowapi.runtime.taskFlowexistiert weiterhin als Alias, aberapi.runtime.tasks.flowist die kanonische Form
Bindung:
api.runtime.tasks.flow.fromToolContext(ctx), wenn du bereits vertrauenswürdigen Tool-Kontext mitsessionKeyhastapi.runtime.tasks.flow.bindSession({ sessionKey, requesterOrigin }), wenn deine Bindungsschicht die Sitzung und den Zustellkontext bereits aufgelöst hat
Lebenszyklus eines verwalteten Flows:
createManaged(...)runTask(...)setWaiting(...), wenn auf eine Person oder ein externes System gewartet wirdresume(...), wenn die Arbeit fortgesetzt werden kannfinish(...)oderfail(...)requestCancel(...)odercancel(...), wenn der gesamte Job gestoppt werden soll
Entwurfsbeschränkungen
- Verwende verwaltete TaskFlows, wenn dein Code die Orchestrierung selbst steuert.
- Gespiegelte Flows mit einer einzigen Aufgabe werden von der Core-Runtime für entkoppelte ACP-/Unteraufgaben erstellt; dieser Skill befasst sich hauptsächlich mit verwalteten Flows.
- Behandle
stateJsonals den persistierten Zustandsbehälter. Es gibt keine separatesetFlowOutput- oderappendFlowOutput-API. - Jede mutierende Methode nach der Erstellung wird revisionsgeprüft. Führe die neueste
flow.revisionnach jeder erfolgreichen Mutation weiter. runTask(...)verknüpft die Unteraufgabe mit dem Fluss. Verwende sie anstelle der manuellen Erstellung entkoppelter Aufgaben, wenn du eine übergeordnete Orchestrierung wünschst.
Beispielstruktur
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,
});
Bedingungslogik oberhalb der Runtime halten
Verwende die Fluss-Runtime für Zustand und Aufgabenverknüpfung. Behalte Entscheidungen in der Autorenschicht:
business-> in Slack posten und wartenpersonal-> Besitzer jetzt benachrichtigenlater-> an einen End-of-Day-Zusammenfassungsbehälter anhängen
Betriebsmuster
- Speichere nur den minimalen Zustand, der zur Wiederaufnahme benötigt wird.
- Füge menschenlesbare Wartegründe in
blockedSummaryoder strukturierte Wartemetadaten inwaitJsonein. - Verwende
getTaskSummary(flowId), wenn der Orchestrator eine kompakte Gesundheitsübersicht der Unteraufgaben benötigt. - Verwende
requestCancel(...), wenn ein Aufrufer möchte, dass der Fluss die Planung sofort einstellt. - Verwende
cancel(...), wenn du auch aktive verknüpfte Unteraufgaben abbrechen möchtest.
Beispiele
- Siehe
skills/taskflow/examples/inbox-triage.lobster - Siehe
skills/taskflow/examples/pr-intake.lobster - Siehe
skills/taskflow-inbox-triage/SKILL.mdfür ein konkretes Routing-Muster