diff --git a/docs/doc_sources/api_reference/dpctl/index.rst b/docs/doc_sources/api_reference/dpctl/index.rst
index 11f86ecb21..94858c2681 100644
--- a/docs/doc_sources/api_reference/dpctl/index.rst
+++ b/docs/doc_sources/api_reference/dpctl/index.rst
@@ -61,6 +61,7 @@
     has_gpu_devices
     has_cpu_devices
     has_accelerator_devices
+    get_composite_devices
 
 .. rubric:: Enums
 
diff --git a/dpctl/__init__.py b/dpctl/__init__.py
index e4dd710ade..3a80c68a71 100644
--- a/dpctl/__init__.py
+++ b/dpctl/__init__.py
@@ -35,6 +35,7 @@
     SyclSubDeviceCreationError,
 )
 from ._sycl_device_factory import (
+    get_composite_devices,
     get_devices,
     get_num_devices,
     has_accelerator_devices,
@@ -87,6 +88,7 @@
     "has_gpu_devices",
     "has_accelerator_devices",
     "has_host_device",
+    "get_composite_devices",
 ]
 __all__ += [
     "SyclEvent",
diff --git a/dpctl/_backend.pxd b/dpctl/_backend.pxd
index 9b41499160..27a00ef2c0 100644
--- a/dpctl/_backend.pxd
+++ b/dpctl/_backend.pxd
@@ -98,6 +98,8 @@ cdef extern from "syclinterface/dpctl_sycl_enum_types.h":
         _usm_atomic_shared_allocations      'usm_atomic_shared_allocations',
         _host_debuggable                    'host_debuggable',
         _emulated                           'emulated',
+        _is_component                       'is_component',
+        _is_composite                       'is_composite',
 
     ctypedef enum _partition_affinity_domain_type 'DPCTLPartitionAffinityDomainType':
         _not_applicable                     'not_applicable',
@@ -217,6 +219,8 @@ cdef extern from "syclinterface/dpctl_sycl_device_interface.h":
     cdef uint32_t DPCTLDevice_GetPartitionMaxSubDevices(const DPCTLSyclDeviceRef DRef)
     cdef uint32_t DPCTLDevice_GetMaxClockFrequency(const DPCTLSyclDeviceRef DRef)
     cdef uint64_t DPCTLDevice_GetMaxMemAllocSize(const DPCTLSyclDeviceRef DRef)
+    cdef DPCTLSyclDeviceRef DPCTLDevice_GetCompositeDevice(const DPCTLSyclDeviceRef DRef)
+    cdef DPCTLDeviceVectorRef DPCTLDevice_GetComponentDevices(const DPCTLSyclDeviceRef DRef)
 
 
 cdef extern from "syclinterface/dpctl_sycl_device_manager.h":
@@ -238,6 +242,7 @@ cdef extern from "syclinterface/dpctl_sycl_device_manager.h":
     cdef DPCTLSyclContextRef DPCTLDeviceMgr_GetCachedContext(
         const DPCTLSyclDeviceRef DRef)
     cdef int64_t DPCTLDeviceMgr_GetRelativeId(const DPCTLSyclDeviceRef DRef)
+    cdef DPCTLDeviceVectorRef DPCTLDeviceMgr_GetCompositeDevices()
 
 
 cdef extern from "syclinterface/dpctl_sycl_device_selector_interface.h":
@@ -316,6 +321,8 @@ cdef extern from "syclinterface/dpctl_sycl_platform_interface.h":
         const DPCTLSyclPlatformRef)
     cdef DPCTLDeviceVectorRef DPCTLPlatform_GetDevices(
         const DPCTLSyclPlatformRef PRef, _device_type DTy)
+    cdef DPCTLDeviceVectorRef DPCTLPlatform_GetCompositeDevices(
+        const DPCTLSyclPlatformRef PRef)
 
 
 cdef extern from "syclinterface/dpctl_sycl_context_interface.h":
diff --git a/dpctl/_sycl_device.pyx b/dpctl/_sycl_device.pyx
index f8d59a56b0..fef70b5cfb 100644
--- a/dpctl/_sycl_device.pyx
+++ b/dpctl/_sycl_device.pyx
@@ -32,6 +32,8 @@ from ._backend cimport (  # noqa: E211
     DPCTLDevice_CreateSubDevicesEqually,
     DPCTLDevice_Delete,
     DPCTLDevice_GetBackend,
+    DPCTLDevice_GetComponentDevices,
+    DPCTLDevice_GetCompositeDevice,
     DPCTLDevice_GetDeviceType,
     DPCTLDevice_GetDriverVersion,
     DPCTLDevice_GetGlobalMemCacheLineSize,
@@ -795,6 +797,32 @@ cdef class SyclDevice(_SyclDevice):
         cdef _aspect_type AT = _aspect_type._emulated
         return DPCTLDevice_HasAspect(self._device_ref, AT)
 
+    @property
+    def has_aspect_is_component(self):
+        """ Returns ``True`` if this device is a component device, ``False``
+        otherwise. A device with this aspect will have a composite device
+        from which it is descended.
+
+        Returns:
+            bool:
+                Indicates if device is a component device.
+        """
+        cdef _aspect_type AT = _aspect_type._is_component
+        return DPCTLDevice_HasAspect(self._device_ref, AT)
+
+
+    @property
+    def has_aspect_is_composite(self):
+        """ Returns ``True`` if this device is a composite device, ``False``
+        otherwise. A device with this aspect contains component devices.
+
+        Returns:
+            bool:
+                Indicates if device is a composite device.
+        """
+        cdef _aspect_type AT = _aspect_type._is_composite
+        return DPCTLDevice_HasAspect(self._device_ref, AT)
+
     @property
     def image_2d_max_width(self):
         """ Returns the maximum width of a 2D image or 1D image in pixels.
@@ -1520,7 +1548,7 @@ cdef class SyclDevice(_SyclDevice):
                 Created sub-devices.
 
         Raises:
-            dpctl.SyclSubdeviceCreationError:
+            dpctl.SyclSubDeviceCreationError:
                 if sub-devices can not be created.
         """
         cdef DPCTLDeviceVectorRef DVRef = NULL
@@ -1546,7 +1574,7 @@ cdef class SyclDevice(_SyclDevice):
                 Created sub-devices.
 
         Raises:
-            dpctl.SyclSubdeviceCreationError:
+            dpctl.SyclSubDeviceCreationError:
                 if sub-devices can not be created.
         """
         cdef int ncounts = len(counts)
@@ -1592,7 +1620,7 @@ cdef class SyclDevice(_SyclDevice):
                 Created sub-devices.
 
         Raises:
-            dpctl.SyclSubdeviceCreationError:
+            dpctl.SyclSubDeviceCreationError:
                 if sub-devices can not be created.
         """
         cdef DPCTLDeviceVectorRef DVRef = NULL
@@ -1662,7 +1690,7 @@ cdef class SyclDevice(_SyclDevice):
                 If the ``partition`` keyword argument is not specified or
                 the affinity domain string is not legal or is not one of the
                 three supported options.
-            dpctl.SyclSubdeviceCreationError:
+            dpctl.SyclSubDeviceCreationError:
                 If sub-devices can not be created.
         """
         if "partition" not in kwargs:
@@ -1728,6 +1756,43 @@ cdef class SyclDevice(_SyclDevice):
             return None
         return SyclDevice._create(pDRef)
 
+    @property
+    def composite_device(self):
+        """ The composite device for a component device, or ``None`` for a
+        non-component device.
+
+        Returns:
+            dpctl.SyclDevice:
+                The composite :class:`dpctl.SyclDevice` instance for a
+                component device, or ``None`` for a non-component device.
+        """
+        cdef DPCTLSyclDeviceRef CDRef = NULL
+        CDRef = DPCTLDevice_GetCompositeDevice(self._device_ref)
+        if (CDRef is NULL):
+            return None
+        return SyclDevice._create(CDRef)
+
+    def component_devices(self):
+        """ Returns a list of component devices contained in this SYCL device.
+
+        The returned list will be empty if this SYCL device is not a composite
+        device, i.e., if `is_composite` is ``False``.
+
+        Returns:
+            List[:class:`dpctl.SyclDevice`]:
+                List of component devices.
+
+        Raises:
+            ValueError:
+                If the ``DPCTLDevice_GetComponentDevices`` call returned
+                ``NULL`` instead of a ``DPCTLDeviceVectorRef`` object.
+        """
+        cdef DPCTLDeviceVectorRef cDVRef = NULL
+        cDVRef = DPCTLDevice_GetComponentDevices(self._device_ref)
+        if cDVRef is NULL:
+            raise ValueError("Internal error: NULL device vector encountered")
+        return _get_devices(cDVRef)
+
     @property
     def profiling_timer_resolution(self):
         """ Profiling timer resolution.
diff --git a/dpctl/_sycl_device_factory.pxd b/dpctl/_sycl_device_factory.pxd
index e5644ccdbf..6ed5de90e3 100644
--- a/dpctl/_sycl_device_factory.pxd
+++ b/dpctl/_sycl_device_factory.pxd
@@ -32,6 +32,7 @@ cpdef SyclDevice select_cpu_device()
 cpdef SyclDevice select_default_device()
 cpdef SyclDevice select_gpu_device()
 cpdef list get_devices(backend=*, device_type=*)
+cpdef list get_composite_devices()
 cpdef int get_num_devices(backend=*, device_type=*)
 cpdef cpp_bool has_gpu_devices()
 cpdef cpp_bool has_cpu_devices()
diff --git a/dpctl/_sycl_device_factory.pyx b/dpctl/_sycl_device_factory.pyx
index 2d6784c878..ef2f7a4a1a 100644
--- a/dpctl/_sycl_device_factory.pyx
+++ b/dpctl/_sycl_device_factory.pyx
@@ -31,6 +31,7 @@ from ._backend cimport (  # noqa: E211
     DPCTLCPUSelector_Create,
     DPCTLDefaultSelector_Create,
     DPCTLDevice_CreateFromSelector,
+    DPCTLDeviceMgr_GetCompositeDevices,
     DPCTLDeviceMgr_GetDevices,
     DPCTLDeviceMgr_GetNumDevices,
     DPCTLDeviceSelector_Delete,
@@ -62,6 +63,7 @@ __all__ = [
     "has_gpu_devices",
     "has_accelerator_devices",
     "_cached_default_device",
+    "get_composite_devices",
 ]
 
 
@@ -202,6 +204,32 @@ cpdef list get_devices(backend=backend_type.all, device_type=device_type_t.all):
     return devices
 
 
+cpdef list get_composite_devices():
+    """
+    Returns a list of the available composite :class:`dpctl.SyclDevice`
+    instances.
+
+    Only available when `ZE_FLAT_DEVICE_HIERARCHY=COMBINED` is set in
+    the environment, and only for specific Level Zero devices
+    (i.e., those which expose multiple tiles as root devices).
+
+    For more information, see:
+    https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/experimental/sycl_ext_oneapi_composite_device.asciidoc
+
+    Returns:
+        list:
+            A list of available composite :class:`dpctl.SyclDevice` instances.
+    """
+    cdef DPCTLDeviceVectorRef DVRef = NULL
+    cdef list composite_devices
+
+    DVRef = DPCTLDeviceMgr_GetCompositeDevices()
+    composite_devices = _get_devices(DVRef)
+    DPCTLDeviceVector_Delete(DVRef)
+
+    return composite_devices
+
+
 cpdef int get_num_devices(
     backend=backend_type.all, device_type=device_type_t.all
 ):
diff --git a/dpctl/_sycl_platform.pyx b/dpctl/_sycl_platform.pyx
index ab9a2c0489..c27cb63dad 100644
--- a/dpctl/_sycl_platform.pyx
+++ b/dpctl/_sycl_platform.pyx
@@ -37,6 +37,7 @@ from ._backend cimport (  # noqa: E211
     DPCTLPlatform_CreateFromSelector,
     DPCTLPlatform_Delete,
     DPCTLPlatform_GetBackend,
+    DPCTLPlatform_GetCompositeDevices,
     DPCTLPlatform_GetDefaultContext,
     DPCTLPlatform_GetDevices,
     DPCTLPlatform_GetName,
@@ -448,6 +449,38 @@ cdef class SyclPlatform(_SyclPlatform):
 
         return devices
 
+    def get_composite_devices(self):
+        """
+        Returns the list of composite :class:`dpctl.SyclDevice` objects
+        associated with :class:`dpctl.SyclPlatform` instance.
+
+        Returns:
+            list:
+                A :obj:`list` of composite :class:`dpctl.SyclDevice` objects
+                that belong to this platform.
+
+        Raises:
+            ValueError:
+                If the ``DPCTLPlatform_GetCompositeDevices`` call returned
+                ``NULL`` instead of a ``DPCTLDeviceVectorRef`` object.
+        """
+        cdef DPCTLDeviceVectorRef DVRef = NULL
+        cdef size_t num_devs
+        cdef size_t i
+        cdef DPCTLSyclDeviceRef DRef
+
+        DVRef = DPCTLPlatform_GetCompositeDevices(self.get_platform_ref())
+        if (DVRef is NULL):
+            raise ValueError("Internal error: NULL device vector encountered")
+        num_devs = DPCTLDeviceVector_Size(DVRef)
+        composite_devices = []
+        for i in range(num_devs):
+            DRef = DPCTLDeviceVector_GetAt(DVRef, i)
+            composite_devices.append(SyclDevice._create(DRef))
+        DPCTLDeviceVector_Delete(DVRef)
+
+        return composite_devices
+
 
 def lsplatform(verbosity=0):
     """
diff --git a/dpctl/tests/test_sycl_device.py b/dpctl/tests/test_sycl_device.py
index 35fd3f03c9..0d8025c060 100644
--- a/dpctl/tests/test_sycl_device.py
+++ b/dpctl/tests/test_sycl_device.py
@@ -165,6 +165,8 @@ def test_equal():
     "usm_atomic_host_allocations",
     "usm_atomic_shared_allocations",
     "emulated",
+    "is_component",
+    "is_composite",
 ]
 
 # SYCL 2020 spec aspects not presently
@@ -310,3 +312,32 @@ def test_get_unpartitioned_parent_device_from_sub_device():
         pytest.skip("Default device can not be partitioned")
     assert isinstance(sdevs, list) and len(sdevs) > 0
     assert dev == sdevs[0].get_unpartitioned_parent_device()
+
+
+def test_composite_device_method():
+    """
+    Test that the composite_device method returns a composite
+    device found in ``dpctl.get_composite_devices()``
+    """
+    devices = dpctl.get_devices()
+    composite_devices = dpctl.get_composite_devices()
+    for d in devices:
+        if d.has_aspect_is_component:
+            Cd = d.composite_device
+            assert Cd in composite_devices
+
+
+def test_get_component_devices_from_composite():
+    """
+    Test that the component_devices method returns component
+    root devices.
+    """
+    devices = dpctl.get_devices()
+    composite_devices = dpctl.get_composite_devices()
+    for Cd in composite_devices:
+        assert Cd.has_aspect_is_composite
+        component_devices = Cd.component_devices()
+        for d in component_devices:
+            assert d.has_aspect_is_component
+            # component devices are root devices
+            assert d in devices
diff --git a/dpctl/tests/test_sycl_device_factory.py b/dpctl/tests/test_sycl_device_factory.py
index 8bd9d43f0e..3317ba17fb 100644
--- a/dpctl/tests/test_sycl_device_factory.py
+++ b/dpctl/tests/test_sycl_device_factory.py
@@ -185,3 +185,13 @@ def test_get_devices_with_device_type_str(device_type_str):
             assert dev == devices[i]
     else:
         pytest.skip()
+
+
+def test_get_composite_devices():
+    devices = dpctl.get_composite_devices()
+    if devices:
+        num_devices = len(devices)
+        for i in range(num_devices):
+            assert devices[i].has_aspect_is_composite
+    else:
+        pytest.skip()
diff --git a/dpctl/tests/test_sycl_platform.py b/dpctl/tests/test_sycl_platform.py
index ef0a6b0e5c..66d85db13c 100644
--- a/dpctl/tests/test_sycl_platform.py
+++ b/dpctl/tests/test_sycl_platform.py
@@ -259,3 +259,20 @@ def test_platform_get_devices_enum_device_type():
                 devices = p.get_devices(device_type=dty)
                 if len(devices):
                     assert (d.device_type == dty for d in devices)
+
+
+def test_platform_get_composite_devices():
+    platforms = dpctl.get_platforms()
+    if platforms:
+        for p in platforms:
+            composite_devices = p.get_composite_devices()
+            if not composite_devices:
+                pass
+            devices = p.get_devices()
+            for Cd in composite_devices:
+                assert Cd.has_aspect_is_composite
+                component_devices = Cd.component_devices()
+                # all component devices are root devices
+                assert all(d in devices for d in component_devices)
+    else:
+        pytest.skip("No platforms available")
diff --git a/libsyclinterface/helper/source/dpctl_utils_helper.cpp b/libsyclinterface/helper/source/dpctl_utils_helper.cpp
index fe3bbd86cb..88c1385a26 100644
--- a/libsyclinterface/helper/source/dpctl_utils_helper.cpp
+++ b/libsyclinterface/helper/source/dpctl_utils_helper.cpp
@@ -218,6 +218,12 @@ std::string DPCTL_AspectToStr(aspect aspectTy)
     case aspect::emulated:
         ss << "emulated";
         break;
+    case aspect::ext_oneapi_is_component:
+        ss << "is_component";
+        break;
+    case aspect::ext_oneapi_is_composite:
+        ss << "is_composite";
+        break;
     default:
         throw std::runtime_error("Unsupported aspect type");
     }
@@ -287,6 +293,12 @@ aspect DPCTL_StrToAspectType(const std::string &aspectTyStr)
     else if (aspectTyStr == "emulated") {
         aspectTy = aspect::emulated;
     }
+    else if (aspectTyStr == "is_component") {
+        aspectTy = aspect::ext_oneapi_is_component;
+    }
+    else if (aspectTyStr == "is_composite") {
+        aspectTy = aspect::ext_oneapi_is_composite;
+    }
     else {
         // \todo handle the error
         throw std::runtime_error("Unsupported aspect type");
@@ -335,6 +347,10 @@ aspect DPCTL_DPCTLAspectTypeToSyclAspect(DPCTLSyclAspectType AspectTy)
         return aspect::host_debuggable;
     case DPCTLSyclAspectType::emulated:
         return aspect::emulated;
+    case DPCTLSyclAspectType::is_component:
+        return aspect::ext_oneapi_is_component;
+    case DPCTLSyclAspectType::is_composite:
+        return aspect::ext_oneapi_is_composite;
     default:
         throw std::runtime_error("Unsupported aspect type");
     }
@@ -381,6 +397,10 @@ DPCTLSyclAspectType DPCTL_SyclAspectToDPCTLAspectType(aspect Aspect)
         return DPCTLSyclAspectType::host_debuggable;
     case aspect::emulated:
         return DPCTLSyclAspectType::emulated;
+    case aspect::ext_oneapi_is_composite:
+        return DPCTLSyclAspectType::is_composite;
+    case aspect::ext_oneapi_is_component:
+        return DPCTLSyclAspectType::is_component;
     default:
         throw std::runtime_error("Unsupported aspect type");
     }
diff --git a/libsyclinterface/include/syclinterface/dpctl_sycl_device_interface.h b/libsyclinterface/include/syclinterface/dpctl_sycl_device_interface.h
index 5f940600ec..6fddb2967f 100644
--- a/libsyclinterface/include/syclinterface/dpctl_sycl_device_interface.h
+++ b/libsyclinterface/include/syclinterface/dpctl_sycl_device_interface.h
@@ -766,4 +766,30 @@ __dpctl_keep size_t *
 DPCTLDevice_GetSubGroupSizes(__dpctl_keep const DPCTLSyclDeviceRef DRef,
                              size_t *res_len);
 
+/*!
+ * @brief Wrapper over
+ * device.get_info<info::device::parent_device>
+ *
+ * @param    DRef           Opaque pointer to a sycl::device
+ * @return   Returns an opaque pointer to the composite device for a
+ * component device, or nullptr if the device is not a component device.
+ */
+DPCTL_API
+__dpctl_give DPCTLSyclDeviceRef
+DPCTLDevice_GetCompositeDevice(__dpctl_keep const DPCTLSyclDeviceRef DRef);
+
+/*!
+ * @brief Returns a vector of component devices that are contained by the
+ * provided composite device. If the device is not a composite device,
+ * returns an empty vector.
+ *
+ * @param    DRef         Opaque pointer to a ``sycl::device``
+ * @return   A #DPCTLDeviceVectorRef containing component
+ * #DPCTLSyclDeviceRef objects
+ * @ingroup DeviceInterface
+ */
+DPCTL_API
+__dpctl_give DPCTLDeviceVectorRef
+DPCTLDevice_GetComponentDevices(__dpctl_keep const DPCTLSyclDeviceRef DRef);
+
 DPCTL_C_EXTERN_C_END
diff --git a/libsyclinterface/include/syclinterface/dpctl_sycl_device_manager.h b/libsyclinterface/include/syclinterface/dpctl_sycl_device_manager.h
index 72618c1b0b..cec8ec076c 100644
--- a/libsyclinterface/include/syclinterface/dpctl_sycl_device_manager.h
+++ b/libsyclinterface/include/syclinterface/dpctl_sycl_device_manager.h
@@ -173,6 +173,17 @@ DPCTL_API
 int64_t
 DPCTLDeviceMgr_GetRelativeId(__dpctl_keep const DPCTLSyclDeviceRef DRef);
 
+/*!
+ * @brief Returns a pointer to a std::vector<sycl::DPCTLSyclDeviceRef>
+ * containing the set of ::DPCTLSyclDeviceRef pointers to the
+ * available composite devices.
+ *
+ * @return   A #DPCTLDeviceVectorRef containing #DPCTLSyclDeviceRef objects
+ * that are composite devices.
+ */
+DPCTL_API
+__dpctl_give DPCTLDeviceVectorRef DPCTLDeviceMgr_GetCompositeDevices();
+
 /*! @} */
 
 DPCTL_C_EXTERN_C_END
diff --git a/libsyclinterface/include/syclinterface/dpctl_sycl_enum_types.h b/libsyclinterface/include/syclinterface/dpctl_sycl_enum_types.h
index e98ded7849..2c2ff3bc09 100644
--- a/libsyclinterface/include/syclinterface/dpctl_sycl_enum_types.h
+++ b/libsyclinterface/include/syclinterface/dpctl_sycl_enum_types.h
@@ -130,7 +130,9 @@ typedef enum
     usm_atomic_host_allocations,
     usm_atomic_shared_allocations,
     host_debuggable,
-    emulated
+    emulated,
+    is_component,
+    is_composite
 } DPCTLSyclAspectType;
 
 /*!
diff --git a/libsyclinterface/include/syclinterface/dpctl_sycl_platform_interface.h b/libsyclinterface/include/syclinterface/dpctl_sycl_platform_interface.h
index 66b22e9663..e803e11071 100644
--- a/libsyclinterface/include/syclinterface/dpctl_sycl_platform_interface.h
+++ b/libsyclinterface/include/syclinterface/dpctl_sycl_platform_interface.h
@@ -193,4 +193,17 @@ __dpctl_give DPCTLDeviceVectorRef
 DPCTLPlatform_GetDevices(__dpctl_keep const DPCTLSyclPlatformRef PRef,
                          DPCTLSyclDeviceType DTy);
 
+/*!
+ * @brief Returns a vector of composite devices associated with sycl::platform
+ * referenced by DPCTLSyclPlatformRef object.
+ *
+ * @param    PRef           The DPCTLSyclPlatformRef pointer.
+ * @return   A DPCTLDeviceVectorRef with composite devices associated with
+ * given PRef.
+ * @ingroup PlatformInterface
+ */
+DPCTL_API
+__dpctl_give DPCTLDeviceVectorRef
+DPCTLPlatform_GetCompositeDevices(__dpctl_keep const DPCTLSyclPlatformRef PRef);
+
 DPCTL_C_EXTERN_C_END
diff --git a/libsyclinterface/source/dpctl_sycl_device_interface.cpp b/libsyclinterface/source/dpctl_sycl_device_interface.cpp
index 2f0fb63b3b..7b1e900b58 100644
--- a/libsyclinterface/source/dpctl_sycl_device_interface.cpp
+++ b/libsyclinterface/source/dpctl_sycl_device_interface.cpp
@@ -849,3 +849,57 @@ DPCTLDevice_GetSubGroupSizes(__dpctl_keep const DPCTLSyclDeviceRef DRef,
     }
     return sizes;
 }
+
+__dpctl_give DPCTLDeviceVectorRef
+DPCTLDevice_GetComponentDevices(__dpctl_keep const DPCTLSyclDeviceRef DRef)
+{
+    using vecTy = std::vector<DPCTLSyclDeviceRef>;
+    vecTy *ComponentDevicesVectorPtr = nullptr;
+    if (DRef) {
+        auto D = unwrap<device>(DRef);
+        try {
+            auto componentDevices =
+                D->get_info<sycl::ext::oneapi::experimental::info::device::
+                                component_devices>();
+            ComponentDevicesVectorPtr = new vecTy();
+            ComponentDevicesVectorPtr->reserve(componentDevices.size());
+            for (const auto &cd : componentDevices) {
+                ComponentDevicesVectorPtr->emplace_back(
+                    wrap<device>(new device(cd)));
+            }
+        } catch (std::exception const &e) {
+            delete ComponentDevicesVectorPtr;
+            error_handler(e, __FILE__, __func__, __LINE__);
+            return nullptr;
+        }
+    }
+    return wrap<vecTy>(ComponentDevicesVectorPtr);
+}
+
+__dpctl_give DPCTLSyclDeviceRef
+DPCTLDevice_GetCompositeDevice(__dpctl_keep const DPCTLSyclDeviceRef DRef)
+{
+    auto D = unwrap<device>(DRef);
+    if (D) {
+        bool is_component = false;
+        try {
+            is_component = D->has(sycl::aspect::ext_oneapi_is_component);
+        } catch (std::exception const &e) {
+            error_handler(e, __FILE__, __func__, __LINE__);
+            return nullptr;
+        }
+        if (!is_component)
+            return nullptr;
+        try {
+            const auto &compositeDevice =
+                D->get_info<sycl::ext::oneapi::experimental::info::device::
+                                composite_device>();
+            return wrap<device>(new device(compositeDevice));
+        } catch (std::exception const &e) {
+            error_handler(e, __FILE__, __func__, __LINE__);
+            return nullptr;
+        }
+    }
+    else
+        return nullptr;
+}
diff --git a/libsyclinterface/source/dpctl_sycl_device_manager.cpp b/libsyclinterface/source/dpctl_sycl_device_manager.cpp
index bac6df7ec0..e87f7dd0ab 100644
--- a/libsyclinterface/source/dpctl_sycl_device_manager.cpp
+++ b/libsyclinterface/source/dpctl_sycl_device_manager.cpp
@@ -112,7 +112,7 @@ struct DeviceCacheBuilder
      * avoid the performance overhead of context creation for every queue.
      *
      * The singleton pattern implemented here ensures that the map is
-     * created once in a thread-safe manner. Since, the map is ony read
+     * created once in a thread-safe manner. Since, the map is only read
      * post-creation we do not need any further protection to ensure
      * thread-safety.
      */
@@ -136,7 +136,7 @@ struct DeviceCacheBuilder
 
                     try {
                         // Per https://github.com/intel/llvm/blob/sycl/sycl/doc/
-                        // extensions/PlatformContext/PlatformContext.adoc
+                        // extensions/supported/sycl_ext_oneapi_default_context.asciidoc
                         // sycl::queue(D) would create default platform context
                         // for capable compiler, sycl::context(D) otherwise
                         auto Q = queue(D);
@@ -357,3 +357,35 @@ int64_t DPCTLDeviceMgr_GetRelativeId(__dpctl_keep const DPCTLSyclDeviceRef DRef)
 
     return -1;
 }
+
+/*!
+ * Returns a list of the available composite devices, or an empty list if
+ * there are none.
+ */
+__dpctl_give DPCTLDeviceVectorRef DPCTLDeviceMgr_GetCompositeDevices()
+{
+    using vecTy = std::vector<DPCTLSyclDeviceRef>;
+    vecTy *Devices = nullptr;
+
+    try {
+        Devices = new std::vector<DPCTLSyclDeviceRef>();
+    } catch (std::exception const &e) {
+        delete Devices;
+        error_handler(e, __FILE__, __func__, __LINE__);
+        return nullptr;
+    }
+
+    try {
+        auto composite_devices =
+            ext::oneapi::experimental::get_composite_devices();
+        Devices->reserve(composite_devices.size());
+        for (const auto &CDev : composite_devices) {
+            Devices->emplace_back(wrap<device>(new device(std::move(CDev))));
+        }
+        return wrap<vecTy>(Devices);
+    } catch (std::exception const &e) {
+        delete Devices;
+        error_handler(e, __FILE__, __func__, __LINE__);
+        return nullptr;
+    }
+}
diff --git a/libsyclinterface/source/dpctl_sycl_platform_interface.cpp b/libsyclinterface/source/dpctl_sycl_platform_interface.cpp
index 71234d420d..f6ab657834 100644
--- a/libsyclinterface/source/dpctl_sycl_platform_interface.cpp
+++ b/libsyclinterface/source/dpctl_sycl_platform_interface.cpp
@@ -316,3 +316,39 @@ DPCTLPlatform_GetDevices(__dpctl_keep const DPCTLSyclPlatformRef PRef,
         return nullptr;
     }
 }
+
+__dpctl_give DPCTLDeviceVectorRef
+DPCTLPlatform_GetCompositeDevices(__dpctl_keep const DPCTLSyclPlatformRef PRef)
+{
+    auto P = unwrap<platform>(PRef);
+    if (!P) {
+        error_handler("Cannot retrieve composite devices from "
+                      "DPCTLSyclPlatformRef as input is a nullptr.",
+                      __FILE__, __func__, __LINE__);
+        return nullptr;
+    }
+
+    using vecTy = std::vector<DPCTLSyclDeviceRef>;
+    vecTy *DevicesVectorPtr = nullptr;
+    try {
+        DevicesVectorPtr = new vecTy();
+    } catch (std::exception const &e) {
+        delete DevicesVectorPtr;
+        error_handler(e, __FILE__, __func__, __LINE__);
+        return nullptr;
+    }
+
+    try {
+        auto composite_devices = P->ext_oneapi_get_composite_devices();
+        DevicesVectorPtr->reserve(composite_devices.size());
+        for (const auto &Dev : composite_devices) {
+            DevicesVectorPtr->emplace_back(
+                wrap<device>(new device(std::move(Dev))));
+        }
+        return wrap<vecTy>(DevicesVectorPtr);
+    } catch (std::exception const &e) {
+        delete DevicesVectorPtr;
+        error_handler(e, __FILE__, __func__, __LINE__);
+        return nullptr;
+    }
+}
diff --git a/libsyclinterface/tests/test_sycl_device_aspects.cpp b/libsyclinterface/tests/test_sycl_device_aspects.cpp
index adbe867b56..8c0ffe1f16 100644
--- a/libsyclinterface/tests/test_sycl_device_aspects.cpp
+++ b/libsyclinterface/tests/test_sycl_device_aspects.cpp
@@ -127,7 +127,11 @@ auto build_params()
             std::make_pair("usm_atomic_shared_allocations",
                            sycl::aspect::usm_atomic_shared_allocations),
             std::make_pair("host_debuggable", sycl::aspect::host_debuggable),
-            std::make_pair("emulated", sycl::aspect::emulated));
+            std::make_pair("emulated", sycl::aspect::emulated),
+            std::make_pair("is_component",
+                           sycl::aspect::ext_oneapi_is_component),
+            std::make_pair("is_composite",
+                           sycl::aspect::ext_oneapi_is_composite));
 
     auto pairs =
         build_param_pairs<const char *, std::pair<const char *, sycl::aspect>,
diff --git a/libsyclinterface/tests/test_sycl_device_interface.cpp b/libsyclinterface/tests/test_sycl_device_interface.cpp
index ee44f0b15a..49783df694 100644
--- a/libsyclinterface/tests/test_sycl_device_interface.cpp
+++ b/libsyclinterface/tests/test_sycl_device_interface.cpp
@@ -539,6 +539,18 @@ TEST_P(TestDPCTLSyclDeviceInterface, ChkGetGlobalMemCacheType)
                  res == DPCTL_MEM_CACHE_TYPE_READ_WRITE));
 }
 
+TEST_P(TestDPCTLSyclDeviceInterface, ChkGetCompositeDevice)
+{
+    DPCTLSyclDeviceRef CDRef = nullptr;
+    EXPECT_NO_FATAL_FAILURE(CDRef = DPCTLDevice_GetCompositeDevice(DRef));
+    if (DPCTLDevice_HasAspect(DRef, DPCTLSyclAspectType::is_component)) {
+        EXPECT_TRUE(CDRef != nullptr);
+    }
+    else {
+        EXPECT_TRUE(CDRef == nullptr);
+    }
+}
+
 INSTANTIATE_TEST_SUITE_P(DPCTLDeviceFns,
                          TestDPCTLSyclDeviceInterface,
                          ::testing::Values("opencl",
@@ -898,3 +910,18 @@ TEST_F(TestDPCTLSyclDeviceNullArgs, ChkGetSubGroupSizes)
     ASSERT_TRUE(sg_sizes == nullptr);
     ASSERT_TRUE(sg_sizes_len == 0);
 }
+
+TEST_F(TestDPCTLSyclDeviceNullArgs, ChkGetComponentDevices)
+{
+    DPCTLDeviceVectorRef cDVRef = nullptr;
+    EXPECT_NO_FATAL_FAILURE(cDVRef =
+                                DPCTLDevice_GetComponentDevices(Null_DRef));
+    ASSERT_TRUE(cDVRef == nullptr);
+}
+
+TEST_F(TestDPCTLSyclDeviceNullArgs, ChkGetCompositeDevice)
+{
+    DPCTLSyclDeviceRef CDRef = nullptr;
+    EXPECT_NO_FATAL_FAILURE(CDRef = DPCTLDevice_GetCompositeDevice(Null_DRef));
+    EXPECT_TRUE(CDRef == nullptr);
+}
diff --git a/libsyclinterface/tests/test_sycl_device_manager.cpp b/libsyclinterface/tests/test_sycl_device_manager.cpp
index f0fff04c64..0ce19124c4 100644
--- a/libsyclinterface/tests/test_sycl_device_manager.cpp
+++ b/libsyclinterface/tests/test_sycl_device_manager.cpp
@@ -316,3 +316,49 @@ TEST_F(TestDPCTLDeviceMgrNullReference, ChkGetPositionInDevices)
     EXPECT_NO_FATAL_FAILURE(
         DPCTLDeviceMgr_GetPositionInDevices(nullDRef, mask));
 }
+
+struct TestDPCTLGetCompositeDevices : public ::testing::Test
+{
+    DPCTLDeviceVectorRef DV = nullptr;
+    size_t nDevices = 0;
+
+    TestDPCTLGetCompositeDevices()
+    {
+        EXPECT_NO_FATAL_FAILURE(DV = DPCTLDeviceMgr_GetCompositeDevices());
+        EXPECT_TRUE(DV != nullptr);
+        EXPECT_NO_FATAL_FAILURE(nDevices = DPCTLDeviceVector_Size(DV));
+    }
+
+    void SetUp()
+    {
+        if (!nDevices) {
+            GTEST_SKIP_("Skipping as no composite devices available");
+        }
+    }
+
+    ~TestDPCTLGetCompositeDevices()
+    {
+        EXPECT_NO_FATAL_FAILURE(DPCTLDeviceVector_Clear(DV));
+        EXPECT_NO_FATAL_FAILURE(DPCTLDeviceVector_Delete(DV));
+    }
+};
+
+TEST_F(TestDPCTLGetCompositeDevices, ChkGetAt)
+{
+    for (auto i = 0ul; i < nDevices; ++i) {
+        DPCTLSyclDeviceRef DRef = nullptr;
+        EXPECT_NO_FATAL_FAILURE(DRef = DPCTLDeviceVector_GetAt(DV, i));
+        ASSERT_TRUE(DRef != nullptr);
+    }
+}
+
+TEST_F(TestDPCTLGetCompositeDevices, ChkCompositeAspect)
+{
+    for (auto i = 0ul; i < nDevices; ++i) {
+        DPCTLSyclDeviceRef DRef = nullptr;
+        EXPECT_NO_FATAL_FAILURE(DRef = DPCTLDeviceVector_GetAt(DV, i));
+        ASSERT_TRUE(DRef != nullptr);
+        ASSERT_TRUE(
+            DPCTLDevice_HasAspect(DRef, DPCTLSyclAspectType::is_composite));
+    }
+}
diff --git a/libsyclinterface/tests/test_sycl_platform_interface.cpp b/libsyclinterface/tests/test_sycl_platform_interface.cpp
index 8bd100669b..3a1b970f63 100644
--- a/libsyclinterface/tests/test_sycl_platform_interface.cpp
+++ b/libsyclinterface/tests/test_sycl_platform_interface.cpp
@@ -113,6 +113,28 @@ void check_platform_get_devices(__dpctl_keep const DPCTLSyclPlatformRef PRef)
     EXPECT_NO_FATAL_FAILURE(DPCTLDeviceVector_Delete(DVRef));
 }
 
+void check_platform_get_composite_devices(
+    __dpctl_keep const DPCTLSyclPlatformRef PRef)
+{
+    DPCTLDeviceVectorRef CDVRef = nullptr;
+    size_t nCDevices = 0;
+
+    EXPECT_NO_FATAL_FAILURE(CDVRef = DPCTLPlatform_GetCompositeDevices(PRef));
+    EXPECT_TRUE(CDVRef != nullptr);
+    EXPECT_NO_FATAL_FAILURE(nCDevices = DPCTLDeviceVector_Size(CDVRef));
+    for (auto i = 0ul; i < nCDevices; ++i) {
+        DPCTLSyclDeviceRef CDRef = nullptr;
+        EXPECT_NO_FATAL_FAILURE(CDRef = DPCTLDeviceVector_GetAt(CDVRef, i));
+        ASSERT_TRUE(CDRef != nullptr);
+        ASSERT_TRUE(
+            DPCTLDevice_HasAspect(CDRef, DPCTLSyclAspectType::is_composite));
+        EXPECT_NO_FATAL_FAILURE(DPCTLDevice_Delete(CDRef));
+    }
+
+    EXPECT_NO_FATAL_FAILURE(DPCTLDeviceVector_Clear(CDVRef));
+    EXPECT_NO_FATAL_FAILURE(DPCTLDeviceVector_Delete(CDVRef));
+}
+
 } // namespace
 
 struct TestDPCTLSyclPlatformInterface
@@ -308,6 +330,11 @@ TEST_P(TestDPCTLSyclPlatformInterface, ChkGetDevices)
     check_platform_get_devices(PRef);
 }
 
+TEST_P(TestDPCTLSyclPlatformInterface, ChkGetCompositeDevices)
+{
+    check_platform_get_composite_devices(PRef);
+}
+
 TEST_F(TestDPCTLSyclDefaultPlatform, ChkGetName) { check_platform_name(PRef); }
 
 TEST_F(TestDPCTLSyclDefaultPlatform, ChkGetVendor)