diff --git a/MANIFEST.in b/MANIFEST.in
deleted file mode 100644
index 0467be2..0000000
--- a/MANIFEST.in
+++ /dev/null
@@ -1,5 +0,0 @@
-include README.md
-include LICENSE
-graft opsdroid
-include opsdroid/configuration/example_configuration.yaml
-recursive-exclude * *.py[co]
diff --git a/docs/configuration-reference.md b/docs/configuration-reference.md
index 130a125..65bcd2b 100644
--- a/docs/configuration-reference.md
+++ b/docs/configuration-reference.md
@@ -23,11 +23,11 @@ _Config options of the connectors themselves differ between connectors, see the
 ```yaml
 connectors:
 
-  slack:
+  - name: slack
     token: "mysecretslacktoken"
 
   # conceptual connector
-  twitter:
+  - name: twitter
     oauth_key: "myoauthkey"
     secret_key: "myoauthsecret"
 ```
@@ -44,7 +44,7 @@ _Config options of the databases themselves differ between databases, see the da
 
 ```yaml
 databases:
-  mongo:
+  - name: mongo
     host: "mymongohost.mycompany.com"
     port: "27017"
     database: "opsdroid"
@@ -62,11 +62,11 @@ All python logging levels are available in opsdroid. `logging` can be set to `de
 logging: debug
 
 connectors:
-  shell:
+  - name: shell
 
 skills:
-  hello:
-  seen:
+  - name: hello
+  - name: seen
 ```
 
 ### `module-path`
@@ -77,11 +77,11 @@ Set the path for opsdroid to use when installing skills. Defaults to the current
 module-path: "/etc/opsdroid/modules"
 
 connectors:
-  shell:
+  - name: shell
 
 skills:
-  hello:
-  seen:
+  - name: hello
+  - name: seen
 ```
 
 ### `skills`
@@ -92,8 +92,8 @@ _Config options of the skills themselves differ between skills, see the skill do
 
 ```yaml
 skills:
-  hello:
-  seen:
+  - name: hello
+  - name: seen
 ```
 
 See [module options](#module-options) for installing custom skills.
@@ -110,9 +110,9 @@ A git url to install the module from.
 
 ```yaml
 connectors:
-  slack:
+  - name: slack
     token: "mysecretslacktoken"
-  mynewconnector:
+  - name: mynewconnector
     repo: https://github.com/username/myconnector.git
 ```
 
@@ -122,7 +122,7 @@ A local path to install the module from.
 
 ```yaml
 skills:
-  myawesomeskill:
+  - name: myawesomeskill
     path: /home/me/src/opsdroid-skills/myawesomeskill
 ```
 
@@ -130,7 +130,7 @@ Or you can specify a single file.
 
 ```yaml
 skills:
-  myawesomeskill:
+  - name: myawesomeskill
     path: /home/me/src/opsdroid-skills/myawesomeskill/myskill.py
 ```
 
@@ -140,7 +140,7 @@ Set this to do a fresh git clone of the module whenever you start opsdroid.
 
 ```yaml
 databases:
-  mongodb:
+  - name: mongodb
     repo: https://github.com/username/mymongofork.git
     no-cache: true
 ```
diff --git a/docs/getting-started.md b/docs/getting-started.md
index 89b891f..f9b2692 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -30,10 +30,10 @@ For example a simple barebones configuration would look like:
 
 ```yaml
 connectors:
-  shell:
+  - name: shell
 
 skills:
-  hello:
+  - name: hello
 ```
 
 This tells opsdroid to use the [shell connector](https://github.com/opsdroid/connector-shell) and [hello skill](https://github.com/opsdroid/skill-hello) from the official module library.
@@ -46,19 +46,19 @@ A more advanced config would like similar to the following:
 
 ```yaml
 connectors:
-  slack:
+  - name: slack
     token: "mysecretslacktoken"
 
 databases:
-  mongo:
+  - name: mongo
     host: "mymongohost.mycompany.com"
     port: "27017"
     database: "opsdroid"
 
 skills:
-  hello:
-  seen:
-  myawesomeskill:
+  - name: hello
+  - name: seen
+  - name: myawesomeskill
     repo: "https://github.com/username/myawesomeskill.git"
 ```
 
diff --git a/docs/parsers/api.ai.md b/docs/parsers/api.ai.md
index ef147dc..71d0856 100644
--- a/docs/parsers/api.ai.md
+++ b/docs/parsers/api.ai.md
@@ -39,7 +39,7 @@ You can also set a `min-score` option to tell opsdroid to ignore any matches whi
 ```yaml
 
 parsers:
-  apiai:
+  - name: apiai
     access-token: "exampleaccesstoken123"
     min-score: 0.6
 ```
diff --git a/opsdroid/configuration/example_configuration.yaml b/opsdroid/configuration/example_configuration.yaml
index dd5a231..92a7c29 100644
--- a/opsdroid/configuration/example_configuration.yaml
+++ b/opsdroid/configuration/example_configuration.yaml
@@ -1,42 +1,54 @@
-#                      _           _     _
-#   ___  _ __  ___  __| |_ __ ___ (_) __| |
-#  / _ \| '_ \/ __|/ _` | '__/ _ \| |/ _` |
-# | (_) | |_) \__ \ (_| | | | (_) | | (_| |
-#  \___/| .__/|___/\__,_|_|  \___/|_|\__,_|
-#       |_|
-#                   __ _
-#   ___ ___  _ __  / _(_) __ _
-#  / __/ _ \| '_ \| |_| |/ _` |
-# | (_| (_) | | | |  _| | (_| |
-#  \___\___/|_| |_|_| |_|\__, |
-#                        |___/
-#
-# A default config file to use with opsdroid
-
-# Set the logging level
+##                      _           _     _
+##   ___  _ __  ___  __| |_ __ ___ (_) __| |
+##  / _ \| '_ \/ __|/ _` | '__/ _ \| |/ _` |
+## | (_) | |_) \__ \ (_| | | | (_) | | (_| |
+##  \___/| .__/|___/\__,_|_|  \___/|_|\__,_|
+##       |_|
+##                   __ _
+##   ___ ___  _ __  / _(_) __ _
+##  / __/ _ \| '_ \| |_| |/ _` |
+## | (_| (_) | | | |  _| | (_| |
+##  \___\___/|_| |_|_| |_|\__, |
+##                        |___/
+##
+## A default config file to use with opsdroid
+
+## Set the logging level
 # logging: info
 
-# Set the location for opsdroid to install modules
+## Set the location for opsdroid to install modules
 # module-path: "."
 
-# Connector modules
+## Parsers
+# parsers:
+#   - name: regex
+#     enabled: true
+#
+#   - name: crontab
+#     enabled: true
+#
+#   - name: apiai
+#     access-token: "youraccesstoken"
+#     min-score: 0.6
+
+## Connector modules
 connectors:
-  shell:
+  - name: shell
 
-# Database modules (optional)
+## Database modules (optional)
 # databases:
 
-# Skill modules
+## Skill modules
 skills:
 
-  # Hello world (https://github.com/opsdroid/skill-hello)
-  hello:
+  ## Hello world (https://github.com/opsdroid/skill-hello)
+  - name: hello
 
-  # Last seen (https://github.com/opsdroid/skill-seen)
-  seen:
+  ## Last seen (https://github.com/opsdroid/skill-seen)
+  - name: seen
 
-  # Dance (https://github.com/opsdroid/skill-dance)
-  dance:
+  ## Dance (https://github.com/opsdroid/skill-dance)
+  - name: dance
 
-  # Loud noises (https://github.com/opsdroid/skill-loudnoises)
-  loudnoises:
+  ## Loud noises (https://github.com/opsdroid/skill-loudnoises)
+  - name: loudnoises
diff --git a/opsdroid/const.py b/opsdroid/const.py
index 688c79d..77f5b2c 100644
--- a/opsdroid/const.py
+++ b/opsdroid/const.py
@@ -1,6 +1,6 @@
 """Constants used by OpsDroid."""
 
-__version__ = "0.5.1"
+__version__ = "0.5.0"
 
 LOG_FILENAME = 'output.log'
 DEFAULT_GIT_URL = "https://github.com/opsdroid/"
diff --git a/opsdroid/core.py b/opsdroid/core.py
index 4308eb9..772073d 100644
--- a/opsdroid/core.py
+++ b/opsdroid/core.py
@@ -150,7 +150,17 @@ class OpsDroid():
             tasks.append(
                 self.eventloop.create_task(parse_regex(self, message)))
 
-            if "parsers" in self.config and "apiai" in self.config["parsers"]:
-                tasks.append(
-                    self.eventloop.create_task(parse_apiai(self, message)))
+            if "parsers" in self.config:
+                logging.debug("Processing parsers")
+                parsers = self.config["parsers"]
+
+                apiai = [p for p in parsers if p["name"] == "apiai"]
+                logging.debug("Checking apiai")
+                if len(apiai) == 1 and \
+                        ("enabled" not in apiai[0] or
+                         apiai[0]["enabled"] is not False):
+                    logging.debug("Parsing with apiai")
+                    tasks.append(
+                        self.eventloop.create_task(
+                            parse_apiai(self, message, apiai[0])))
         return tasks
diff --git a/opsdroid/loader.py b/opsdroid/loader.py
index 7965637..7d2158b 100644
--- a/opsdroid/loader.py
+++ b/opsdroid/loader.py
@@ -18,6 +18,7 @@ class Loader:
         """Setup object with opsdroid instance."""
         self.opsdroid = opsdroid
         self.modules_directory = MODULES_DIRECTORY
+        self.current_import_config = None
         logging.debug("Loaded loader")
 
     @staticmethod
@@ -154,12 +155,12 @@ class Loader:
         if not os.path.isdir(self.modules_directory):
             os.makedirs(self.modules_directory)
 
-        for module_name in modules.keys():
+        for module in modules:
 
             # Set up module config
-            config = modules[module_name]
+            config = module
             config = {} if config is None else config
-            config["name"] = module_name
+            config["name"] = module["name"]
             config["type"] = modules_type
             config["module_path"] = self.build_module_path("import", config)
             config["install_path"] = self.build_module_path("install", config)
@@ -173,6 +174,7 @@ class Loader:
             self._install_module(config)
 
             # Import module
+            self.current_import_config = config
             module = self.import_module(config)
             if module is not None:
                 loaded_modules.append({
diff --git a/opsdroid/parsers/apiai.py b/opsdroid/parsers/apiai.py
index 8cea8dd..cd6798b 100644
--- a/opsdroid/parsers/apiai.py
+++ b/opsdroid/parsers/apiai.py
@@ -28,13 +28,12 @@ async def call_apiai(message, config):
         return result
 
 
-async def parse_apiai(opsdroid, message):
+async def parse_apiai(opsdroid, message, config):
     """Parse a message against all apiai skills."""
     # pylint: disable=broad-except
     # We want to catch all exceptions coming from a skill module and not
     # halt the application. If a skill throws an exception it just doesn't
     # give a response to the user, so an error response should be given.
-    config = opsdroid.config['parsers']['apiai']
     if 'access-token' in config:
 
         result = await call_apiai(message, config)
@@ -62,7 +61,8 @@ async def parse_apiai(opsdroid, message):
                                 result["result"]["intentName"]):
                         message.apiai = result
                         try:
-                            await skill["skill"](opsdroid, message)
+                            await skill["skill"](opsdroid, skill["config"],
+                                                 message)
                         except Exception:
                             await message.respond(
                                 "Whoops there has been an error")
diff --git a/opsdroid/parsers/crontab.py b/opsdroid/parsers/crontab.py
index 49f9281..c7083d1 100644
--- a/opsdroid/parsers/crontab.py
+++ b/opsdroid/parsers/crontab.py
@@ -19,6 +19,6 @@ async def parse_crontab(opsdroid):
         for skill in opsdroid.skills:
             if "crontab" in skill and pycron.is_now(skill["crontab"]):
                 try:
-                    await skill["skill"](opsdroid, None)
+                    await skill["skill"](opsdroid, skill["config"], None)
                 except Exception:
                     logging.exception("Exception when executing cron skill.")
diff --git a/opsdroid/parsers/regex.py b/opsdroid/parsers/regex.py
index a8500c0..bcefa2d 100644
--- a/opsdroid/parsers/regex.py
+++ b/opsdroid/parsers/regex.py
@@ -16,7 +16,7 @@ async def parse_regex(opsdroid, message):
             if regex:
                 message.regex = regex
                 try:
-                    await skill["skill"](opsdroid, message)
+                    await skill["skill"](opsdroid, skill["config"], message)
                 except Exception:
                     await message.respond(
                         "Whoops there has been an error")
diff --git a/opsdroid/skills.py b/opsdroid/skills.py
index 5b4b7f3..7938a53 100644
--- a/opsdroid/skills.py
+++ b/opsdroid/skills.py
@@ -8,7 +8,9 @@ def match_regex(regex):
     def matcher(func):
         """Add decorated function to skills list for regex matching."""
         for opsdroid in OpsDroid.instances:
-            opsdroid.skills.append({"regex": regex, "skill": func})
+            opsdroid.skills.append({"regex": regex, "skill": func,
+                                    "config":
+                                    opsdroid.loader.current_import_config})
         return func
     return matcher
 
@@ -18,7 +20,9 @@ def match_apiai_action(action):
     def matcher(func):
         """Add decorated function to skills list for apiai matching."""
         for opsdroid in OpsDroid.instances:
-            opsdroid.skills.append({"apiai_action": action, "skill": func})
+            opsdroid.skills.append({"apiai_action": action, "skill": func,
+                                    "config":
+                                    opsdroid.loader.current_import_config})
         return func
     return matcher
 
@@ -28,7 +32,9 @@ def match_apiai_intent(intent):
     def matcher(func):
         """Add decorated function to skills list for apiai matching."""
         for opsdroid in OpsDroid.instances:
-            opsdroid.skills.append({"apiai_intent": intent, "skill": func})
+            opsdroid.skills.append({"apiai_intent": intent, "skill": func,
+                                    "config":
+                                    opsdroid.loader.current_import_config})
         return func
     return matcher
 
@@ -38,6 +44,8 @@ def match_crontab(crontab):
     def matcher(func):
         """Add decorated function to skills list for crontab matching."""
         for opsdroid in OpsDroid.instances:
-            opsdroid.skills.append({"crontab": crontab, "skill": func})
+            opsdroid.skills.append({"crontab": crontab, "skill": func,
+                                    "config":
+                                    opsdroid.loader.current_import_config})
         return func
     return matcher
diff --git a/setup.py b/setup.py
index 93c131f..e341c5a 100644
--- a/setup.py
+++ b/setup.py
@@ -11,8 +11,6 @@ PACKAGES = find_packages(exclude=['tests', 'tests.*', 'modules',
 
 REQUIRES = [
     'pyyaml>=3.11,<4',
-    'aiohttp>=1.2.0,<2',
-    'pycron>=0.40',
 ]
 
 setup(

Change module configuration layout
As suggested by @tpowellmeto `connectors`/`databases`/`skills` are all lists of modules. Therefore they should probably be a list in the configuration rather than a dictionary.

This makes empty module configurations easier to read as they are not empty key/value pairs.

Before

```yaml
skills:
  hello:
    additionalconfigitem: "value"
  seen:
  dance:
  loudnoises:
```

After
```yaml
skills:
  - name: hello
    additionalconfigitem: "value"
  - name: seen
  - name: dance
  - name: loudnoises
```
diff --git a/tests/test_core.py b/tests/test_core.py
index b022f1b..0deff87 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -8,7 +8,7 @@ import importlib
 from opsdroid.core import OpsDroid
 from opsdroid.message import Message
 from opsdroid.connector import Connector
-from opsdroid.skills import match_regex
+from opsdroid.skills import match_regex, match_apiai_action
 
 
 class TestCore(unittest.TestCase):
@@ -124,7 +124,7 @@ class TestCore(unittest.TestCase):
 class TestCoreAsync(asynctest.TestCase):
     """Test the async methods of the opsdroid core class."""
 
-    async def test_parse(self):
+    async def test_parse_regex(self):
         with OpsDroid() as opsdroid:
             regex = r".*"
             skill = amock.CoroutineMock()
@@ -136,3 +136,18 @@ class TestCoreAsync(asynctest.TestCase):
             for task in tasks:
                 await task
             self.assertTrue(skill.called)
+
+    async def test_parse_apiai(self):
+        with OpsDroid() as opsdroid:
+            opsdroid.config["parsers"] = [{"name": "apiai"}]
+            apiai_action = ""
+            skill = amock.CoroutineMock()
+            mock_connector = Connector({})
+            decorator = match_apiai_action(apiai_action)
+            decorator(skill)
+            message = Message("Hello world", "user", "default", mock_connector)
+            with amock.patch('opsdroid.parsers.apiai.parse_apiai'):
+                tasks = await opsdroid.parse(message)
+                self.assertEqual(len(tasks), 2)  # apiai and regex
+                for task in tasks:
+                    await task
diff --git a/tests/test_loader.py b/tests/test_loader.py
index f1bb702..f88088e 100644
--- a/tests/test_loader.py
+++ b/tests/test_loader.py
@@ -76,6 +76,7 @@ class TestLoader(unittest.TestCase):
         open(config['install_path'] + ".py", 'w')
         ld.Loader.check_cache(config)
         self.assertFalse(os.path.isfile(config["install_path"] + ".py"))
+        shutil.rmtree(directory)
 
     def test_check_cache_leaves(self):
         config = {}
@@ -139,7 +140,7 @@ class TestLoader(unittest.TestCase):
         opsdroid, loader = self.setup()
 
         modules_type = "test"
-        modules = {"testmodule": None}
+        modules = [{"name": "testmodule"}]
         mockedmodule = mock.Mock(return_value={"name": "testmodule"})
 
         with mock.patch.object(loader, '_install_module') as mockinstall, \
@@ -170,6 +171,7 @@ class TestLoader(unittest.TestCase):
             logmock.assert_called_with(
                     'Module ' + config["name"] +
                     ' already installed, skipping')
+        shutil.rmtree(config["install_path"])
 
     def test_install_missing_local_module(self):
         opsdroid, loader = self.setup()
@@ -199,12 +201,13 @@ class TestLoader(unittest.TestCase):
 
     def test_install_specific_local_git_module(self):
         opsdroid, loader = self.setup()
+        repo_path = "/tmp/testrepo"
         config = {"name": "testmodule",
-                  "install_path": "/tmp/testrepo",
+                  "install_path": repo_path,
                   "repo": "https://github.com/rmccue/test-repository.git",
                   "branch": "master"}
         loader._install_module(config)  # Clone remote repo for testing with
-        config["repo"] = config["install_path"]
+        config["repo"] = config["install_path"] + "/.git"
         config["install_path"] = "/tmp/test_specific_local_module"
         with mock.patch('logging.debug'), \
                 mock.patch.object(loader, 'git_clone') as mockclone:
@@ -212,11 +215,13 @@ class TestLoader(unittest.TestCase):
             mockclone.assert_called_with(config["repo"],
                                          config["install_path"],
                                          config["branch"])
+        shutil.rmtree(repo_path)
 
     def test_install_specific_local_path_module(self):
         opsdroid, loader = self.setup()
+        repo_path = "/tmp/testrepo"
         config = {"name": "testmodule",
-                  "install_path": "/tmp/testrepo",
+                  "install_path": repo_path,
                   "repo": "https://github.com/rmccue/test-repository.git",
                   "branch": "master"}
         loader._install_module(config)  # Clone remote repo for testing with
@@ -227,6 +232,7 @@ class TestLoader(unittest.TestCase):
                 as mockclone:
             loader._install_module(config)
             mockclone.assert_called_with(config)
+        shutil.rmtree(repo_path)
 
     def test_install_default_remote_module(self):
         opsdroid, loader = self.setup()
@@ -243,21 +249,25 @@ class TestLoader(unittest.TestCase):
             mockdeps.assert_called_with(
                     config["install_path"] + "/requirements.txt")
 
+        shutil.rmtree(config["install_path"])
+
     def test_install_local_module_dir(self):
         opsdroid, loader = self.setup()
+        base_path = "/tmp/long"
         config = {"name": "slack",
                   "type": "connector",
-                  "install_path": "/tmp/long/test/path/test",
+                  "install_path": base_path + "/test/path/test",
                   "path": "/tmp/install/from/here"}
         os.makedirs(config["path"], exist_ok=True)
         loader._install_local_module(config)
         self.assertTrue(os.path.isdir(config["install_path"]))
+        shutil.rmtree(base_path)
 
     def test_install_local_module_file(self):
         opsdroid, loader = self.setup()
         config = {"name": "slack",
                   "type": "connector",
-                  "install_path": "/tmp/test/test",
+                  "install_path": "/tmp/test_local_module_file",
                   "path": "/tmp/install/from/here.py"}
         directory, _ = os.path.split(config["path"])
         os.makedirs(directory, exist_ok=True)
@@ -265,12 +275,13 @@ class TestLoader(unittest.TestCase):
         loader._install_local_module(config)
         self.assertTrue(os.path.isfile(
                             config["install_path"] + "/__init__.py"))
+        shutil.rmtree(config["install_path"])
 
     def test_install_local_module_failure(self):
         opsdroid, loader = self.setup()
         config = {"name": "slack",
                   "type": "connector",
-                  "install_path": "/tmp/test/test",
+                  "install_path": "/tmp/test_local_module_failure",
                   "path": "/tmp/does/not/exist"}
         with mock.patch('logging.error') as logmock:
             loader._install_local_module(config)
diff --git a/tests/test_parser_apiai.py b/tests/test_parser_apiai.py
index 268e326..7537e1f 100644
--- a/tests/test_parser_apiai.py
+++ b/tests/test_parser_apiai.py
@@ -17,7 +17,7 @@ class TestParserApiai(asynctest.TestCase):
     async def test_call_apiai(self):
         mock_connector = Connector({})
         message = Message("Hello world", "user", "default", mock_connector)
-        config = {'access-token': 'test'}
+        config = {'name': 'apiai', 'access-token': 'test'}
         result = amock.Mock()
         result.json = amock.CoroutineMock()
         result.json.return_value = {
@@ -38,9 +38,9 @@ class TestParserApiai(asynctest.TestCase):
 
     async def test_parse_apiai(self):
         with OpsDroid() as opsdroid:
-            opsdroid.config['parsers'] = {
-                    'apiai': {'access-token': "test"}
-                }
+            opsdroid.config['parsers'] = [
+                    {'name': 'apiai', 'access-token': "test"}
+                ]
             mock_skill = amock.CoroutineMock()
             match_apiai_action('myaction')(mock_skill)
 
@@ -58,15 +58,16 @@ class TestParserApiai(asynctest.TestCase):
                             "errorType": "success"
                         }
                     }
-                await apiai.parse_apiai(opsdroid, message)
+                await apiai.parse_apiai(opsdroid, message,
+                                        opsdroid.config['parsers'][0])
 
             self.assertTrue(mock_skill.called)
 
     async def test_parse_apiai_raises(self):
         with OpsDroid() as opsdroid:
-            opsdroid.config['parsers'] = {
-                    'apiai': {'access-token': "test"}
-                }
+            opsdroid.config['parsers'] = [
+                    {'name': 'apiai', 'access-token': "test"}
+                ]
             mock_skill = amock.CoroutineMock()
             mock_skill.side_effect = Exception()
             match_apiai_action('myaction')(mock_skill)
@@ -85,15 +86,16 @@ class TestParserApiai(asynctest.TestCase):
                             "errorType": "success"
                         }
                     }
-                await apiai.parse_apiai(opsdroid, message)
+                await apiai.parse_apiai(opsdroid, message,
+                                        opsdroid.config['parsers'][0])
 
             self.assertTrue(mock_skill.called)
 
     async def test_parse_apiai_failure(self):
         with OpsDroid() as opsdroid:
-            opsdroid.config['parsers'] = {
-                    'apiai': {'access-token': "test"}
-                }
+            opsdroid.config['parsers'] = [
+                    {'name': 'apiai', 'access-token': "test"}
+                ]
             mock_skill = amock.CoroutineMock()
             match_apiai_action('myaction')(mock_skill)
 
@@ -111,15 +113,16 @@ class TestParserApiai(asynctest.TestCase):
                             "errorType": "not found"
                         }
                     }
-                await apiai.parse_apiai(opsdroid, message)
+                await apiai.parse_apiai(opsdroid, message,
+                                        opsdroid.config['parsers'][0])
 
             self.assertFalse(mock_skill.called)
 
     async def test_parse_apiai_low_score(self):
         with OpsDroid() as opsdroid:
-            opsdroid.config['parsers'] = {
-                    'apiai': {'access-token': "test", "min-score": 0.8}
-                }
+            opsdroid.config['parsers'] = [
+                    {'name': 'apiai', 'access-token': "test", "min-score": 0.8}
+                ]
             mock_skill = amock.CoroutineMock()
             match_apiai_action('myaction')(mock_skill)
 
@@ -137,6 +140,7 @@ class TestParserApiai(asynctest.TestCase):
                             "errorType": "success"
                         }
                     }
-                await apiai.parse_apiai(opsdroid, message)
+                await apiai.parse_apiai(opsdroid, message,
+                                        opsdroid.config['parsers'][0])
 
             self.assertFalse(mock_skill.called)

pip3 install -e .
parse_log_pytest
requirements.txt
pytest pytest-cov
apt-get update apt-get install -y git
3.6
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
aiohttp==1.3.5
aiosignal==1.2.0
async-timeout==4.0.2
asynctest==0.13.0
attrs==22.2.0
certifi==2021.5.30
chardet==5.0.0
charset-normalizer==3.0.1
coverage==6.2
frozenlist==1.2.0
idna==3.10
idna-ssl==1.1.0
importlib-metadata==4.8.3
iniconfig==1.1.1
multidict==5.2.0
-e git+https://github.com/opsdroid/opsdroid.git@7673919fc9ea93eaf475c9258388894fdbd27955#egg=opsdroid
packaging==21.3
pluggy==1.0.0
py==1.11.0
pycron==3.0.0
pyparsing==3.1.4
pytest==7.0.1
pytest-cov==4.0.0
PyYAML==3.13
tomli==1.2.3
typing_extensions==4.1.1
yarl==0.9.8
zipp==3.6.0

name: opsdroid
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - aiohttp==1.3.5
      - aiosignal==1.2.0
      - async-timeout==4.0.2
      - asynctest==0.13.0
      - attrs==22.2.0
      - chardet==5.0.0
      - charset-normalizer==3.0.1
      - coverage==6.2
      - frozenlist==1.2.0
      - idna==3.10
      - idna-ssl==1.1.0
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - multidict==5.2.0
      - packaging==21.3
      - pluggy==1.0.0
      - py==1.11.0
      - pycron==3.0.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - pytest-cov==4.0.0
      - pyyaml==3.13
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - yarl==0.9.8
      - zipp==3.6.0
prefix: /opt/conda/envs/opsdroid

tests/test_core.py::TestCoreAsync::test_parse_apiai tests/test_loader.py::TestLoader::test_load_modules tests/test_parser_apiai.py::TestParserApiai::test_parse_apiai tests/test_parser_apiai.py::TestParserApiai::test_parse_apiai_failure tests/test_parser_apiai.py::TestParserApiai::test_parse_apiai_low_score
tests/test_loader.py::TestLoader::test_load_non_existant_config_file tests/test_parser_apiai.py::TestParserApiai::test_parse_apiai_raises
tests/test_core.py::TestCore::test_core tests/test_core.py::TestCore::test_critical tests/test_core.py::TestCore::test_default_connector tests/test_core.py::TestCore::test_default_room tests/test_core.py::TestCore::test_exit tests/test_core.py::TestCore::test_load_config tests/test_core.py::TestCore::test_load_regex_skill tests/test_core.py::TestCore::test_multiple_opsdroids tests/test_core.py::TestCore::test_setup_modules tests/test_core.py::TestCore::test_start_connectors tests/test_core.py::TestCore::test_start_databases tests/test_core.py::TestCore::test_start_loop tests/test_core.py::TestCoreAsync::test_parse_regex tests/test_loader.py::TestLoader::test_build_module_path tests/test_loader.py::TestLoader::test_check_cache_leaves tests/test_loader.py::TestLoader::test_check_cache_removes_dir tests/test_loader.py::TestLoader::test_check_cache_removes_file tests/test_loader.py::TestLoader::test_git_clone tests/test_loader.py::TestLoader::test_import_module tests/test_loader.py::TestLoader::test_import_module_failure tests/test_loader.py::TestLoader::test_import_module_new tests/test_loader.py::TestLoader::test_install_default_remote_module tests/test_loader.py::TestLoader::test_install_existing_module tests/test_loader.py::TestLoader::test_install_local_module_dir tests/test_loader.py::TestLoader::test_install_local_module_failure tests/test_loader.py::TestLoader::test_install_local_module_file tests/test_loader.py::TestLoader::test_install_missing_local_module tests/test_loader.py::TestLoader::test_install_specific_local_git_module tests/test_loader.py::TestLoader::test_install_specific_local_path_module tests/test_loader.py::TestLoader::test_install_specific_remote_module tests/test_loader.py::TestLoader::test_load_broken_config_file tests/test_loader.py::TestLoader::test_load_config tests/test_loader.py::TestLoader::test_load_config_file tests/test_loader.py::TestLoader::test_load_empty_config tests/test_loader.py::TestLoader::test_pip_install_deps tests/test_parser_apiai.py::TestParserApiai::test_call_apiai
opsdroid/parsers/regex.py opsdroid/skills.py MANIFEST.in setup.py opsdroid/parsers/crontab.py opsdroid/const.py opsdroid/parsers/apiai.py opsdroid/configuration/example_configuration.yaml opsdroid/core.py docs/parsers/api.ai.md docs/getting-started.md docs/configuration-reference.md opsdroid/loader.py
opsdroid/parsers/regex.py opsdroid/skills.py MANIFEST.in setup.py opsdroid/parsers/crontab.py opsdroid/const.py opsdroid/parsers/apiai.py opsdroid/configuration/example_configuration.yaml opsdroid/core.py docs/parsers/api.ai.md docs/getting-started.md docs/configuration-reference.md opsdroid/loader.py