```diff
--- test_files/367-original.txt	2025-03-07 19:06:50
+++ test_files/367-modified.txt	2025-03-07 19:06:50
@@ -5,9 +5,14 @@
 from abc import abstractmethod
 
 import inflection
+import typing_extensions as te
 from pydantic import BaseModel, Field
 
+from composio import Composio
+from composio.client.collections import ConnectedAccountModel, CustomAuthParameter
 from composio.client.enums.base import ActionData, SentinalObject, add_runtime_action
+from composio.client.exceptions import ComposioClientError
+from composio.exceptions import ComposioSDKError
 from composio.tools.base.abs import (
     Action,
     ActionRequest,
@@ -18,11 +23,17 @@
 from composio.tools.base.local import LocalToolMixin
 from composio.tools.env.host.shell import Shell
 from composio.tools.env.host.workspace import Browsers, FileManagers, Shells
+from composio.utils import logging
 
 
-ActionCallable = t.Callable
+if t.TYPE_CHECKING:
+    from composio.tools.toolset import ComposioToolSet
 
 
+class InvalidRuntimeAction(ComposioSDKError):
+    """Raise when invalid action definition is found"""
+
+
 class FileModel(BaseModel):
     name: str = Field(
         ...,
@@ -147,6 +158,7 @@
         display_name = f.__name__
 
         file = _file
+        runtime = True
         requires = _requires
         run_on_shell: bool = runs_on_shell
 
@@ -167,11 +179,12 @@
         t.Type[WrappedAction],
         type(inflection.camelize(f.__name__), (WrappedAction,), {}),
     )
-    # TODO(Viraj): Add error handling if docstring is not provided
     cls.__doc__ = f.__doc__
+    cls.description = f.__doc__ or f.__name__  # type: ignore
 
-    existing_actions = []
+    # Normalize app name
     toolname = toolname.upper()
+    existing_actions = []
     if toolname in tool_registry["runtime"]:
         existing_actions = tool_registry["runtime"][toolname].actions()
     tool = _create_tool_class(name=toolname, actions=[cls, *existing_actions])  # type: ignore
@@ -182,10 +195,10 @@
 
 def _is_simple_action(argspec: inspect.FullArgSpec) -> bool:
     """Check if the action is defined with `request_data` and `metadata`"""
-    if "request_data" not in argspec.args and "metadata" not in argspec.args:
+    if "request" not in argspec.args and "metadata" not in argspec.args:
         return False
 
-    if not issubclass(argspec.annotations["request_data"], BaseModel):
+    if not issubclass(argspec.annotations["request"], BaseModel):
         raise ValueError("`request_data` needs to be a `pydantic.BaseModel` object")
 
     if not issubclass(argspec.annotations["return"], BaseModel):
@@ -222,12 +235,8 @@
 
 def _parse_docstring(
     docstr: str,
-) -> t.Tuple[str, t.Dict[str, str], t.Optional[t.Tuple[str, str]],]:
+) -> t.Tuple[str, t.Dict[str, str], t.Optional[t.Tuple[str, str]]]:
     """Parse docstring for descriptions."""
-    if docstr is None:
-        raise ValueError(
-            "Docstring is None, Please provide a docstring for runtime tools"
-        )
     header, *descriptions = docstr.lstrip().rstrip().split("\n")
     params = {}
     returns = None
@@ -246,19 +255,77 @@
     return header, params, returns
 
 
-def _build_executable_from_args(
+def _get_connected_account(
+    app: str, entity_id: str
+) -> t.Optional[ConnectedAccountModel]:
+    try:
+        client = Composio.get_latest()
+        connected_account = client.connected_accounts.get(
+            connection_id=client.get_entity(entity_id).get_connection(app=app).id
+        )
+        return connected_account
+    except ComposioClientError:
+        return None
+
+
+def _get_auth_params(app: str, metadata: t.Dict) -> t.Dict:
+    try:
+        client = Composio.get_latest()
+        connected_account = client.connected_accounts.get(
+            connection_id=client.get_entity(metadata["entity_id"])
+            .get_connection(app=app)
+            .id
+        )
+        connection_params = connected_account.connectionParams
+        return {
+            "entity_id": metadata["entity_id"],
+            "headers": connection_params.headers,
+            "base_url": connection_params.base_url,
+            "query_params": connection_params.queryParams,
+        }
+    except ComposioClientError:
+        logging.get_logger().error(
+            f"Error fetching auth for runtime action of app {app!r}, "
+            "connected account for this account does not exist!"
+        )
+        return {
+            "entity_id": metadata["entity_id"],
+            "subdomain": metadata.pop("subdomain", {}),
+            "headers": metadata.pop("header", {}),
+            "base_url": metadata.pop("base_url", None),
+            "body_params": metadata.pop("body", {}),
+            "path_params": metadata.pop("path", {}),
+            "query_params": metadata.pop("query", {}),
+            **metadata,
+        }
+
+
+def _build_executable_from_args(  # pylint: disable=too-many-statements
     f: t.Callable,
-) -> t.Tuple[t.Callable, t.Type[BaseModel], t.Type[BaseModel], bool,]:
+    app: str,
+) -> t.Tuple[t.Callable, t.Type[BaseModel], t.Type[BaseModel], bool]:
     """Build execute action from function arguments."""
     argspec = inspect.getfullargspec(f)
+    missing_annot = set(argspec.args) - set(argspec.annotations)
+    if len(missing_annot) > 0:
+        raise InvalidRuntimeAction(
+            message=f"Following arguments are missing type annotations: {missing_annot}"
+        )
+
     defaults = dict(
         zip(
             reversed(argspec.annotations),
             reversed(argspec.defaults or []),
         )
     )
+    docstr = getattr(f, "__doc__")
+    if docstr is None:
+        raise InvalidRuntimeAction(
+            message=f"Runtime action `{f.__name__}` is missing docstring"
+        )
+
     header, paramdesc, returns = _parse_docstring(
-        docstr=getattr(f, "__doc__"),
+        docstr=docstr,
     )
     request_schema: t.Dict[str, t.Any] = {
         "__annotations__": {},
@@ -266,26 +333,61 @@
     response_schema: t.Dict[str, t.Any] = {
         "__annotations__": {},
     }
+
     shell_argument = None
+    auth_param = False
+    connected_account_param = False
+    request_executor = False
+    if "return" not in argspec.annotations:
+        raise InvalidRuntimeAction(
+            f"Please add return type on runtime action `{f.__name__}`"
+        )
+
     for arg, annot in argspec.annotations.items():
         if annot is Shell:
             shell_argument = arg
             continue
-        if getattr(annot, "__name__", "") == "Annotated":
+
+        if arg == "auth":
+            auth_param = True
+            continue
+
+        if arg == "connected_account":
+            connected_account_param = True
+            continue
+
+        if arg == "execute_request":
+            request_executor = True
+            continue
+
+        if isinstance(annot, te._AnnotatedAlias):  # pylint: disable=protected-access
             annottype, description, default = _parse_annotated_type(
                 argument=arg,
                 annotation=annot,
             )
+            default = defaults.get(arg, default)
         else:
-            annottype, description = _parse_raw_type(argument=arg, annotation=annot)
-            description = paramdesc.get(arg, description)
-            default = defaults.get(arg, ...)
-            if arg == "return" and returns is not None:
+            annottype, _ = _parse_raw_type(argument=arg, annotation=annot)
+            if arg != "return" and arg not in paramdesc:
+                raise InvalidRuntimeAction(
+                    f"Please provide description for `{arg}` on runtime action `{f.__name__}`"
+                )
+
+            if arg == "return":
+                if returns is None:
+                    raise InvalidRuntimeAction(
+                        f"Please provide description for `{arg}` on runtime action `{f.__name__}`"
+                    )
                 _, description = returns
+            else:
+                description = paramdesc[arg]
 
+            default = defaults.get(arg, ...)
         if arg == "return":
             if returns is not None:
                 arg, _ = returns
+            else:
+                arg = "result"
             response_schema[arg] = Field(default=default, description=description)
             response_schema["__annotations__"][arg] = annottype
             continue
@@ -298,6 +400,7 @@
         (BaseModel,),
         request_schema,
     )
+
     ResponseSchema = type(
         f"{inflection.camelize(f.__name__)}Response",
         (BaseModel,),
@@ -310,11 +413,37 @@
         if shell_argument is not None:
             kwargs[shell_argument] = metadata["workspace"].shells.recent
 
+        if connected_account_param:
+            kwargs["connected_account"] = (
+                _get_connected_account(app=app, entity_id=metadata["entity_id"]) or {}
+            )
+        if auth_param:
+            kwargs["auth"] = _get_auth_params(app=app, metadata=metadata)
+
+        if request_executor:
+            toolset = t.cast("ComposioToolSet", metadata["_toolset"])
+
+            def execute_request(
+                endpoint: str,
+                method: str,
+                body: t.Optional[t.Dict] = None,
+                parameters: t.Optional[t.List[CustomAuthParameter]] = None,
+            ):
+                return toolset.execute_request(
+                    endpoint=endpoint,
+                    method=method,
+                    body=body,
+                    app=app,
+                    parameters=parameters,
+                )
+
+            kwargs["execute_request"] = execute_request
+
         response = f(**kwargs)
         if isinstance(response, BaseModel):
             return response
 
-        rname = returns[0] if returns is not None else "return"
+        rname = returns[0] if returns is not None else "result"
         return ResponseSchema(**{rname: response})
 
     execute.__doc__ = header
@@ -327,34 +456,48 @@
     )
 
 
+def _build_executable_from_request_class(f: t.Callable, app: str) -> t.Callable:
+    def execute(request: BaseModel, metadata: t.Dict) -> BaseModel:
+        """Wrapper for action callable."""
+        auth_data = _get_auth_params(app=app, metadata=metadata)
+        if auth_data is not None:
+            metadata.update(auth_data)
+        return f(request, metadata)
+
+    execute.__name__ = f.__name__
+    execute.__doc__ = f.__doc__
+    return execute
+
+
 def _parse_schemas(
-    f: t.Callable, runs_on_shell: bool
-) -> t.Tuple[t.Callable, t.Type[BaseModel], t.Type[BaseModel], bool,]:
+    f: t.Callable, app: str, runs_on_shell: bool
+) -> t.Tuple[t.Callable, t.Type[BaseModel], t.Type[BaseModel], bool]:
     """Parse action callable schemas."""
     argspec = inspect.getfullargspec(f)
     if _is_simple_action(argspec=argspec):
         return (
-            f,
-            argspec.annotations["request_data"],
+            _build_executable_from_request_class(f=f, app=app),
+            argspec.annotations["request"],
             argspec.annotations["return"],
             runs_on_shell,
         )
-    return _build_executable_from_args(f=f)
+    return _build_executable_from_args(f=f, app=app)
 
 
 def action(
     toolname: str,
     runs_on_shell: bool = False,
-    tags: t.Optional[t.List[str]] = None,
     requires: t.Optional[t.List] = None,
-) -> t.Callable[[ActionCallable], t.Type[RuntimeAction]]:
+    tags: t.Optional[t.List[str]] = None,
+) -> t.Callable[[t.Callable], t.Type[RuntimeAction]]:
     """Marks a callback as wanting to receive the current context object as first argument."""
 
-    def wrapper(f: ActionCallable) -> t.Type[RuntimeAction]:
+    def wrapper(f: t.Callable) -> t.Type[RuntimeAction]:
         """Action wrapper."""
         file = inspect.getfile(f)
-        f, RequestSchema, ResponseSchema, _runs_on_shell = _parse_schemas(
+        f, request_schema, response_schema, _runs_on_shell = _parse_schemas(
             f=f,
+            app=toolname,
             runs_on_shell=runs_on_shell,
         )
         return _wrap(
@@ -362,8 +505,8 @@
             toolname=toolname,
             tags=tags or [],
             file=file,
-            request_schema=RequestSchema,
-            response_schema=ResponseSchema,
+            request_schema=request_schema,
+            response_schema=response_schema,
             runs_on_shell=_runs_on_shell,
             requires=requires,
         )
```
