diff --git a/src/planner/Algo.cpp b/src/planner/Algo.cpp
index fbb80ea52b6917589d0963b61be80650e8b4f32e..ae3c678568c4f3210b8918c4ad9f59ef98fb2d99 100644
--- a/src/planner/Algo.cpp
+++ b/src/planner/Algo.cpp
@@ -5,10 +5,50 @@
  */
 
 #include "planner/Algo.h"
-
+#include "util/ToJson.h"
 namespace nebula {
 namespace graph {
 
+
+std::unique_ptr<PlanNodeDescription> ConjunctPath::explain() const {
+    auto desc = BiInputNode::explain();
+    switch (pathKind_) {
+        case PathKind::kBiBFS: {
+            addDescription("kind", "BFS", desc.get());
+            break;
+        }
+        case PathKind::kBiDijkstra: {
+            addDescription("kind", "Dijkstra", desc.get());
+            break;
+        }
+        case PathKind::kFloyd: {
+            addDescription("kind", "Floyd", desc.get());
+            break;
+        }
+        case PathKind::kAllPaths: {
+            addDescription("kind", "AllPath", desc.get());
+            break;
+        }
+    }
+    addDescription("conditionalVar", util::toJson(conditionalVar_), desc.get());
+    addDescription("noloop", util::toJson(noLoop_), desc.get());
+    return desc;
+}
+
+std::unique_ptr<PlanNodeDescription> ProduceAllPaths::explain() const {
+    auto desc = SingleDependencyNode::explain();
+    addDescription("noloop ", util::toJson(noLoop_), desc.get());
+    return desc;
+}
+
+std::unique_ptr<PlanNodeDescription> CartesianProduct::explain() const {
+    auto desc = SingleDependencyNode::explain();
+    for (size_t i = 0; i < inputVars_.size(); ++i) {
+        addDescription("var", folly::toJson(util::toJson(inputVars_[i])), desc.get());
+    }
+    return desc;
+}
+
 Status CartesianProduct::addVar(std::string varName) {
     auto checkName = [&varName](auto var) { return var->name == varName; };
     if (std::find_if(inputVars_.begin(), inputVars_.end(), checkName) != inputVars_.end()) {
diff --git a/src/planner/Algo.h b/src/planner/Algo.h
index fa8e07f3dbf7f13d2eac03e4f4ad2e591131d0dc..d2bf0cb6ecae5b7fb91335d565eb648e7e2a20ce 100644
--- a/src/planner/Algo.h
+++ b/src/planner/Algo.h
@@ -75,6 +75,7 @@ public:
     void setNoLoop(bool noLoop) {
         noLoop_ = noLoop;
     }
+    std::unique_ptr<PlanNodeDescription> explain() const override;
 
 private:
     ConjunctPath(QueryContext* qctx,
@@ -106,6 +107,7 @@ public:
     void setNoLoop(bool noLoop) {
         noLoop_ = noLoop;
     }
+    std::unique_ptr<PlanNodeDescription> explain() const override;
 
 private:
     ProduceAllPaths(QueryContext* qctx, PlanNode* input)
@@ -128,6 +130,7 @@ public:
     std::vector<std::vector<std::string>> allColNames() const {
         return allColNames_;
     }
+    std::unique_ptr<PlanNodeDescription> explain() const override;
 
 private:
     CartesianProduct(QueryContext* qctx, PlanNode* input)