Skip to content

fix(code): authorize Auto actions from ask_user selections - #4946

Closed
Mason Daugherty (mdrxy) wants to merge 4 commits into
mainfrom
mdrxy/code/ask-user-authorization
Closed

fix(code): authorize Auto actions from ask_user selections#4946
Mason Daugherty (mdrxy) wants to merge 4 commits into
mainfrom
mdrxy/code/ask-user-authorization

Conversation

@mdrxy

Copy link
Copy Markdown
Member

In Auto mode, answering an ask_user prompt now authorizes the exact action the user selected, so the agent no longer stalls asking the user to retype a choice they just made.


Auto mode's action classifier previously accepted only literal chat-input text as evidence of user consent. A selection made through an ask_user prompt became an ordinary tool result, which the classifier is required to treat as untrusted context. As a result, after the user picked an option such as "Rebase my new local commit onto the remote branch, then push," the follow-up action was still denied and the agent looped back asking the user to explicitly re-authorize the same command.

When the user answers an ask_user prompt, dcode now records a server-owned authorization receipt bound to the current thread, turn, and originating tool call. The classifier admits these validated same-turn answers as consent evidence, resolving references such as "run it" or a selected option without requiring the user to restate the command.

The grant is deliberately narrow:

  • Only answers recorded by dcode for the current turn count; model- or tool-authored text cannot forge one, and the model-authored question is never treated as consent.
  • Receipts are bound to the LangGraph execution thread, the active turn, and the exact ask_user call, so stale, cross-turn, cross-thread, duplicated, or replayed receipts are ignored.
  • An answer authorizes only the action and target it names. Chained or broader operations, riskier variants (for example, force-push when the user approved a normal push), and destructive escalations still require their own explicit authorization.
  • Cancelled, errored, or malformed responses record no receipt.

@github-actions github-actions Bot added dcode Related to `deepagents-code` feature New feature/enhancement or request for one internal User is a member of the `langchain-ai` GitHub organization size: L 500-999 LOC labels Jul 22, 2026
@mdrxy Mason Daugherty (mdrxy) changed the title feat(code): authorize Auto actions from ask_user selections fix(code): authorize Auto actions from ask_user selections Jul 22, 2026
@github-actions github-actions Bot added fix A bug fix (PATCH) and removed feature New feature/enhancement or request for one labels Jul 22, 2026

@open-swe open-swe Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Open SWE Review: No issues found

Open SWE reviewed this PR and found no potential bugs to report.

Open in WebView Open SWE trace

@mdrxy

Copy link
Copy Markdown
Member Author

Superseded by #4993.

The replacement carries forward this PR's server-owned, same-turn ask_user authorization receipts and combines them with #4947's deterministic handling of built-in conversation compaction. The combined PR makes the Auto-mode decision order explicit while keeping verified prior consent separate from operations that intrinsically require no approval.

Closing this PR in favor of #4993.

Mason Daugherty (mdrxy) added a commit that referenced this pull request Jul 23, 2026
Supersedes #4946
Supersedes #4947

Auto mode no longer interrupts users when an action is already covered
by their explicit `ask_user` selection or when the agent is performing
the built-in conversation-compaction operation.

---

Previously, Auto mode could ask users to approve an action immediately
after they selected it in an `ask_user` prompt. It could also pause
autonomous work to approve `compact_conversation`, even though
compaction is an internal maintenance operation without an externally
consequential effect.

The two cases now follow separate trust rules:
- Server-created, same-turn receipts allow the authorization classifier
to consider only the user's selected answer for the exact subsequent
action. The receipt is bound to the LangGraph execution thread, the
active turn, and the originating `ask_user` tool call, and is validated
against the full checkpoint history so it survives conversation
compaction. Only the latest `ask_user` exchange in the turn is admitted;
model-authored questions, unselected choices, and prior answers are
excluded. Invalid, stale, ambiguous, or overly broad consent continues
through the normal approval path.
- The trusted built-in `compact_conversation` operation is
deterministically allowed without classifier or human review. The
exemption is guarded by exact tool-object identity, not by name, so a
caller-supplied tool with the same name cannot exploit it. At most one
trusted compaction call is allowed per action batch; duplicates are
denied without classifier review, and that denial is preserved across
all fallback paths.

<details>
<summary>Test plan</summary>

Targeted Auto-mode, ask_user, agent-wiring, and Textual-adapter tests:

```
uv run --group test pytest tests/unit_tests/test_ask_user_middleware.py \
  tests/unit_tests/test_auto_mode.py \
  tests/unit_tests/tui/test_textual_adapter.py::TestExecuteTaskTextualTurnMarkers \
  tests/unit_tests/test_agent.py::test_cli_context_schema_fields_mirror_typed_dict \
  tests/unit_tests/test_agent.py::TestCreateCliAgentInterpreterWiring \
  --disable-socket --allow-unix-socket --benchmark-disable -q
```
Result: 135 passed.

Full package unit tests:

```
make test
```
Result: 10617 passed, 4 skipped, 6 pre-existing failures in
`TestLangsmithSecretRedaction` (env-dependent, fail on clean
`origin/main`).

Lint, format, type check, and commands catalog:

```
make lint
```
Result: All checks passed.

A real LangGraph interrupt/resume test
(`test_real_agent_resume_forwards_ask_user_receipt_to_classifier`)
verifies the full path: `ask_user` interrupt → checkpoint resume →
receipt minting with real `execution_info.thread_id` → classifier sees
`same_turn_user_answers` → action executes without a second HITL prompt.

A compiled-graph identity test
(`test_compiled_agent_preserves_canonical_compaction_tool_identity`)
verifies the canonical `CLICompactionMiddleware` tool object survives
`create_deep_agent`'s middleware merge into the compiled `ToolNode`, and
that `AutoModeHITLMiddleware._trusted_compaction_tool` references that
same object.

The 6 `TestLangsmithSecretRedaction` failures are pre-existing and
env-dependent (real LangSmith credentials in the local environment);
they fail identically on clean `origin/main` and are unrelated to this
change.

</details>
Marcelo5444 pushed a commit to Marcelo5444/deepagents that referenced this pull request Jul 30, 2026
Supersedes langchain-ai#4946
Supersedes langchain-ai#4947

Auto mode no longer interrupts users when an action is already covered
by their explicit `ask_user` selection or when the agent is performing
the built-in conversation-compaction operation.

---

Previously, Auto mode could ask users to approve an action immediately
after they selected it in an `ask_user` prompt. It could also pause
autonomous work to approve `compact_conversation`, even though
compaction is an internal maintenance operation without an externally
consequential effect.

The two cases now follow separate trust rules:
- Server-created, same-turn receipts allow the authorization classifier
to consider only the user's selected answer for the exact subsequent
action. The receipt is bound to the LangGraph execution thread, the
active turn, and the originating `ask_user` tool call, and is validated
against the full checkpoint history so it survives conversation
compaction. Only the latest `ask_user` exchange in the turn is admitted;
model-authored questions, unselected choices, and prior answers are
excluded. Invalid, stale, ambiguous, or overly broad consent continues
through the normal approval path.
- The trusted built-in `compact_conversation` operation is
deterministically allowed without classifier or human review. The
exemption is guarded by exact tool-object identity, not by name, so a
caller-supplied tool with the same name cannot exploit it. At most one
trusted compaction call is allowed per action batch; duplicates are
denied without classifier review, and that denial is preserved across
all fallback paths.

<details>
<summary>Test plan</summary>

Targeted Auto-mode, ask_user, agent-wiring, and Textual-adapter tests:

```
uv run --group test pytest tests/unit_tests/test_ask_user_middleware.py \
  tests/unit_tests/test_auto_mode.py \
  tests/unit_tests/tui/test_textual_adapter.py::TestExecuteTaskTextualTurnMarkers \
  tests/unit_tests/test_agent.py::test_cli_context_schema_fields_mirror_typed_dict \
  tests/unit_tests/test_agent.py::TestCreateCliAgentInterpreterWiring \
  --disable-socket --allow-unix-socket --benchmark-disable -q
```
Result: 135 passed.

Full package unit tests:

```
make test
```
Result: 10617 passed, 4 skipped, 6 pre-existing failures in
`TestLangsmithSecretRedaction` (env-dependent, fail on clean
`origin/main`).

Lint, format, type check, and commands catalog:

```
make lint
```
Result: All checks passed.

A real LangGraph interrupt/resume test
(`test_real_agent_resume_forwards_ask_user_receipt_to_classifier`)
verifies the full path: `ask_user` interrupt → checkpoint resume →
receipt minting with real `execution_info.thread_id` → classifier sees
`same_turn_user_answers` → action executes without a second HITL prompt.

A compiled-graph identity test
(`test_compiled_agent_preserves_canonical_compaction_tool_identity`)
verifies the canonical `CLICompactionMiddleware` tool object survives
`create_deep_agent`'s middleware merge into the compiled `ToolNode`, and
that `AutoModeHITLMiddleware._trusted_compaction_tool` references that
same object.

The 6 `TestLangsmithSecretRedaction` failures are pre-existing and
env-dependent (real LangSmith credentials in the local environment);
they fail identically on clean `origin/main` and are unrelated to this
change.

</details>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dcode Related to `deepagents-code` fix A bug fix (PATCH) internal User is a member of the `langchain-ai` GitHub organization size: L 500-999 LOC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant