feat(flows): add decision node type for constrained LLM branching#210
Open
JoshuaLelon wants to merge 2 commits intoopenclaw:mainfrom
Open
feat(flows): add decision node type for constrained LLM branching#210JoshuaLelon wants to merge 2 commits intoopenclaw:mainfrom
JoshuaLelon wants to merge 2 commits intoopenclaw:mainfrom
Conversation
Add a first-class `decision` node type to ACPX flows that makes a single
constrained LLM call and returns a validated `{ choice, reasoning }` result
for use with switch edge routing.
Key design:
- `DecisionNodeDefinition` takes `prompt`, `options: Record<string, string>`,
and optional `model`/`profile` fields
- `resolveDecision` callback on `FlowRunnerOptions` keeps ACPX provider-agnostic —
callers inject their own structured output implementation (e.g. OpenAI
response_format, Anthropic tool_use)
- Falls back to isolated ACP agent session with structured prompt + JSON parse
when no resolver is provided
- `validateDecisionResult` enforces choice ∈ options at runtime
- Output feeds naturally into existing `switch` edges via `$.choice`
🤖 AI-assisted (Claude Code) — fully tested
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ptional - Make DecisionResult.reasoning optional — resolveDecision callbacks no longer need to provide reasoning if the decision doesn't require it - Extract runIsolatedAcpPromptWithTrace helper to deduplicate the isolated session path shared by executeAcpNode and executeDecisionNode (~70 lines) - Add ACP fallback test for decision nodes (no resolveDecision provided) - Add test for optional reasoning and non-string reasoning validation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
decisionnode type to ACPX flows for single constrained LLM calls that return validated{ choice, reasoning? }resultsresolveDecisioncallback onFlowRunnerOptions— keeps ACPX provider-agnostic while enabling callers to inject structured output implementations (OpenAIresponse_format, Anthropictool_use, etc.)extractJsonObjectparse when no resolver is providedchoice ∈ optionsat runtime; invalid choices fail the nodereasoningis optional — resolvers that don't need to explain themselves can omit itrunIsolatedAcpPromptWithTracehelper to deduplicate the isolated session path betweenexecuteAcpNodeandexecuteDecisionNodeswitchedges via$.choiceUsage
Files changed
src/flows/types.tsDecisionNodeDefinition,DecisionResolverInput,DecisionResulttypes;resolveDecisiononFlowRunnerOptions;reasoningoptionalsrc/flows/definition.tsdecision()builder helpersrc/flows/runtime.tsexecuteDecisionNode,validateDecisionResult, ACP fallback,runIsolatedAcpPromptWithTraceshared helpersrc/flows/store.tssrc/flows.tstest/flows.test.tsTest plan
pnpm run typecheck— cleanpnpm run build— cleanpnpm run test— 0 failures (7 new decision tests + all existing tests pass)🤖 AI-assisted (Claude Code) — fully tested
Generated with Claude Code