Skip to content

fix(approval): evaluate require_approval predicates on schema-parsed arguments - #31

Merged
alexb-openrouter merged 4 commits into
mainfrom
devin/1794512255-approval-parsed-args
Nov 12, 2026
Merged

alexb-openrouter merged 4 commits into
mainfrom
devin/1794512255-approval-parsed-args

Conversation

@alexb-openrouter

@alexb-openrouter alexb-openrouter commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Callable require_approval predicates and call-level approval checks received the raw model arguments, while execute received the arguments after input_schema validation. A coerced or defaulted value could pass a strict predicate and then run as the dangerous value without approval (for example the string "true" failing args["force"] is True and then executing as True).

  • tool_requires_approval now parses arguments with the tool's input_schema first (_parse_tool_arguments). Tool-level predicates get the parsed mapping; arguments that fail parsing or don't produce a mapping require approval. Call-level checks get a copy of the call with parsed arguments. This is the approval part of tool_requires_approval from port: sync with @openrouter/agent upstream (EVAL FAILED — do not merge) #29.
  • Regression cases from the upstream approval-gate suite in tests/unit/test_approval_predicate_parsed_args.py (defaults, coercion, call-level checks, invalid and non-object arguments).
  • Release as 0.8.1, a downstream-only patch on the 0.8.0 port. Upstream never published 0.8.1, so the publish guard maps it explicitly to the @openrouter/agent@0.8.0 tag for its tag and ahead-of-tag checks. Changelog entry added.

Not included: re-checking approval after a PreToolUse hook rewrites arguments (depends on the larger model_result.py rewrite in #29).

Tests: pytest tests/unit (132 passed), ruff check, ruff format --check, mypy src tests, uv lock --check.

alexb-openrouter and others added 2 commits November 12, 2026 19:17
…arguments

Callable require_approval predicates and call-level approval checks
received the raw model arguments, while execute received the arguments
after input_schema validation. Coercions and defaults could therefore
make a strict predicate allow a call whose executed input needed
approval.

Parse arguments with the tool's input_schema before the approval check
and pass the parsed mapping to tool-level predicates. Call-level checks
get a copy of the call with parsed arguments. Arguments that fail
parsing, or parse to a non-mapping value, require approval.

Ported from the upstream approval-gate regression suite.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Bump to the PEP 440 post-release 0.8.0.post1: the tree is still the
0.8.0 port plus a downstream-only fix, so the publish guard now resolves
X.Y.Z.postN to the upstream X.Y.Z release tag.
@devin-ai-integration

devin-ai-integration Bot commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

I'll fix CI failures and address comments from users with write access that start with 'Devin'.

  • Disable automatic comment, CI, and merge conflict monitoring

Use an integer patch version for the downstream-only fix. The publish guard maps
0.8.1 explicitly to the @openrouter/agent@0.8.0 tag it is ported from, since
upstream never released 0.8.1.

@devin-ai-integration devin-ai-integration 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.

Verdict: no blockers. Posting as COMMENT, not APPROVE, because the code was written by the same automation that is reviewing it; a human reviewer should approve.
Estimated impact: medium. Changes which calls need human approval and the release gate; failure modes fail closed (extra approval prompts) rather than open.
Risk: implementation low, premise low, impact medium.

Checked: _parse_tool_arguments uses the same validate_schema(input_schema, arguments) call as execute_regular_tool, so predicates see the values execute receives (model_dump() of the same model). The only approval entry point is tool_requires_approval via partition_tool_calls; _classify already routes raw-string arguments to approval. The publish case only maps 0.8.1; every other version still needs its own upstream tag, and the ahead-of-tag check still runs against @openrouter/agent@0.8.0.

Comment thread .github/workflows/publish.yaml Resolved
@alexb-openrouter
alexb-openrouter merged commit 438b88f into main Nov 12, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants