Skip to content

fix(bedrock-agent): make flow and prompt operations work and match the model - #2594

Merged
vieiralucas merged 3 commits into
mainfrom
fix/bedrock-agent-flow-prompt-shape
Sep 30, 2026
Merged

vieiralucas merged 3 commits into
mainfrom
fix/bedrock-agent-flow-prompt-shape

Conversation

@vieiralucas

@vieiralucas vieiralucas commented Sep 29, 2026 •

Copy link
Copy Markdown
Member

Summary

Found while checking Bedrock Agent response shapes after the ARN partition campaign.

Flows were broken over the wire. Every flow handler read flowId from the body, but the router supplies flowIdentifier (and aliasIdentifier), so GetFlow/UpdateFlow/DeleteFlow/PrepareFlow and every flow version and alias op always failed with a missing-field error. They now read the modeled names and accept the ID or the (URL-encoded) ARN.

Responses match the Smithy output shapes

  • GetFlow/UpdateFlow and GetPrompt/UpdatePrompt return the model's top-level members (id, stored arn, ...), not a {"flow":{"flowId"}} / {"prompt":{"promptId"}} wrapper; customerEncryptionKeyArn and defaultVariant are persisted.
  • Flow versions and aliases use the model shapes (alias ARN flow/<id>/alias/<alias-id>); deletes return their modeled id fields.
  • PrepareFlow returns Prepared (was the enum name PREPARED; old snapshots normalized on load); creates return 201, PrepareFlow 202; UpdateFlow resets the flow to NotPrepared.

ValidateFlowDefinition was routed to PrepareFlow. It now has its own route and checks structure (missing start/end node, unknown nodes/inputs, true duplicate connections keyed on source/target/output/input, unfulfilled or multiply-connected inputs, cycles, unreachable nodes, duplicate/empty node names) and returns the modeled validations list.

Versions and identifiers

  • Flow and prompt version numbers come from a persisted counter, so a deleted number is never reused.
  • DeletePrompt validates promptVersion as NumericalVersion (DRAFT/non-numeric -> ValidationException) instead of deleting the whole prompt; GetPrompt/DeletePrompt honor ?promptVersion=; ListPrompts honors promptIdentifier (the prompt's versions).
  • Prompt versions capture customerEncryptionKeyArn at creation.
  • ARN identifiers are parsed with arn_resource and must match the caller's account, region and partition (and an alias must belong to the flow in the path); foreign ARNs return ResourceNotFound.
  • Path labels are percent-decoded once in handle(); tags are keyed by the decoded ARN, and older snapshots' percent-encoded tag keys are re-keyed on load.
  • Removed the non-model GetPromptVersion/ListPromptVersions routes (the model reaches versions via GetPrompt/ListPrompts query members).

No surface changes (no SDK/introspection change).

Test plan

  • Route-level tests through handle() asserting exact key sets for flows, prompts and validate-definition; version numbering, DeletePrompt DRAFT rejection, ListPrompts by identifier, version encryption key, foreign-ARN rejection, AWS-sample flow validation, duplicate node names, tag re-keying on load. New tests fail without the change.
  • cargo test -p fakecloud-bedrock-agent (14), clippy -D warnings, fmt, cargo check --workspace --all-targets.
  • Conformance nextest (bedrock-agent, bedrock-agent-runtime) 6/6; probe conformance run --services bedrock-agent,bedrock-agent-runtime: 72/72 and 31/31 ops, 3669/3669 variants.

Summary by cubic

Fixes Bedrock Agent flow and prompt operations so they work over the wire and return the Smithy model's output shapes. Nearly every flow operation failed because handlers read a flowId body member the router never supplies, and responses carried wrapper objects the model doesn't define.

Bug Fixes

  • Flow handlers read the modeled flowIdentifier/aliasIdentifier and accept a bare ID or the URL-encoded ARN.
  • Get/Update flow and prompt responses return top-level members (id, stored arn, ...) instead of {"flow":{"flowId"}} / {"prompt":{"promptId"}} wrappers; customerEncryptionKeyArn and defaultVariant are persisted.
  • Flow versions and aliases use the model shapes; creates return 201 (PrepareFlow 202 and Prepared, was PREPARED); UpdateFlow resets the flow to NotPrepared.
  • ValidateFlowDefinition is now its own route (was routed to PrepareFlow) and returns the modeled validations list.
  • DeletePrompt rejects non-numeric promptVersion instead of deleting the whole prompt; GetPrompt/DeletePrompt honor ?promptVersion=; ListPrompts honors promptIdentifier.
  • ARN identifiers must name the caller's account, region and partition; foreign ARNs return ResourceNotFound.

Versions and identifiers

  • Version numbers come from a persisted per-resource counter, so a deleted number is never reused; prompt versions capture customerEncryptionKeyArn at creation.
  • Path labels are percent-decoded once in handle(); tag keys stored percent-encoded are re-keyed on load.
  • Removed the non-model GetPromptVersion/ListPromptVersions routes; versions are reached via GetPrompt/ListPrompts query members.

Written for commit 6621fb8. Summary will update on new commits.

Review in cubic

The flow and prompt handlers returned shapes the Smithy model doesn't have, and most flow operations could not be reached at all:

- Every flow handler read the flow from a flowId body member, but the router supplies the @httpLabel as flowIdentifier (aliases as aliasIdentifier), so GetFlow, UpdateFlow, DeleteFlow, PrepareFlow and every version and alias operation failed with a missing-field error over the wire. They now read flowIdentifier/aliasIdentifier and accept the bare ID or the (URL-encoded) ARN.
- GetFlow/UpdateFlow wrapped the flow in a flow member keyed flowId; GetPrompt/UpdatePrompt wrapped it in prompt keyed promptId. All now return the top-level output members (id, arn from the stored ARN, name, status, version, timestamps, plus customerEncryptionKeyArn, defaultVariant and definition, now persisted).
- Flow versions and aliases return GetFlowVersion/FlowAlias shapes (the alias ARN is flow/<id>/alias/<alias-id>); deletes return their modeled id members; PrepareFlow returns {id, status} with the FlowStatus wire value Prepared (not PREPARED) and 202, creates return 201, and UpdateFlow drops the flow back to NotPrepared.
- GetPrompt and DeletePrompt honor the promptVersion query member (and a version pinned in the ARN).
- POST /flows/validate-definition was routed as PrepareFlow on a flow named validate-definition. It now reaches ValidateFlowDefinition, which reads the definition and reports structural validations (missing starting/ending nodes, unknown connection endpoints and inputs/outputs, duplicate connections, unfulfilled or over-fed node inputs, cycles, unreachable nodes) in the modeled validations list instead of the unmodeled isValid/validationDetails.
…dation

- Flow and prompt version numbers come from a persisted per-resource counter (latest_version, defaulting from the highest live version for older snapshots), so a deleted version's number is never minted again.
- DeletePrompt's promptVersion is a NumericalVersion: DRAFT or any other non-numeric value is a ValidationException instead of deleting the whole prompt. GetPrompt still reads DRAFT as the working draft.
- ListPrompts honors its promptIdentifier query member, listing the draft and every numbered version of that prompt as PromptSummary. The GET /prompts/{id}/versions[/{v}] routes (ListPromptVersions/GetPromptVersion), which are not in the model, are removed.
- Prompt versions capture customerEncryptionKeyArn at creation. Version snapshots are now authoritative, and only versions persisted before the snapshot existed fall back to the live resource.
- Path labels are percent-decoded once in handle() instead of per handler.
- Identifier ARNs go through arn_resource and must name the caller's account, region and partition (and an alias ARN its own flow). A foreign ARN is ResourceNotFound instead of resolving to a local resource with the same ID.
- ValidateFlowDefinition keys duplicate connections on their ends (output and input, or condition), so one node feeding two inputs of another is valid. Nodes with an empty or already-used name are reported as Unspecified validations instead of being silently merged.
- create_flow_version/create_prompt_version borrow the resource instead of cloning it. Fixed the stale prompt_summary_json doc comment.
Tags are now keyed by the decoded resource ARN, but state persisted by builds that did not decode the {resourceArn} path label holds TagResource entries under the percent-encoded ARN, which the decoded lookups in ListTagsForResource/UntagResource never find. The load-time backfill now percent-decodes each tags-map key and merges it into any existing decoded entry. The decoded entry was written later, so its values win.
@vieiralucas
vieiralucas merged commit 8073de5 into main Sep 30, 2026
157 checks passed
@vieiralucas
vieiralucas deleted the fix/bedrock-agent-flow-prompt-shape branch September 30, 2026 02:28
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