[mirror] Upstream/pr1 on plan ready#1
Conversation
Adds an optional callback that fires after the coordinator decomposes
a goal into tasks but before execution begins.
const orchestrator = new OpenMultiAgent({
onPlanReady: async (tasks) => {
displayPlan(tasks)
return await confirm('Proceed?')
},
})
Returning false aborts the run immediately (returns success: false with
empty agentResults). Only fires for runTeam(); runAgent() and runTasks()
are unaffected.
⚡ Risk Assessment —
|
| Files | Summary |
|---|---|
Plan Ready Callback Integrationsrc/orchestrator/orchestrator.tssrc/types.ts |
Introduces onPlanReady callback to OrchestratorConfig, enabling plan approval before task execution. Callback receives decomposed task list and can abort execution if approval denied. |
Sequence Diagram
sequenceDiagram
participant Caller
participant OpenMultiAgent
participant Coordinator
participant onPlanReady
participant TaskQueue
Caller->>OpenMultiAgent: runTeam(goal)
OpenMultiAgent->>Coordinator: decompose goal
Coordinator->>TaskQueue: create tasks
OpenMultiAgent->>onPlanReady: invoke with task list
alt Callback returns false
onPlanReady-->>OpenMultiAgent: false
OpenMultiAgent-->>Caller: {success: false, empty results}
else Callback returns true or undefined
onPlanReady-->>OpenMultiAgent: true
OpenMultiAgent->>TaskQueue: executeQueue
TaskQueue-->>OpenMultiAgent: execution complete
OpenMultiAgent-->>Caller: {success: true, results}
end
Dig Deeper With Commands
/review <file-path> <function-optional>/chat <file-path> "<question>"/roast <file-path>
Runs only when explicitly triggered.
| return { | ||
| success: false, | ||
| agentResults: new Map(), | ||
| totalTokenUsage: { input_tokens: 0, output_tokens: 0 }, |
There was a problem hiding this comment.
Plan-rejection path silently zeros out coordinator decomposition tokens
When onPlanReady returns false, runTeam returns hardcoded zero token usage and a fresh empty agentResults Map, but by that point the coordinator decomposition has already run and its tokens are sitting in cumulativeUsage (and its result in agentResults under 'coordinator:decompose'). Billing/observability will under-report real spend on every rejected plan.
Return the live cumulativeUsage and the existing agentResults Map (or call buildTeamRunResult with success:false) so the decomposition spend isn't lost.
| } | ||
|
|
||
| if (this.config.onPlanReady) { | ||
| const tasks = queue.list() |
There was a problem hiding this comment.
onPlanReady call isn't wrapped in try/catch like its sibling onApproval
The existing onApproval callback in this file is invoked inside a try/catch that defaults to a safe approved=false on throw. onPlanReady is called bare — a thrown error from user code will propagate out of runTeam, leaving the already-spent coordinator tokens unaccounted and skipping any cleanup the caller expected. Worth matching the existing pattern.
Mirror the onApproval pattern: try/catch around the await, default approved=false on throw (or rethrow with context), so a buggy host callback can't tear down the run mid-flight.
Actionable Comments Posted: 2🧹 Nitpick comments (1)onPlanReady accepts mutable Task[] while sibling onApproval is readonly - src/types.ts (645, 653)🧾 Coverage Summary✔️ Covered (2 files) |
Mirror of upstream open-multi-agent#181 (open PR live findings) for benchmark. Do not merge.
Summary by MergeMonkey