v0.4.0-alpha
v0.4.0-alpha
Released: February 2026
Flow lifecycle hooks, gate nodes for approval workflows, child workflow composition, dynamic flow templates, and two new providers.
New Features
Flow Hooks
Flows now support lifecycle callbacks at flow, step, and node boundaries. All callbacks are optional — nil callbacks are safely skipped.
flow := core.NewFlow("monitored-pipeline").
TriggeredBy(core.Schedule("*/15 * * * *")).
WithHooks(&core.FlowHooks{
BeforeFlow: func(ctx core.HookContext) {
log.Info("flow starting", "flow", ctx.FlowName)
},
AfterNode: func(ctx core.HookContext) {
log.Info("node completed",
"node", ctx.NodeName,
"duration", ctx.Duration,
"error", ctx.Error,
)
},
OnCost: func(entry core.CostEntry) {
metrics.RecordLLMCost(entry.Model, entry.CostUSD)
},
}).
Then(fetchNode).
Then(processNode).
Build()New APIs:
| API | Description |
|---|---|
FlowHooks | Struct holding optional lifecycle callbacks |
HookContext | Carries FlowName, StepName, NodeName, Duration, Error |
CostEntry | LLM cost event with Model, Provider, TokensIn/Out, CostUSD |
.WithHooks(*FlowHooks) | Attach hooks to a flow via FlowBuilder |
Hooks run inside Temporal’s deterministic workflow context. They must not perform I/O directly — enqueue activities for side effects.
Gate Nodes
Gates pause flow execution until an external Temporal signal is received. Use them for approval workflows, manual review steps, or wait-for-event patterns.
flow := core.NewFlow("deploy-with-approval").
TriggeredBy(core.Manual("api")).
Then(runTestsNode).
ThenGate("approval", core.GateConfig{
SignalName: "deploy-approval",
Timeout: 24 * time.Hour,
}).
Then(deployNode).
Build()To approve from outside the workflow:
client.SignalWorkflow(ctx, workflowID, "", "deploy-approval", core.GateResult{
Approved: true,
DecidedBy: "alice@company.com",
Reason: "Tests passed, deploy approved",
})New APIs:
| API | Description |
|---|---|
GateNode | ExecutableNode that waits for a signal |
GateConfig{SignalName, Timeout} | Signal name to wait for and optional timeout |
GateResult | Decision payload with Approved, DecidedBy, Reason, Metadata |
GateTimeoutError | Returned when timeout expires before signal |
.ThenGate(name, config) | Add a gate step via FlowBuilder |
Child Flow Nodes
Spawn child workflows from a parent flow for fan-out processing, batch operations, or nested workflow composition.
processingFlow := core.NewFlow("process-item").
TriggeredBy(core.Manual("internal")).
Then(processNode).
Build()
parentFlow := core.NewFlow("batch-processor").
TriggeredBy(core.Schedule("0 * * * *")).
Then(fetchItemsNode).
ThenChildren("process-items", core.ChildFlowConfig{
Flow: processingFlow,
InputMapper: func(state *core.FlowState) []core.FlowInput {
items := core.Get[FetchOutput](state, "fetch-items")
inputs := make([]core.FlowInput, len(items.Items))
for i, item := range items.Items {
inputs[i] = core.FlowInput{
Data: map[string][]byte{
"item": marshal(item),
},
}
}
return inputs
},
}).
Then(aggregateNode).
Build()New APIs:
| API | Description |
|---|---|
ChildFlowNode | ExecutableNode that spawns child workflows |
ChildFlowConfig{Flow, InputMapper, Sequential} | Child flow, input derivation function, execution mode |
ChildFlowResults{States, Errors, Count} | Aggregated results from all child workflows |
.ThenChildren(name, config) | Add a child flow step via FlowBuilder |
Parallel execution by default. Set Sequential: true to process children one at a time, stopping on first error.
Flow Templates
Construct flows dynamically at runtime when step composition depends on configuration, feature flags, or user input.
tmpl := core.NewFlowTemplate("dynamic-pipeline").
TriggeredBy(core.Manual("api"))
tmpl.AddStep(fetchNode)
if config.NeedsApproval {
tmpl.AddGate("review", core.GateConfig{
SignalName: "review-approval",
Timeout: 48 * time.Hour,
})
}
if config.ParallelProcessing {
tmpl.AddParallel("process-all", transformNode, enrichNode)
} else {
tmpl.AddStep(transformNode)
tmpl.AddStep(enrichNode)
}
tmpl.AddStep(storeNode)
flow := tmpl.Build()New APIs:
| API | Description |
|---|---|
FlowTemplate | Runtime flow builder (vs compile-time FlowBuilder) |
NewFlowTemplate(name) | Create a new template |
.AddStep(node) | Add a sequential step |
.AddParallel(name, ...nodes) | Add a parallel step |
.AddGate(name, config) | Add a gate step |
.AddChildren(name, config) | Add a child flow step |
.AddConditional(pred, then, else) | Add a conditional branch |
.Build() | Validate and return a *Flow |
InputData Magic Marker
Access webhook payload data from activity input structs using the InputData marker.
flow := core.NewFlow("webhook-handler").
TriggeredBy(core.Webhook("/bitbucket")).
Then(bitbucket.ParseWebhook(bitbucket.ParseWebhookInput{
RawPayload: core.InputData("webhook_payload"),
})).
Then(processNode).
Build()| API | Description |
|---|---|
core.InputData(key) | Creates {{input:key}} marker resolved at execution time |
FlowState.GetInputData(key) | Retrieves raw input data by key |
New Providers
Bitbucket (resolute-bitbucket)
Bitbucket integration for webhook-driven workflows and PR automation.
go get github.com/resolute-sh/resolute-bitbucket@v0.4.0-alphaActivities:
| Activity | Description |
|---|---|
ParseWebhook | Parses raw webhook payload into structured PRMetadata |
AddComment | Posts a comment to a Bitbucket pull request |
Utility: ExtractTicketID(branch) extracts Jira ticket IDs from branch names.
Slack (resolute-slack)
Slack integration for sending notifications via incoming webhooks.
go get github.com/resolute-sh/resolute-slack@v0.4.0-alphaActivities:
| Activity | Description |
|---|---|
SendMessage | Sends messages via Slack webhook with Block Kit support |
Installation
go get github.com/resolute-sh/resolute@v0.4.0-alphaMigration from v0.3.0-alpha
No breaking changes to existing APIs. All new features are additive:
WithHooks,ThenGate,ThenChildrenare optional FlowBuilder methodsFlowTemplateis an alternative toFlowBuilder— existing flows are unaffectedInputDatais a new marker alongside existingCursorForandOutputRef- New providers are independent modules installed separately
Full Changelog
v0.3.0-alpha…v0.4.0-alpha