anomalyco / anomalyco/opencode

[FEATURE]: Show why an agent needs a permission before the user approves it

Open
#47,889 0 comments 0 reactions 1 assignee View on GitHub

@rekram1-node is already working on this.

Since Sep 8, 2026.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
Avg merge
7h 2m
Merged PRs (30d)
384

Description

Problem

Permission prompts show the requested operation or scope, but generally lack an explicit explanation of why it is needed for the current task. Existing tool-specific metadata and task descriptions do not provide a consistent requester-to-user explanation across clients.

For example, access to ~/.config/example/* identifies the resource but leaves the user to infer why the agent needs it and how it relates to their request. This becomes harder during longer workflows and subagent operations.

Requested enhancement

Allow requesters to attach an optional human-readable reason to permission requests and display it before approval, alongside the authoritative command, path, or scope.

Run command: npm test

Reason:
Run the project tests to verify the requested change.

Allow once / Allow always / Reject
Access external directory: ~/.config/example/*

Reason:
Read the existing provider configuration before updating
the setting requested by the user.

Allow once / Allow always / Reject

When no reason is supplied, existing behavior should remain unchanged.

Implementation considerations

Source inspection at commit ecbc6ccac85b3e8087b6445e584318419b9e2b34 found both legacy PermissionV1.Request requests and Core V2 requests, whose canonical schema is Permission.Request in packages/schema/src/permission.ts and which Core exposes as PermissionV2.Request.

The value should survive request construction, events, pending-request APIs, generated clients, and client compatibility conversions. In particular, the browser application converts both V2 live events and pending-list responses into legacy-shaped requests; both paths need to preserve the explanation.

Custom tools could supply the field through ToolContext.ask. Core tools use PermissionV2.Service.assert. Supporting ordinary agent-generated reasons also requires an explicit way for selected tools to receive task-specific intent: adding a transport field alone will not make tools populate it.

A possible legacy custom-tool API shape, after adding the optional field, is:

await ctx.ask({
  permission: "external_directory",
  patterns: ["~/.config/example/*"],
  always: ["~/.config/example/*"],
  metadata: {},
  reason:
    "Read the existing provider configuration before updating the requested setting.",
})

The exact implementation is up to the maintainers. A first-class optional field would give clients a consistent contract rather than requiring them to infer intent or agree on an undocumented metadata key.

Acceptance criteria

  • Requests may omit the reason without changing existing behavior.
  • Supplied reasons survive both live events and pending-request retrieval.
  • Generated API/SDK contracts expose the optional field.
  • TUI and the shared Desktop/browser permission UI display the reason alongside the actual permission scope.
  • Requesters can provide short, task-specific explanations; the UI does not invent generic reasons.
  • Reasons remain untrusted explanatory text and do not affect matching, approval, denial, automatic-response decisions, or saved scope.
  • Tests cover propagation, absence, rendering, and unchanged authorization behavior.

Security considerations

The actual command, path, permission type, and scope must remain visible and authoritative.

A reason must not bypass permission rules, override denial, automatically approve an operation, broaden access, or hide or replace the actual operation. It is an explanation from the requester, not evidence that the action is safe.

Related work

#37164 requests native permission creation from tool.execute.before, including plugin-computed explanations. This proposal concerns explanation transport and display for permission requests generally; the two could share the same field and UI without making plugin-hook permission creation a prerequisite.

Human approval/rejection feedback is a separate, opposite-direction flow:

  • This proposal: agent/tool → explanation → human, before authorization.
  • Rejection feedback: human → explanation → agent, after deciding.

The goal is to help the user understand both what is requested and why it is needed before making the permission decision.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.