Skip to content

fix(workflow-executor): read composite-key records via the agent by-id route [PRD-450]#1629

Open
matthv wants to merge 1 commit into
feat/prd-214-server-step-mapperfrom
fix/prd-450-executor-composite-pk-by-id
Open

fix(workflow-executor): read composite-key records via the agent by-id route [PRD-450]#1629
matthv wants to merge 1 commit into
feat/prd-214-server-step-mapperfrom
fix/prd-450-executor-composite-pk-by-id

Conversation

@matthv
Copy link
Copy Markdown
Member

@matthv matthv commented Jun 5, 2026

Problem

On collections with a composite primary key, the workflow executor failed to read records in orchestrator mode with Record not found.

getRecord built the agent filter by zipping two arrays by position:

  • primaryKeyFields — from the orchestrator collection-schema, in alphabetical order (the agent apimap sorts fields alphabetically; is_primary_key is just a boolean, no ordinal);
  • recordId — in model primary_key order.

For a PK whose model order ≠ alphabetical (e.g. Shipping = [order_id, customer_id]), the columns got mis-paired → no match → not found. The executor has no way to recover the real PK order from the schema it receives.

Fix

Stop re-pairing the id in the executor. Read by id through the agent's by-id route (like update/delete already do) and let the agent — the only party that knows the PK column order — do the matching. The recordId is an opaque ordered token; the executor never needs to know the key composition.

  • add Collection#getOne(id, options) to @forestadmin/agent-client (handles 404 / empty as "not found");
  • rewrite getRecord to use it; remove buildPkFilter / resolveSchema;
  • same reasoning for getRelatedData composite recordIds — use the agent's opaque row.id instead of rebuilding from primaryKeyFields.

Coupling

For v1 agents the by-id read needs the agent to accept the pipe-joined id form — forest_liana: ForestAdmin/forest-rails#774 ; forest-express: pending. v2 already supports it.

Testing

  • agent-client-agent-port.test.ts updated (getRecord/getSingleRelatedData now exercise getOne; composite getRelatedData uses the opaque id). Full suite: 887 passing, lint clean.
  • Validated end-to-end: composite-key Shipping workflow (get-data → condition → update-data) reads + updates the record in orchestrator mode.

Relates to PRD-450. The agent-side id-format fix is tracked separately (see PRD-450).

🤖 Generated with Claude Code

Note

Fix composite-key record fetching in workflow executor to use agent by-id route

  • Adds Collection.getOne(id, options?) in collection.ts that fetches a single record via GET /forest/<collection>/<id>, returning null on 404 or empty response.
  • Replaces the list-based lookup in AgentClientAgentPort.getRecord with a direct call to getOne, removing dependency on schema primary key ordering and filter construction.
  • For composite primary keys in getRelatedData, derives the record id by splitting the agent's packed row.id on | instead of mapping from schema-declared field order, fixing key order mismatches.
  • Removes buildPkFilter, resolveSchema, and related imports that are no longer needed.

🖇️ Linked Issues

Addresses PRD-450.

Macroscope summarized 06eff38.

…d route [PRD-450]

getRecord built the agent filter by zipping primaryKeyFields (alphabetical, from
the orchestrator collection-schema) with the recordId (model primary_key order).
For composite PKs whose model order differs from alphabetical this mis-paired the
columns, so the record was never found ("Record not found").

Fetch by id through the agent's by-id route instead (like update/delete): the
recordId is an opaque ordered token and the agent — the only party that knows the
primary key column order — does the matching. The executor no longer needs to
know the key composition. Same reasoning applied to getRelatedData composite
recordIds (use the agent's opaque row id instead of rebuilding from
primaryKeyFields).

- add Collection#getOne(id, options) to @forestadmin/agent-client (by-id route)
- rewrite getRecord to use it; remove buildPkFilter / resolveSchema

For v1 agents the by-id read needs the agent to accept the pipe-joined id form
(forest_liana: PR #774; forest-express: pending). v2 already supports it.

Relates to PRD-450.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@linear-code
Copy link
Copy Markdown

linear-code Bot commented Jun 5, 2026

PRD-450

Copy link
Copy Markdown
Member

@christophebrun-forest christophebrun-forest left a comment

Choose a reason for hiding this comment

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

OK for me

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