Workflow
Gestalt workflows define an ordered steps plan and one or more
top-level on activations. A trusted workflow provider owns durable
definitions, activation state, workflow runs, per-step execution state, run
events, and run output.
The public workflow contract is intentionally small:
ApplyDefinitionstores or updates one durable definition.SetDefinitionPausedandSetActivationPausedcontrol execution.StartRun,SignalRun, andSignalOrStartRunoperate on definition-backed runs and carryinput.DeliverEventsends an app event to provider-owned activation matching.GetRun,ListRuns,GetRunEvents, andGetRunOutputexpose run state.
There are no separate public CRUD objects for cron or event activation
records. Author one workflow definition with steps and on, then let the
provider reconcile activations internally.
Definitions
Config-managed workflows live under workflows.definitions.
workflows:
definitions:
toolshed_pr_code_review:
provider: temporal
runAs:
subject:
id: service_account:github_webhook
kind: service_account
paused: false
steps:
- id: review
app:
name: codeReview
operation: pullRequests.reviewWorkflow
input:
github: "${{ input.github }}"
raw: "${{ input.raw }}"
on:
github_pr:
event:
type: github.pull_request
source: github
subject: repo:valon-technologies/toolshed
input:
github: "${{ signal.data.github }}"
raw: "${{ signal.data.raw }}"
nightly:
schedule:
cron: "0 2 * * *"
timezone: America/New_York
input:
reason: nightlyEach definition is applied to the provider during bootstrap with a stable config ID. The provider assigns a generation and pins in-flight runs to the generation they started with.
Steps
A workflow step is either an app operation or an agent turn.
steps:
- id: diagnose
app:
name: datadog
operation: logs.search
input:
query: "${{ input.query }}"
- id: summarize
agent:
provider: openai
model: gpt-5.5
prompt:
template: "Summarize: ${{ steps.diagnose.outputs.body }}"
- id: notify
app:
name: slack
operation: messages.post
input:
channel: "${{ input.channel }}"
text: "${{ steps.summarize.outputs.text }}"timeout/timeoutSeconds is an optional per-step override. Omit it to use the
provider default.
Expressions
Workflow authoring uses ${{ ... }} expressions. Supported roots are:
input.*: run input after activation mapping.signal.*: the latest signal or delivered event payload available while mapping activation input.steps.<stepId>.outputs.*: output from a prior step.steps.<stepId>.inputs.*: materialized inputs for a prior step.
when guards must resolve to booleans. A skipped dependency skips the
dependent step with a missing-dependency reason.
Events
Apps deliver events through the workflow service.
import { Workflow } from "@valon-technologies/gestalt";
const workflows = Workflow.connect();
await workflows.deliverEvent(
{
type: "github.pull_request",
source: "github",
subject: "repo:valon-technologies/toolshed",
datacontenttype: "application/json",
data: { github, raw },
},
{ appName: "github", providerName: "temporal" },
);The provider matches the event against definition activations, evaluates the
activation input mapping, and starts or signals runs with the resulting
run.input.
Providers
A workflow provider implements the WorkflowProvider service:
type Provider struct{}
func (p *Provider) ApplyDefinition(
ctx context.Context,
req *gestalt.ApplyWorkflowProviderDefinitionRequest,
) (*gestalt.WorkflowDefinition, error) {
// Store req.Spec atomically and return the provider generation.
return &gestalt.WorkflowDefinition{
Id: req.Spec.Id,
Generation: 1,
Target: req.Spec.Target,
Activations: req.Spec.Activations,
ProviderName: req.ProviderName,
}, nil
}
func (p *Provider) StartRun(
ctx context.Context,
req *gestalt.StartWorkflowProviderRunRequest,
) (*gestalt.WorkflowRun, error) {
return &gestalt.WorkflowRun{
Id: req.IdempotencyKey,
DefinitionId: req.DefinitionId,
DefinitionGeneration: req.ExpectedDefinitionGeneration,
Input: req.Input,
}, nil
}Providers execute one durable unit per step and persist the run projection
after each step. GetRun returns the current step list, and GetRunEvents /
GetRunOutput expose the event stream and final output.