Skip to content

fix(agent): refuse a single-record action given several records [PRD-1704] - #337

Open
hercemer42 wants to merge 3 commits into
mainfrom
feature/prd-1704-a-single-record-action-given-several-records-runs-on-the
Open

hercemer42 wants to merge 3 commits into
mainfrom
feature/prd-1704-a-single-record-action-given-several-records-runs-on-the

Conversation

@hercemer42

@hercemer42 hercemer42 commented Oct 21, 2026 •

Copy link
Copy Markdown

A single-record action triggered on several record ids now answers 422 ("This action can only be triggered on one record at a time.") instead of running on the first record and answering success. Same fix as the Node agent (ForestAdmin/agent-nodejs#2028) and the Ruby agent (ForestAdmin/agent-ruby#417).

Refs: PRD-1704

What changes

  1. A single-record action on two or more ids. Before: the action ran on the first record only (ActionContextSingle.get_record returns records[0]) and answered success, so the other records were skipped and nobody was told. After: 422, and nothing runs.
  2. The same request on an action that requires approval. Before: the agent asked for an approval, which later ran on the first record only. After: 422 at submit time, before the permission check, so no approval is asked for. Approving a request already stored with several ids answers 422 too.
  3. A single-record action on a select-all selection. Before: it ran on whichever record came first. After: 422. The UI already disables single-record actions on a select-all, so it never sends this.
  4. Loading a single-record action's form with several ids (/hooks/load, /hooks/change, /hooks/search). Before: the form loaded against the first record. After: 422.

A single-record action on exactly one id, and bulk and global actions, behave as before; a test now pins the one-id case.

Squash message

fix(agent): refuse a single-record action given several records [PRD-1704]

A single-record action triggered on several record ids ran on the first
record only and answered success, skipping the others silently; approving
an approval request naming several ids did the same.

The action resource now answers 422 for a single-record action whose
selection names more than one id or is a select-all, before the
permission check, on execute and on the form hooks alike.

🤖 Generated with Claude Code

Note

Refuse multi-record selections on SINGLE-scope actions in ActionResource

ActionResource._get_records_selection now validates the record selection for SINGLE-scope actions and raises UnprocessableError unless exactly one ID is selected. This rejects empty selections, multi-ID selections, select-all selections, and selections with excluded IDs, before permission checks and form computation. Signed approval data with multiple IDs is also rejected. Adds a full test fixture in test_resources.py covering rejection cases and the single-ID success path.

  • Behavioral Change: SINGLE-scope action requests that previously accepted multiple records or select-all now fail with UnprocessableError in src/agent_toolkit/forestadmin/agent_toolkit/resources/actions/resources.py

Macroscope summarized b394193.

…1704]

A single-record action triggered on several ids ran on the first record
only and answered success, since ActionContextSingle.get_record reads the
first record. An API client, an MCP call or an approval request could send
such a selection, and every record past the first was silently skipped.

The action resource now answers 422 for a single-record action whose
selection names more than one id or is a select-all, before the
permission check: no approval is asked for, approving a stored request
runs nothing, and the form hooks refuse it too. Same fix as the Node
agent (ForestAdmin/agent-nodejs#2028).

Refs: PRD-1704

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@linear-code

linear-code Bot commented Oct 21, 2026

Copy link
Copy Markdown

PRD-1704

@hercemer42 hercemer42 left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Spec (PRD-1704): conforms.

from forestadmin.agent_toolkit.utils.id import unpack_id
from forestadmin.datasource_toolkit.decorators.action.result_builder import ResultBuilder
from forestadmin.datasource_toolkit.exceptions import BusinessError
from forestadmin.datasource_toolkit.exceptions import BusinessError, UnprocessableError

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Claude Opus 5.5 (claude-opus-5-5): There is additional feedback on https://linear.app/forestadmin/issue/PRD-1704, so please read it before merging.

hercemer42 and others added 2 commits October 21, 2026 18:35
An empty selection leaves the action's filter unrestricted, so a
single-record action sent `ids: []` ran on whichever record it read
first. The single-record guard now refuses anything but exactly one id.

Refs: PRD-1704

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs: PRD-1704

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant