microsoft / microsoft/TypeAgent
Reasoning Action needs user confirmation for tool calls like CoPilot/Claude
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 740
- Forks
- 106
- Avg merge
- 1d 6h
- Merged PRs (30d)
- 84
Description
Problem
The dispatcher's Reasoning Action (the ReasoningAction fallback that routes complex requests into an LLM reasoning loop) executes tool calls without asking the user for confirmation. Both reasoning adapters auto-approve every tool call:
- Claude:
canUseTool: async () => ({ behavior: "allow" })+permissionMode: "acceptEdits"—packages/dispatcher/dispatcher/src/reasoning/claude.ts(~L584-586) - Copilot:
onPermissionRequest: approveAll—packages/dispatcher/dispatcher/src/reasoning/copilot.ts(L15 import, L647) - Shared adapter:
canUseTool: async () => ({ behavior: "allow" })—packages/dispatcher/dispatcher/src/reasoning/claudeSDKAdapter.ts(~L155)
The reasoning loop exposes tools including execute_action (runs real, side-effecting dispatcher actions), discover_actions, search_memory, and remember. Because approval is hard-wired to allow-all, the loop can perform side-effecting actions (send email, modify lists, browser automation, etc.) with no human in the loop.
Desired behavior
Before executing a side-effecting reasoning tool call, prompt the user to confirm — the same UX GitHub Copilot and Claude use ("Allow / Deny", ideally with "Allow always for this tool/session"):
- Show the tool name and a human-readable summary of the arguments (e.g., which action + parameters
execute_actionis about to run). - Offer Allow once / Deny / Allow for session.
- Deny aborts that tool call and feeds the denial back into the loop so the model can adapt.
- Read-only tools (
discover_actions,search_memory) may run without a prompt; side-effecting tools (execute_action,remember, browser actions) prompt by default.
Suggested approach (implementation notes)
- Reuse
SessionContext.popupQuestion(message, choices, defaultId)(packages/dispatcher/dispatcher/src/execute/sessionContext.ts~L222) — it already round-trips to the Shell/CLI/RPCclientIO. - Add an SDK-agnostic gating hook to
ReasoningLoopConfig(packages/dispatcher/dispatcher/src/reasoning/reasoningLoopBase.ts), e.g.onToolApproval?(tool, args): Promise<"allow" | "deny" | "allow_always">. The base already has informationalonToolCall/onToolResultcallbacks (L31-32); this adds a gating counterpart. - Wire real permission callbacks in both adapters instead of allow-all:
- Copilot: replace
onPermissionRequest: approveAll—copilot.tsL647. - Claude: replace the
canUseToolallow-all —claude.ts~L586 andclaudeSDKAdapter.ts~L155.
- Copilot: replace
- Follow the workflow engine's secure-by-default
ApprovalFnprecedent (examples/workflow/model/src/taskDefinition.ts~L175,examples/workflow/engine/src/runner.ts; design docdocs/architecture/workflows/engineering/task-policy-temp.md). - Add a policy/toggle under the existing
reasoningconfig (config.defaults.yaml~L14):prompt(default) /allow/ per-tool, plus an "allow all" escape hatch for headless runs (mirrors the workflow CLI--allow-all/--dry-run).
The auto-approve posture is already documented as deliberately temporary in
docs/architecture/workflows/ir/decisions/0010-copilot-task-family.md§7, which points toward a capability-based permission model.
Acceptance criteria
- Side-effecting reasoning tool calls prompt for confirmation before executing (Copilot + Claude adapters).
- The prompt shows the tool name + summarized args.
- Allow / Deny / Allow-for-session work; Deny aborts the call and the loop continues gracefully.
- Read-only tools do not prompt (configurable).
- A config/flag can auto-approve all for headless/automated scenarios, off by default.
- Works across Shell, CLI, and RPC clients via
popupQuestion/clientIO.
Out of scope
- Full capability-based security model (tracked separately per decision 0010 §7).
- Per-agent permission policies beyond the reasoning loop.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with ReasoningLoopConfig in packages/dispatcher/dispatcher/src/reasoning/reasoningLoopBase.ts and SessionContext.popupQuestion in packages/dispatcher/dispatcher/src/execute/sessionContext.ts, then trace the permission callbacks in reasoning/copilot.ts, reasoning/claude.ts, and reasoning/claudeSDKAdapter.ts. Compare the workflow engine's ApprovalFn precedent and existing reasoning configuration before making the change. Done means side-effecting tools prompt through Shell, CLI, and RPC clients, read-only tools remain unprompted, denial continues the loop, and headless auto-approval is opt-in.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- authorization, security
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100