I can not invoke a Lambda function from AWS Lex

0

Hello,

I would like to invoke a lambda function from AWS Lex v2, after the intent has been fulfilled. The needed resources (bot, lambda, rol, etc) must be defined using Cloudformation. This is apparently an easy task, just by defining a code hook on the Cloudformation template. But AFAIK it does not work, and the lambda is never invoked. I validate the lambda invocation using Cloudwatch logs.

If you would like to reproduce the environment, here you can find the Cloudformation template: https://pastebin.com/i9mzZMZE Just deploy the template (lambda code is embedded).

What am I missing?

Thanks in advance.

Roberto.

2 Answers
0

Hi Roberto,

Lex v2 requires a specific response format from the lambda function. https://docs.aws.amazon.com/lexv2/latest/dg/lambda.html#lambda-response-format

Add a response in the lambda code to indicate success, such as:

  intent = event['sessionState']['intent']['name']
  # if success and completed, send fulfilled response
  return {
                "sessionState": {
                    "dialogAction": {
                        "type": "Close"
                    },
                    "intent": {
                        "name": intent,
                        "state": 'Fulfilled'
                    }
                },
                'sessionId': event['sessionId']
            } 

AWS
answered a year ago
  • Hi TimG,

    Thanks a lot for the answer, but it is not exactly my case.

    In my case, I do not having problems with the format of the response - this will probably come later - but I don't get an answer at all, that is, the lambda is not invoked after the intent has been fulfilled.

    To reproduce the issue, please deploy the CloudFormation template included in the above ticket and fulfill an intent. You should see no lambda execution on CloudWatch.

    Thanks!

  • The CloudFormation worked fine and the lambda does run for me, although Lex will return a failure since its not in the format. Can you run the lambda function manually without any issue?

  • Hi AWS-TimG, The CloudFormation is working fine - it has always been working fine, no problem there. The lambda can be executed by hand. It will log an issue on CloudWatch. The real problem is that, when deployed using CloudFormation, Lex V2 is not executing the lambda function (that is, you can not see log messages on CloudWatch) and it's always returning a message of 'FailureResponse' - you assume that the failure is coming from the wrong return data from lambda, but the reality is that the FailureResponse is returned from Lex V2 without any lambda invocation.

    Could you please confirm this by executing an intent, and then validating the lambda's log messages on CloudWatch?? Thanks for the help!

  • Yes, when I execute an intent from the deployed CloudFormation Lex, lambda does run and logs the event in CW logs (also can be seen in CloudWatch invocations), even though I get a failure result in Lex. I wasn't able to re-produce the issue that you are seeing with the provided template.

    Does CW metrics show invocations/errors for the function (even though CW logs not showing anything)?

  • Hi TimG,

    Just to be aligned with your tests, I've reinstalled the Cloudformation Stack from the beginning. I confirm I cannot see the execution logs in CloudWatch nor the invocations errors on the lambda function. All the invocations show the "Esto es FailureResponse" message, indicating it's a failure, but no trace at all on CW logs. Any idea where to go from here?

0

I know this is an older question, but I wanted to put an answer on it for anyone who might hit the same issue in future and come across this post.

The issue you are hitting is likely because you are testing against the TestBotAlias, but in your CloudFormation you only associated the Lambda function with your Prod alias. When you test from the console you are hitting the TestBotAlias and I'm guessing that is where you are doing initial tests.

To associate it with the TestBotAlias you need to use the TestBotAliasSettings in the AWS::Lex::Bot resource.

From the CloudFormation you provided in your question, that would look like this:

  ReHubBot:
    DependsOn: BotRuntimeRole
    Type: AWS::Lex::Bot
    Properties:
      Name: "ReHubBot"
      RoleArn: !GetAtt BotRuntimeRole.Arn
      DataPrivacy:
        ChildDirected: false
      IdleSessionTTLInSeconds: 300
      Description: "Provides voice control to the ReHub app."
      AutoBuildBotLocales: true
      TestBotAliasSettings:
        BotAliasLocaleSettings:
            - LocaleId: es_ES
              BotAliasLocaleSetting:
                Enabled: true
                CodeHookSpecification:
                  LambdaCodeHook:
                    CodeHookInterfaceVersion: "1.0"
                    LambdaArn: !GetAtt TestLexFunction.Arn
    ....

You would also need to update the permissions to allow both the Prod and Test aliases to call the Lambda function. Here is what it would look like to update your CloudFormation to allow ALL aliases from that bot:

  LexInvokeLambdaPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: "lambda:InvokeFunction"
      FunctionName: !GetAtt TestLexFunction.Arn
      Principal: "lexv2.amazonaws.com"
      SourceArn:
        !Join
        - '/'
        - - !Sub arn:aws:lex:${AWS::Region}:${AWS::AccountId}:bot-alias
          - !Ref ReHubBot
          - '*'

As the previous poster also pointed out you do need to respond to Lex with the correct response format or it will fail. Here is the most basic version of that, it just does a pass-through delegating back to Lex and allowing it to use the configuration you set up.

import logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
def lambda_handler(event, context):
  logger.debug(event)
  session_state = event['sessionState']
  session_state['dialogAction'] = {
    'type': "Delegate"
  } 
  request_attributes = event.get('requestAttributes', {})
  lex_response = {
    'sessionState': session_state,
    'requestAttributes': request_attributes
  }
  logger.debug(lex_response)
  return lex_response

This code will work with any Lex v2 code hook (although take no action), so it's a good one if you are just testing out initially.

answered 4 months ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions