fix(bedrock-agent): make flow and prompt operations work and match the model - #2594
Merged
Merged
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Found while checking Bedrock Agent response shapes after the ARN partition campaign.
Flows were broken over the wire. Every flow handler read
flowIdfrom the body, but the router suppliesflowIdentifier(andaliasIdentifier), 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
id, storedarn, ...), not a{"flow":{"flowId"}}/{"prompt":{"promptId"}}wrapper;customerEncryptionKeyArnanddefaultVariantare persisted.flow/<id>/alias/<alias-id>); deletes return their modeledidfields.Prepared(was the enum namePREPARED; old snapshots normalized on load); creates return 201, PrepareFlow 202; UpdateFlow resets the flow toNotPrepared.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
validationslist.Versions and identifiers
DeletePromptvalidatespromptVersionasNumericalVersion(DRAFT/non-numeric -> ValidationException) instead of deleting the whole prompt;GetPrompt/DeletePrompthonor?promptVersion=;ListPromptshonorspromptIdentifier(the prompt's versions).customerEncryptionKeyArnat creation.arn_resourceand must match the caller's account, region and partition (and an alias must belong to the flow in the path); foreign ARNs return ResourceNotFound.handle(); tags are keyed by the decoded ARN, and older snapshots' percent-encoded tag keys are re-keyed on load.GetPromptVersion/ListPromptVersionsroutes (the model reaches versions viaGetPrompt/ListPromptsquery members).No surface changes (no SDK/introspection change).
Test plan
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 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
flowIdbody member the router never supplies, and responses carried wrapper objects the model doesn't define.Bug Fixes
flowIdentifier/aliasIdentifierand accept a bare ID or the URL-encoded ARN.id, storedarn, ...) instead of{"flow":{"flowId"}}/{"prompt":{"promptId"}}wrappers;customerEncryptionKeyArnanddefaultVariantare persisted.Prepared, wasPREPARED); UpdateFlow resets the flow toNotPrepared.ValidateFlowDefinitionis now its own route (was routed to PrepareFlow) and returns the modeledvalidationslist.DeletePromptrejects non-numericpromptVersioninstead of deleting the whole prompt;GetPrompt/DeletePrompthonor?promptVersion=;ListPromptshonorspromptIdentifier.Versions and identifiers
customerEncryptionKeyArnat creation.handle(); tag keys stored percent-encoded are re-keyed on load.GetPromptVersion/ListPromptVersionsroutes; versions are reached viaGetPrompt/ListPromptsquery members.Written for commit 6621fb8. Summary will update on new commits.