Session Steps
A session step supports three actions:
| Action | Use it to |
|---|---|
launch_task | Launch an agent with a Valdr task |
launch_prompt | Launch an agent from a prompt without requiring a task |
input | Send a follow-up message to an existing session |
Fields by action
Valdr supplies the run actor and a unique request ID. It can also supply taskKey from a task-scoped run. You author the fields that choose the work and the agent:
| Action | Required authored fields | Common optional fields |
|---|---|---|
launch_task | taskKey unless the run is task-scoped, agentHandle, launcherConfigKey | role, additionalInstructions, capabilityKeys, worktree, provider, config, maxRuntimeSeconds |
launch_prompt | prompt, launcherConfigKey | contextRef, role, worktree, provider, config, maxRuntimeSeconds |
input | sessionUlid, prompt | expectAgentHandle, expectTaskKey |
The selected launcher preset provides the provider configuration. If you also set provider, it must match that preset.
Launch a task agent
- key: launch_executor
name: Launch Executor
kind: session
session:
action: launch_task
taskKey: "${workflow.inputs.taskKey}"
agentHandle: "${workflow.inputs.executorHandle}"
launcherConfigKey: "${workflow.inputs.launcherConfigKey}"
role: executor
waitsFor:
kind: workflow_input
expected: [executor_completed, executor_blocked]
outputs:
sessionUlid: "$.normalized.session.sessionUlid"
outcome: "$.normalized.input.outcome"Provide a task key, registered agent handle, and launcher preset. A task-scoped run can supply the task key automatically.
The declared sessionUlid lets later steps wait for the session, launch a reviewer against its work, or send a follow-up turn.
Launch a prompt-only agent
- key: summarize_risk
name: Summarize Risk
kind: session
session:
action: launch_prompt
prompt: "Summarize the release risk for ${workflow.inputs.releaseName}."
launcherConfigKey: coder-codex
contextRef: "release:${workflow.inputs.releaseName}"
waitsFor:
kind: workflow_input
expected: [summary_ready]
gates:
- key: summary
kind: session_output
source:
event: final_agent_message
extract: { format: json, path: $.outcome }
outcomes: { summary_ready: summary_ready }
onInvalid: { action: block }
outputs:
sessionUlid: "$.normalized.session.sessionUlid"
outcome: "$.normalized.input.outcome"prompt and launcherConfigKey are required. Use contextRef when the session should join other taskless work under the same local context. This example expects the agent’s final message to contain JSON with "outcome": "summary_ready".
Interpret structured session output
A session-output gate maps a field from the final agent message into the step’s expected outcome. Put the gate on a start-and-wait Session or Review step, as above, or on a Session input step. Only one session-output gate is supported per wait.
For a start-and-wait launch, omit source.sessionUlid or bind it to that step’s own session. For a Session input gate, source.sessionUlid is required and must identify the session receiving the turn. onInvalid.action may be block, keep_waiting, or default; default also requires a defaultOutcome listed under waitsFor.expected. Use payload.includeParsed or payload.includeSession only when downstream work needs that data.
Launch steps should choose an explicit completion mode. Add waitsFor when the step owns completion, or set detached: true and join that exact turn with a later await_condition step. For launch_task only, use run: false when the workflow should create the task session without dispatching work. Prompt-only launches must run when created.
| Mode | Configuration | Use it when |
|---|---|---|
| Start and wait | Add waitsFor | This step should wait for and own the agent outcome |
| Continue after dispatch | Set detached: true | Other work can proceed before a later exact-turn join |
| Create session only | Set run: false on launch_task | A later step will send the first turn |
Continue an existing session
- key: request_revision
name: Request Revision
kind: session
needs: [launch_executor]
session:
action: input
sessionUlid: "${steps.launch_executor.outputs.sessionUlid}"
expectAgentHandle: "${workflow.inputs.executorHandle}"
expectTaskKey: "${workflow.inputs.taskKey}"
prompt: "Apply the latest review feedback and report when the revision is ready."
waitsFor:
kind: workflow_input
expected: [revision_ready]Use input when the same agent should preserve its existing conversation and worktree context. expectAgentHandle and expectTaskKey make Valdr verify that the target session belongs to the intended agent and task before sending the message. Declare the wait, gate, and outputs on the input step so it owns that follow-up turn before the workflow advances. A separate await_condition around exactly one non-detached Session input step is rejected as redundant.
Results to map
Launch actions expose the session identity under $.normalized.session. Map sessionUlid whenever another step needs to inspect, review, or continue that session. A start-and-wait launch also exposes the accepted outcome under $.normalized.input.outcome; a detached launch exposes turnClientRequestId for an exact-turn join.
Builder controls
The session card changes its fields when you choose an action. It offers current agents, launcher presets, workflow inputs, and outputs from upstream steps, then lets you map the results needed later.
Failure and recovery
If a launch cannot find the selected agent or launcher preset, the run blocks with a visible error. Restore or register the referenced agent or preset and use Retry step when Valdr offers it. To change the binding, update the definition and start a new run; a Session retry retains the run’s frozen binding.
Next step
Add an Await-Condition Step when later work must wait for the session’s result, or add a Review Step to evaluate its implementation.