Add human-in-the-loop-cdk: CDK version of one-click email approval wo…#417
Add human-in-the-loop-cdk: CDK version of one-click email approval wo…#417YogeshNain2015 wants to merge 7 commits into
Conversation
…rkflow CDK (Python) implementation of the human-in-the-loop pattern with one-click email approval. Uses AWS Lambda to URL-encode the task token and send clickable approve/reject links via Amazon SNS, with Amazon API Gateway handling the callback to resume the AWS Step Functions workflow.
| api_endpoint = f"https://{approval_api.rest_api_id}.execute-api.{self.region}.amazonaws.com/prod/respond" | ||
|
|
||
| send_approval_email_fn = _lambda.Function(self, "SendApprovalEmailFunction", | ||
| runtime=_lambda.Runtime.PYTHON_3_13, |
There was a problem hiding this comment.
please use the latest available runtime version
| notification_topic.grant_publish(send_approval_email_fn) | ||
|
|
||
| handle_approval_fn = _lambda.Function(self, "HandleApprovalFunction", | ||
| runtime=_lambda.Runtime.PYTHON_3_13, |
| ) | ||
|
|
||
| processing_fn = _lambda.Function(self, "ProcessingLambda", | ||
| runtime=_lambda.Runtime.NODEJS_24_X, |
There was a problem hiding this comment.
Why mix two programming languages?
| @@ -0,0 +1,80 @@ | |||
| { | |||
| "title": "Human in the Loop (CDK)", | |||
There was a problem hiding this comment.
| "title": "Human in the Loop (CDK)", | |
| "title": "Human in the Loop (AWS CDK)", |
| "cleanup": { | ||
| "headline": "Cleanup", | ||
| "text": [ | ||
| "1. Delete the stack: <code>cdk destroy</code>." |
There was a problem hiding this comment.
| "1. Delete the stack: <code>cdk destroy</code>." | |
| "Delete the stack: <code>cdk destroy</code>." |
| ``` | ||
|
|
||
| ---- | ||
| Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. |
There was a problem hiding this comment.
| Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | |
| Copyright 2026 Amazon.com, Inc. or its affiliates. All Rights Reserved. |
| "FunctionName": "${ProcessingLambda}", | ||
| "Payload": { | ||
| "input.$": "$", | ||
| "result": "rejected" |
There was a problem hiding this comment.
Both "result": "failure" and "result": "rejected" are passed as payload to ProcessingLambda (defined in cdk/cdk_stack.py). The ProcessingLambda is a simple lambda that returns the event as-is i.e currently its not doing anything however it's meant to be replaced by users with their own business logic to handle each outcome differently (e.g., send a rejection notification, trigger a rollback, log the failure, etc.). The result field allows the downstream function to differentiate which path was taken.
| "FunctionName": "${ProcessingLambda}", | ||
| "Payload": { | ||
| "input.$": "$", | ||
| "result": "failure" |
There was a problem hiding this comment.
Both "result": "failure" and "result": "rejected" are passed as payload to ProcessingLambda (defined in cdk/cdk_stack.py). The ProcessingLambda is a simple lambda that returns the event as-is i.e currently its not doing anything however it's meant to be replaced by users with their own business logic to handle each outcome differently (e.g., send a rejection notification, trigger a rollback, log the failure, etc.). The result field allows the downstream function to differentiate which path was taken.
| ) | ||
| ) | ||
|
|
||
| state_machine = sfn.CfnStateMachine(self, "HumanInTheLoopStateMachine", |
There was a problem hiding this comment.
Why not use sfn.StateMachine?
| handler="send_approval_email.lambda_handler", | ||
| code=_lambda.Code.from_asset("lambda"), | ||
| timeout=Duration.seconds(30), | ||
| memory_size=512, |
There was a problem hiding this comment.
The memory is much higher than in the SAM version for all functions. Any particular reason? Same for the timeout
- Use latest Python runtime (3.14) for all Lambda functions - Remove Node.js ProcessingLambda, rewrite in Python (single language) - Use L2 sfn.StateMachine construct instead of CfnStateMachine - Set Lambda timeout to 10s and updated 128MB memory use - Fix title to "Human in the Loop (AWS CDK)" - Remove numbered prefix from cleanup text - Add copyright year 2026 - Add Comment fields to rejection/failure states for clarity - In normal scenrio the failure processing lambda is unlikely to be invoked but if someone chages the code handleapprovalfunction specially sendtasktoken in that case it would go to hadlefailure flow, also it can be removed as well. feel free to suggest on the same...
|
Updated below changes:
|
| ```bash | ||
| cdk deploy --parameters ModeratorEmailAddress=your-email@example.com | ||
| ``` | ||
| 1. Note the outputs from the CDK deployment. These contain the resource names and/or ARNs which are used for testing. |
There was a problem hiding this comment.
Let's be more precise. It's the link to the state machine in the Step Functions console
- Rename human_in_the_loop_cdk/ to cdk/ to avoid name duplication - Clarify deployment output as link to state machine in Step Functions console
Co-authored-by: Ben <9841563+bfreiberg@users.noreply.github.com>
Co-authored-by: Ben <9841563+bfreiberg@users.noreply.github.com>
bfreiberg
left a comment
There was a problem hiding this comment.
Looks good, thanks for your contribution. Your workflow will be merged soon
Summary
CDK (Python) implementation of the existing human-in-the-loop pattern with one-click email approval.
-cdkworkflows in this repoResources created
GET /respondendpointwaitForTaskTokenintegrationRelated
Issue #, if available:
Description of changes:
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.