feat(flows): Workflows B4 — agent proposes a workflow#4472
Conversation
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (27)
📝 WalkthroughWalkthroughAdds an agent-facing ChangesBackend propose_workflow tool
Frontend workflow proposal UI
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant Agent
participant ProposeWorkflowTool
participant ChatRuntimeProvider
participant ReduxStore
participant WorkflowProposalCard
participant createFlow
Agent->>ProposeWorkflowTool: propose_workflow(name, graph, require_approval)
ProposeWorkflowTool-->>Agent: workflow_proposal JSON
ChatRuntimeProvider->>ChatRuntimeProvider: parseWorkflowProposal(output)
ChatRuntimeProvider->>ReduxStore: dispatch setWorkflowProposalForThread
ReduxStore-->>WorkflowProposalCard: pendingWorkflowProposal
WorkflowProposalCard->>WorkflowProposalCard: render trigger/steps
WorkflowProposalCard->>createFlow: createFlow(name, graph, requireApproval) [on Save]
createFlow-->>WorkflowProposalCard: Flow or error
WorkflowProposalCard->>ReduxStore: dispatch clearWorkflowProposalForThread
Possibly related PRs
Suggested labels: Suggested reviewers: Poem
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1c9a944528
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| // action ever calls `flows_create`, so this dispatch alone can never | ||
| // create a flow. | ||
| if (event.tool_name === 'propose_workflow' && event.success) { | ||
| const proposal = parseWorkflowProposal(event.output); |
There was a problem hiding this comment.
Wire workflow proposals from actual tool output
In the normal web-chat path, tool_result events do not contain the tool's returned body: progress_bridge.rs publishes output as only {"output_chars":...,"elapsed_ms":...} for AgentProgress::ToolCallCompleted. Therefore a successful propose_workflow call will parse that placeholder here, fail the type === 'workflow_proposal' check, and never dispatch setWorkflowProposalForThread, so the Save/Dismiss card is never shown. Please either include this tool's actual result in the socket event or source the proposal from another captured outcome.
Useful? React with 👍 / 👎.
| setSaving(true); | ||
| setErrorMsg(null); | ||
| try { | ||
| await createFlow(proposal.name, proposal.graph, proposal.requireApproval); |
There was a problem hiding this comment.
Force approval on agent-proposed flows
When the agent includes require_approval: false, the parser stores requireApproval: false and this save path forwards it unchanged to flows_create. The approval gate treats workflow runs with require_approval: false as trusted and allows predeclared external actions without prompting, while the card only shows a message when approval is true. A prompt-injected proposal can therefore become an enabled flow whose future outbound tool/HTTP steps skip HITL after a generic Save click; force agent-authored proposals to true or make the no-approval state explicit and separately confirmed.
Useful? React with 👍 / 👎.
…card) Talk → workflow. A new propose_workflow agent tool lets the assistant draft a WorkflowGraph; it VALIDATES the graph (validate_and_migrate_graph, the same path flows_create uses) and returns a summary — it never persists. The chat renders a WorkflowProposalCard; the user's Save (and only that) calls flows_create. Backend: flows/tools.rs ProposeWorkflowTool (permission None, external_effect false; validate-or-error so the agent self-corrects) + tools_tests.rs (15); validate_and_migrate_graph made pub(crate); registered in tools/ops.rs. Frontend: WorkflowProposalCard.tsx (+test); flowsApi.createFlow + Flow type; chatRuntimeSlice pendingWorkflowProposalsByThread + reducers; ChatRuntimeProvider onToolResult → dispatch when tool_name==propose_workflow (persists past turn-end); Conversations.tsx renders it; toolTimelineFormatting label; i18n chat.flowProposal.* x14 locales (distinct namespace, no B3b/B5a conflict). Human-in-the-loop invariant: no agent/tool path reaches flows_create. Rust: 15 tool + 271 flows tests pass, tool live in registry. Frontend: typecheck/ lint/prettier clean, card 8 + runtime 157 tests pass, i18n parity clean.
1c9a944 to
d5b2fe9
Compare
Summary
Talk → workflow. A new
propose_workflowagent tool lets the assistant draft aWorkflowGraph; it validates the graph (the samevalidate_and_migrate_graphpathflows_createuses) and returns a summary — it never persists. The chat renders a WorkflowProposalCard; the user's Save (and only that) callsflows_create.Backend
flows/tools.rs—ProposeWorkflowTool(permission_level None,external_effect false; validate-or-error so the agent self-corrects) + 15 tests.validate_and_migrate_graphmadepub(crate); registered intools/ops.rs.Frontend
WorkflowProposalCard.tsx(+test) — name/trigger/step-badges + Save/Dismiss.flowsApi.createFlow+Flowtype;chatRuntimeSlicependingWorkflowProposalsByThread+ reducers;ChatRuntimeProvideronToolResult→ dispatch whentool_name==propose_workflow(persists past turn-end, not a blocking gate);Conversations.tsxrenders it; i18nchat.flowProposal.*× 14 (distinct namespace — no B3b/B5a conflict).Human-in-the-loop invariant
No agent/tool code path reaches
flows_create— creation is exclusively the user's Save click. Asserted by the tool'spermission_level None/external_effect falsetests.Notes
tinyflows 0.3validateonly checks structural invariants (unique ids, one trigger, valid edges) — so the tool description carries the per-kind config guidance for the LLM.Verification
Rust: 15 tool + 271 flows tests pass, tool live in registry. Frontend: typecheck/lint/prettier clean, 8 card + 157 runtime tests pass, i18n parity clean.
Summary by CodeRabbit
New Features
Bug Fixes
Documentation