feat(ai-studio): human decision node. A run parks on the canvas until a person decides - #154
Open
piotrblaszczyk wants to merge 7 commits into
Open
piotrblaszczyk wants to merge 7 commits into
piotrblaszczyk wants to merge 7 commits into
Conversation
…tion the request offers
…og and on the controls
piotrblaszczyk
marked this pull request as ready for review
September 15, 2026 13:05
piotrblaszczyk
requested review from
librowski,
lukasz-jazwa and
szymon-t-sc
as code owners
September 15, 2026 13:05
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.
What
A node an author drops on the AI Studio canvas that stops the run until a person decides. The worker executor returns
{ waiting: true }(durable pause, #120), the node carries adecisionRequest(#127), andPOST /api/executions/:id/decision(#133) resumes it. The canvas shows the wait; the "Refund Review" template shows the whole loop. No engine or backend code changes.Changes
apps/execution-workerdomain/ai-studio-nodes.ts:HumanDecisionNodewith an empty config (the request travels onBaseNode.decisionRequest).executors/human-decision.ts: returns{ waiting: true }; a node without a request throwsPermanentNodeExecutionError('decision_request_missing')instead of parking a run nobody can resolve. First classified error in the worker.engines/temporal/worker.ts: registry entryai-studio/human-decision.apps/ai-studio/src/nodes/human-decision/schema.ts:sharedProperties+decisionRequest: { type: 'object', properties: {} },required: ['decisionRequest'].uischema.ts: title only(follow-up: decision-request-properties-ui).default-properties-data.ts: preset request, version 1,approve->source:inner:approved(resume),reject->source:inner:rejected(reject,reasonRequired: false), empty form. Ports come fromgetHandleId.index.ts: palette itemai-studio/human-decision, iconUserCheck,outputSchemawithactionandeffectfor the variable picker;humanDecisionNodeTypeshared withapp.tsx.human-decision-template.tsx+ CSS: own template viadefineNodeTemplate, registered under the palette type innodeTemplatesonWorkflowBuilder.Root. One source handle per action that carries a port,id= port; one target handle; rows inNodeSectioninsideOptionalNodeContent, where the execution markers mount. HonourslayoutDirection. Palette preview renders the header only. Malformed or missing request: header and target handle, no source handles.apps/ai-studio/src/stores/use-execution-store.ts: node statuswaitingfromnode_waiting. Run status derived:waitingwhile any node waits,runningonce the last resolves, terminal events win. Same rule on the live path and on the snapshot after a reload (the engine's status write is advisory and may be skipped).components/execution/node-markers.tsx:HourglassMediumforwaiting, not clickable.highlighting.tsx:waitingkeeps the active shadow.controls/ai-studio-controls.tsx:waitingcounts as running, so a parked run shows Stop.highlighting.css/log-panel.module.css:--ai-studio-status-color--waitingfrom--ax-txt-info-default, badgenode_waiting, status pillwaiting.apps/ai-studio/src/data/refund-review-flow.ts: template id 306, iconReceipt. trigger -> AI "Draft the Refund Reply" -> "Review Refund" ->approved-> AI "Send the Confirmation" -> visualize (markdown);rejected-> visualize (json). The node's request adds the refund form:refundAmount(number, required),orderDate(read-only),note. Both edges drawn, exactly one predecessor.Decisions worth a look
DecisionNodetemplate: no "Add branch" placeholder, nodecisionBranches, the port is written once, in the request. Handle ids keep the SDK shapesource:inner:<action>so edge z-index and id helpers stay on their known path.node_not_waitingfor such a node.applySnapshotuses the same rule asapplyEvent.incomplete(WB-499 is next).Known gaps, unchanged on purpose
curl. Panel is a separate task (WB-502 and its designed successor).(follow-up: decision-request-properties-ui).Notes for the reviewer
properties: {}on the request field (NodeSchemarequires it), the preset shape pinned directly instead of importing the backend zod schema (AI Studio has no zod), own action rows becauseConnectableItemis not a public SDK export.