Custom Action invalid json response from server

I’m writing a custom action server in another language using API spec as a guide (not the Python SDK).

I am able to get Rasa to make a call to my server, however, when I generate a valid JSON response to send back to Rasa, the jsonschema validator within Rasa is failing. Here is the log:

raise error
jsonschema.exceptions.ValidationError: None is not of type 'object'. Failed to validate Action server response from API, make sure your response from the Action endpoint is valid. For more information about the format visit https://rasa.com/docs/rasa/custom-actions

Failed validating 'type' in schema:
    {'properties': {'events': {'items': {'properties': {'event': {'type': 'string'}},
                                         'type': 'object'},
                               'type': 'array'},
                    'responses': {'items': {'type': 'object'},
                                  'type': 'array'}},
     'type': 'object'}

On instance:
    None

The response sent back is very basic. It looks like this, which is according to the API spec (Rasa Action Server Documentation):

{
  "responses": [
    {
      "text": "Hello from server"
    }
  ]
}

Any help would be appreciated. Thanks!

1 Like

Just took a quick look here, I may be off, but I think you need to specify events, even when they’re empty e.g.

{
  "events": [],
  "responses": [
    {
      "text": "Hello from server"
    }
  ]
}

this is the method that’s validating this:


    @staticmethod
    def action_response_format_spec() -> Dict[Text, Any]:
        """Expected response schema for an Action endpoint.

        Used for validation of the response returned from the
        Action endpoint."""
        return {
            "type": "object",
            "properties": {
                "events": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {"event": {"type": "string"}},
                    },
                },
                "responses": {"type": "array", "items": {"type": "object"}},
            },
        }
1 Like

@mloubser I’ve just tried this, the same result. I also tried several other combinations of the response:

{
  "events": [{}],
  "responses": [
    {
      "text": "Hello from server"
    }
  ]
}

and also this, even though action should not be explicitly set (Events):

{
  "events": [
    {
      "event": "action",
      "name": "action_test"
    }
  ],
  "responses": [
    {
      "text": "Hello from server"
    }
  ]
}

Could you post the code that is sending this response? I know you said it’s not python, that’s fine, but someone one here could probably help

I tried this to see what part of this is throwing the error:

>>> from rasa.core.actions.action import RemoteAction
>>> payload = {
...   "responses": [
...     {
...       "text": "Hello from server"
...     }
...   ]
... }
>>> action = RemoteAction("hallo","http://localhost:5055")
>>> action._validate_action_result(payload)
True

So, the ‘result’ it is validating must not in fact be the payload you posted; is it getting processed somehow?

@mloubser I’m currently using Elixir code to run a Phoenix HTTP server. As seen below, I’m creating the proper structure to be returned and JSON encoding it.

Here are the outputs from my code:

Struct: %{events: [], responses: [%{text: "Hello world from server"}]}
Json string: "{\"responses\":[{\"text\":\"Hello world from server\"}],\"events\":[]}"

chat_action is the entry point of the HTTP request

  def chat_action(conn, body = _params) do
    case Rasa.handle_action(body) do
      nil ->
        send_resp(conn, 400, "error")

      result ->
        response = Poison.encode!(result)

        put_resp_header(conn, "content-type", "application/json")
        send_resp(conn, 200, response)
    end
  end

  def handle_action(message) do
    case Map.get(message, "next_action") do
      nil ->
        Logger.error("[rasa] no action")
        nil

      "action_test" ->
        %{
          responses: [construct_response("Hello world from server")],
          events: []
        }
    end
  end

  def construct_response(text) do
    %{
      text: text
    }
  end

Ok I think I got something - look at the on instance message in your error. It is validating a None response, not your payload. This is what I get if I enter an intentionally wrong payload:

>>> payload = "wrong"
>>> action._validate_action_result(payload)
...
Failed validating 'type' in schema:
    {'properties': {'events': {'items': {'properties': {'event': {'type': 'string'}},
                                         'type': 'object'},
                               'type': 'array'},
                    'responses': {'items': {'type': 'object'},
                                  'type': 'array'}},
     'type': 'object'}

On instance:
    'wrong'

vs. in the original error

Failed validating 'type' in schema:
    {'properties': {'events': {'items': {'properties': {'event': {'type': 'string'}},
                                         'type': 'object'},
                               'type': 'array'},
                    'responses': {'items': {'type': 'object'},
                                  'type': 'array'}},
     'type': 'object'}

On instance:
    None

@mloubser Is it possible that rasa instance isn’t receiving my server’s response body? Do you know of any way to log the responses that rasa is receiving to confirm this?

It would be useful to see the response body being sent. You could do this by adding debug statements directly in rasa’s code; easier would be to add it to your action server somewhere - I’m not familiar with Elixir, but can you get a dump of the network request sent by send_resp?

You can try log the response from action server

response should be (JSON) below format :

{'events': [], 'responses': [{'text': "Hey! I'm  test assistant ", 'buttons': [], 'elements': [], 'custom': {}, 'template': None, 'response': None, 'image': None, 'attachment': None}]}