Skip to content

feat(flows): add decision() helper for constrained LLM branching#278

Merged
steipete merged 1 commit into
openclaw:mainfrom
JoshuaLelon:feat/decision-helper
May 5, 2026
Merged

feat(flows): add decision() helper for constrained LLM branching#278
steipete merged 1 commit into
openclaw:mainfrom
JoshuaLelon:feat/decision-helper

Conversation

@JoshuaLelon
Copy link
Copy Markdown
Contributor

Summary

  • Adds decision() and decisionEdge() to acpx/flows — a typed, narrow helper for constrained LLM branching built on top of the existing acp + parse + switch machinery. decision() returns a plain AcpNodeDefinition that scaffolds the JSON-with-reason prompt and validates the chosen value against the supplied choices tuple. decisionEdge() builds the matching switch edge with cases typed as Record<TChoice, string>, so a missing case is a compile error.
  • Rewrites examples/flows/branch.flow.ts to use the helper, demonstrating the ergonomic win (choices declared once, shared between node and edge).
  • Reframes the constrained-branching idea from feat(flows): add decision node type for constrained LLM branching #210 as the smaller, design-aligned helper that @steipete suggested in #210 (comment). feat(flows): add decision node type for constrained LLM branching #210 is closed and superseded by this PR.

What this deliberately does not touch

  • No new node type. decision() returns nodeType: "acp", so src/flows/schema.ts (FLOW_NODE_TYPES) is unchanged. No definition snapshot fields, no replay-viewer cases, no compatibility test churn.
  • No FlowRunnerOptions change for provider-specific structured output. This is pure prompt engineering in user-space; if structured output later becomes a first-class feature, this helper can be reimplemented on top with no caller changes.
  • No new dependencies. Uses existing extractJsonObject from src/flows/json.ts.

Codebase consistency

  • Prompt scaffold matches the existing convention used across examples/flows/** ("Return exactly one JSON object with this shape:").
  • Error messages follow the sentence-style/no-prefix convention from src/flows/graph.ts and src/flows/json.ts.
  • Public API documented with the same // line-comment style used in src/flows/json.ts.
  • decision() accepts the same flat field shape as acp() (profile, cwd, session, timeoutMs, …) plus the helper-specific question/choices/field.

Test plan

  • pnpm run typecheck
  • pnpm run lint (oxlint + persisted-key-casing + flow-schema-terms)
  • pnpm run format:check
  • pnpm run lint:docs
  • pnpm test — 34/34 flow tests pass, including 3 new tests covering prompt scaffolding, choice validation reject paths (out-of-set value, missing field, non-object), custom field name + acp option pass-through, and edge construction.
  • Reviewer to spot-check examples/flows/branch.flow.ts with acpx flow run examples/flows/branch.flow.ts --input-json '{"task":"..."}' against a real agent.

🤖 Generated with Claude Code

@steipete steipete self-assigned this May 5, 2026
Wraps the existing acp + parse + switch pattern into a typed helper that
scaffolds the JSON-with-reason prompt and validates the chosen value
against the supplied choices tuple. decisionEdge() builds the matching
switch edge with exhaustively-typed cases. Returns a plain AcpNodeDefinition
so no schema, snapshot, or replay-viewer changes are required.

Rewrites examples/flows/branch.flow.ts to use the helper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@steipete steipete force-pushed the feat/decision-helper branch from 1257677 to ea63cf1 Compare May 5, 2026 19:27
@steipete steipete merged commit 2d1e30d into openclaw:main May 5, 2026
@steipete
Copy link
Copy Markdown
Contributor

steipete commented May 5, 2026

Landed via temp rebase onto main.\n\n- Gate: pnpm run check (602/602, coverage), pnpm run check:docs, focused node --test dist-test/test/flows.test.js, built-CLI decision flow smoke, and npm pack --dry-run --json --ignore-scripts.\n- Windows crabbox: host cpc-steip-11eno answered Tailscale ping, but SSH attach timed out on ports 22 and 2222, so no Windows SSH smoke was possible from this machine.\n- Land commit: ea63cf1377b74e728dba5c98e0c4d6e9f2d7e7f4\n- Merge commit: 2d1e30d00c246b441b40b718392ea09730e0d1e3\n\nThanks @JoshuaLelon!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants