Repository: antgroup/agentUniverse (language: python)

Issue:
compress pictures



Discussion / hints:

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 54bfed04..7ec09f51 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,21 @@ Note - Additional remarks regarding the version.
 ***************************************************
 
 # Version Update History
+## [0.0.9] - 2024-06-14
+### Added
+- Added standard integration for Claude and Ollama LLM components
+- Added new Qwen embedding module
+- Added default agents for ReAct-Type and NL2API-Type
+
+### Note
+- Added new use cases
+  - RAG-Type Agent Examples: Legal Consultation Agent
+  - ReAct-Type Agent Examples: Python Code Generation and Execution Agent
+  - Multi-Agent: Discussion Group Based on Multi-Turn Multi-Agent Mode
+
+  For more details, please refer to the use case section in the user documentation.
+- Some code optimizations and documentation updates.
+
 ## [0.0.8] - 2024-06-06
 ### Added
 - Introduced a new monitor module
diff --git a/CHANGELOG_zh.md b/CHANGELOG_zh.md
index f938da24..600479be 100644
--- a/CHANGELOG_zh.md
+++ b/CHANGELOG_zh.md
@@ -24,6 +24,21 @@ Note - 对于版本的额外说明。
 ***************************************************
 
 # 版本更新记录
+## [0.0.9] - 2024-06-14
+### Added
+- LLM组件新增claude、ollama标准接入
+- 新增qwen embedding模块
+- 新增ReAct、nl2api默认agent
+
+### Note
+- 新增使用案例
+  - RAG类Agent案例-法律咨询Agent
+  - ReAct类Agent案例-Python代码生成与执行Agent
+  - 多智能体案例-基于多轮多Agent的讨论小组
+
+  详情请看用户文档案例部分。
+- 部分代码优化与文档更新
+
 ## [0.0.8] - 2024-06-06
 ### Added
 - 新增monitor模块
diff --git a/README.md b/README.md
index 977ad774..ee6656b2 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@ Language version: [English](./README.md) | [中文](./README_zh.md) | [日本語
 ![](https://img.shields.io/badge/framework-agentUniverse-pink)
 ![](https://img.shields.io/badge/python-3.10%2B-blue?logo=Python)
 [![](https://img.shields.io/badge/%20license-Apache--2.0-yellow)](LICENSE)
-[![Static Badge](https://img.shields.io/badge/pypi-v0.0.8-blue?logo=pypi)](https://pypi.org/project/agentUniverse/)
+[![Static Badge](https://img.shields.io/badge/pypi-v0.0.9-blue?logo=pypi)](https://pypi.org/project/agentUniverse/)
 
 ![](docs/guidebook/_picture/logo_bar.jpg)
 ****************************************
@@ -44,6 +44,11 @@ We will show you how to:
 * Quickly serve the agent
 For details, please read [Quick Start](docs/guidebook/en/1_3_Quick_Start.md).
 
+## Use Cases
+[Legal Consultation Agent](./docs/guidebook/en/7_1_1_Legal_Consultation_Case.md)
+[Python Code Generation and Execution Agent](./docs/guidebook/en/7_1_1_Python_Auto_Runner.md)
+[Discussion Group Based on Multi-Turn Multi-Agent Mode](./docs/guidebook/en/6_2_1_Discussion_Group.md)
+
 ## Guidebook
 For more detailed information, please refer to the [Guidebook](docs/guidebook/en/0_index.md).
 
diff --git a/README_jp.md b/README_jp.md
index 967e2154..ec284e38 100644
--- a/README_jp.md
+++ b/README_jp.md
@@ -5,7 +5,7 @@
 ![](https://img.shields.io/badge/framework-agentUniverse-pink)
 ![](https://img.shields.io/badge/python-3.10%2B-blue?logo=Python)
 [![](https://img.shields.io/badge/%20license-Apache--2.0-yellow)](LICENSE)
-[![Static Badge](https://img.shields.io/badge/pypi-v0.0.8-blue?logo=pypi)](https://pypi.org/project/agentUniverse/)
+[![Static Badge](https://img.shields.io/badge/pypi-v0.0.9-blue?logo=pypi)](https://pypi.org/project/agentUniverse/)
 
 ![](docs/guidebook/_picture/logo_bar.jpg)
 ****************************************
@@ -43,6 +43,11 @@ pip install agentUniverse
 * エージェントを迅速に提供する
 詳細は、[クイックスタート](docs/guidebook/en/1_3_Quick_Start.md)をご覧ください。
 
+## 使用ケース
+[法律相談Agent](./docs/guidebook/en/7_1_1_Legal_Consultation_Case.md)
+[Pythonコード生成と実行Agent](./docs/guidebook/en/7_1_1_Python_Auto_Runner.md)
+[多回多Agentによるディスカッショングループ](./docs/guidebook/en/6_2_1_Discussion_Group.md)
+
 ## ガイドブック
 詳細情報については、[ガイドブック](docs/guidebook/en/0_index.md)を参照してください。
 
diff --git a/README_zh.md b/README_zh.md
index 17763f6e..d35db732 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -5,7 +5,7 @@
 ![](https://img.shields.io/badge/framework-agentUniverse-pink)
 ![](https://img.shields.io/badge/python-3.10%2B-blue?logo=Python)
 [![](https://img.shields.io/badge/%20license-Apache--2.0-yellow)](LICENSE)
-[![Static Badge](https://img.shields.io/badge/pypi-v0.0.8-blue?logo=pypi)](https://pypi.org/project/agentUniverse/)
+[![Static Badge](https://img.shields.io/badge/pypi-v0.0.9-blue?logo=pypi)](https://pypi.org/project/agentUniverse/)
 
 ![](docs/guidebook/_picture/logo_bar.jpg)
 ****************************************
@@ -47,6 +47,11 @@ pip install agentUniverse
 
 详情请阅读[快速开始](docs/guidebook/zh/1_3_%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B.md) 。
 
+## 使用案例
+[法律咨询Agent](./docs/guidebook/zh/7_1_1_法律咨询案例.md)
+[Python代码生成与执行Agent](./docs/guidebook/zh/7_1_1_Python自动执行案例.md)
+[基于多轮多Agent的讨论小组](./docs/guidebook/zh/6_2_1_讨论组.md)
+
 ## 用户指南
 更多详细信息，请参阅[指南](docs/guidebook/zh/0_%E7%9B%AE%E5%BD%95.md) 。
 
diff --git a/agentuniverse/agent/action/knowledge/embedding/dashscope_embedding.py b/agentuniverse/agent/action/knowledge/embedding/dashscope_embedding.py
new file mode 100644
index 00000000..7cab3b0b
--- /dev/null
+++ b/agentuniverse/agent/action/knowledge/embedding/dashscope_embedding.py
@@ -0,0 +1,156 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/6/12 11:43
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: dashscope_embedding.py
+import aiohttp
+import requests
+from typing import List, Generator, Optional
+import json
+
+from agentuniverse.base.util.env_util import get_from_env
+from agentuniverse.agent.action.knowledge.embedding.embedding import Embedding
+
+# Dashscope support max 25 string in one batch, each string max tokens is 2048.
+DASHSCOPE_MAX_BATCH_SIZE = 25
+DASHSCOPE_EMBEDDING_URL = "https://dashscope.aliyuncs.com/api/v1/services/embeddings/text-embedding/text-embedding"
+
+
+def batched(inputs: List,
+            batch_size: int = DASHSCOPE_MAX_BATCH_SIZE) -> Generator[List, None, None]:
+    # Split input string list, due to dashscope support 25 strings in one call.
+    for i in range(0, len(inputs), batch_size):
+        yield inputs[i:i + batch_size]
+
+
+class DashscopeEmbedding(Embedding):
+    """The Dashscope embedding class."""
+    dashscope_api_key: Optional[str] = None
+
+    def __init__(self, **kwargs):
+        """Initialize the dashscope embedding class, need dashscope api key."""
+        super().__init__(**kwargs)
+        self.dashscope_api_key = get_from_env("DASHSCOPE_API_KEY")
+        if not self.dashscope_api_key:
+            raise Exception("No DASHSCOPE_API_KEY in your environment.")
+
+
+    def get_embeddings(self, texts: List[str]) -> List[List[float]]:
+        """
+        Retrieve text embeddings for a list of input texts.
+
+        This function interfaces with the DashScope embedding API to obtain
+        embeddings for a batch of input texts. It handles batching of input texts
+        to ensure efficient API calls. Each text is processed using the specified
+        embedding model.
+
+        Args:
+            texts (List[str]): A list of input texts to be embedded.
+
+        Returns:
+            List[List[float]]: A list of embeddings corresponding to the input texts.
+
+        Raises:
+            Exception: If the API call to DashScope fails, an exception is raised with
+                       the respective error code and message.
+        """
+        def post(post_params):
+            response = requests.post(
+                url=DASHSCOPE_EMBEDDING_URL,
+                headers={
+                    "Content-Type": "application/json",
+                    "Authorization": f"Bearer {self.dashscope_api_key}"
+                },
+                data=json.dumps(post_params, ensure_ascii=False).encode(
+                    "utf-8"),
+                timeout=120
+            )
+            resp_json = response.json()
+            return resp_json
+
+        result = []
+        post_params = {
+            "model": self.embedding_model_name,
+            "input": {},
+            "parameters": {
+                "text_type": "query"
+            }
+        }
+
+        for batch in batched(texts):
+            post_params["input"]["texts"] = batch
+            resp_json: dict = post(post_params)
+            data = resp_json.get("output")
+            if data:
+                data = data["embeddings"]
+                batch_result = [d['embedding'] for d in data if 'embedding' in d]
+                result += batch_result
+            else:
+                error_code = resp_json.get("code", "")
+                error_message = resp_json.get("message", "")
+                raise Exception(f"Failed to call dashscope embedding api, "
+                                f"error code:{error_code}, "
+                                f"error message:{error_message}")
+        return result
+
+    async def async_get_embeddings(self, texts: List[str]) -> List[List[float]]:
+        """
+        Async version of get_embeddings.
+
+        This function interfaces with the DashScope embedding API to obtain
+        embeddings for a batch of input texts. It handles batching of input texts
+        to ensure efficient API calls. Each text is processed using the specified
+        embedding model.
+
+        Args:
+            texts (List[str]): A list of input texts to be embedded.
+
+        Returns:
+            List[List[float]]: A list of embeddings corresponding to the input texts.
+
+        Raises:
+            Exception: If the API call to DashScope fails, an exception is raised with
+                       the respective error code and message.
+        """
+        async def async_post(post_params):
+            async with aiohttp.ClientSession() as session:
+                async with await session.post(
+                        url=DASHSCOPE_EMBEDDING_URL,
+                        headers={
+                            "Content-Type": "application/json",
+                            "Authorization": f"Bearer {self.dashscope_api_key}"
+                        },
+                        data=json.dumps(post_params, ensure_ascii=False).encode(
+                            "utf-8"),
+                        timeout=120,
+                ) as resp:
+                    resp_json = await resp.json()
+            return resp_json
+
+        result = []
+        post_params = {
+            "model": self.embedding_model_name,
+            "input": {},
+            "parameters": {
+                "text_type": "query"
+            }
+        }
+
+        for batch in batched(texts):
+            post_params["input"]["texts"] = batch
+            resp_json: dict = await async_post(post_params)
+            data = resp_json.get("output")
+            if data:
+                data = data["embeddings"]
+                batch_result = [d['embedding'] for d in data if
+                                'embedding' in d]
+                result += batch_result
+            else:
+                error_code = resp_json.get("code", "")
+                error_message = resp_json.get("message", "")
+                raise Exception(f"Failed to call dashscope embedding api, "
+                                f"error code:{error_code}, "
+                                f"error message:{error_message}")
+        return result
\ No newline at end of file
diff --git a/agentuniverse/agent/action/knowledge/embedding/openai_embedding.py b/agentuniverse/agent/action/knowledge/embedding/openai_embedding.py
index 7fa660cc..f54bbd0d 100644
--- a/agentuniverse/agent/action/knowledge/embedding/openai_embedding.py
+++ b/agentuniverse/agent/action/knowledge/embedding/openai_embedding.py
@@ -5,6 +5,7 @@
 # @Author  : wangchongshi
 # @Email   : wangchongshi.wcs@antgroup.com
 # @FileName: openai_embedding.py
+
 from typing import List, Optional, Any
 
 from langchain_community.embeddings.openai import OpenAIEmbeddings
diff --git a/agentuniverse/agent/action/tool/tool.py b/agentuniverse/agent/action/tool/tool.py
index 2190592b..a005a41a 100644
--- a/agentuniverse/agent/action/tool/tool.py
+++ b/agentuniverse/agent/action/tool/tool.py
@@ -73,6 +73,24 @@ def input_check(self, kwargs: dict) -> None:
             if key not in kwargs.keys():
                 raise Exception(f'{self.get_instance_code()} - The input must include key: {key}.')
 
+    def langchain_run(self, *args, callbacks=None, **kwargs):
+        """The callable method that runs the tool."""
+        kwargs["callbacks"] = callbacks
+        tool_input = ToolInput(kwargs)
+        parse_result = self.parse_react_input(args[0])
+        for key in self.input_keys:
+            tool_input.add_data(key, parse_result[key])
+        return self.execute(tool_input)
+
+    def parse_react_input(self, input_str: str):
+        """
+            parse react string to you input
+            you can define your own logic here by override this function
+        """
+        return {
+            self.input_keys[0]: input_str
+        }
+
     @abstractmethod
     def execute(self, tool_input: ToolInput):
         raise NotImplementedError
@@ -80,7 +98,7 @@ def execute(self, tool_input: ToolInput):
     def as_langchain(self) -> LangchainTool:
         """Convert the agentUniverse(aU) tool class to the langchain tool class."""
         return LangchainTool(name=self.name,
-                             func=self.run,
+                             func=self.langchain_run,
                              description=self.description)
 
     def get_instance_code(self) -> str:
diff --git a/agentuniverse/agent/default/nl2api_agent/__init__.py b/agentuniverse/agent/default/nl2api_agent/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/agentuniverse/agent/default/nl2api_agent/default_cn_prompt.yaml b/agentuniverse/agent/default/nl2api_agent/default_cn_prompt.yaml
new file mode 100644
index 00000000..b2ec805f
--- /dev/null
+++ b/agentuniverse/agent/default/nl2api_agent/default_cn_prompt.yaml
@@ -0,0 +1,27 @@
+introduction: 你是一位精通工具选择ai助手。
+target: 你的目标是根据用户的问题选择出合适的工具。
+instruction: |
+  你需要根据问题和用户提供的工具，选择其中的一个或几个工具用来回答用户提出的问题。
+  你必须从多个角度、维度分析用户的问题，需要根据背景和问题，决定使用哪些工具可以回答用户问题。 
+  
+  您可以使用以下工具:
+  {tools}
+  
+  之前的对话: 
+  {chat_history}
+  
+  背景信息是: 
+  {background}
+  
+  回答必须是按照以下格式化的Json代码片段。
+  1. tools字段代表选择的几个工具的完整名称，列表格式。例如：[add, sub, mul, div]
+  2. thought字段代表选择工具的思考过程和原因。
+  ```{{
+    "tools": list,
+    "thought": string
+  }}```
+  
+  当前的问题：{input}
+metadata:
+  type: 'PROMPT'
+  version: 'default_nl2api_agent.cn'
diff --git a/agentuniverse/agent/default/nl2api_agent/default_en_prompt.yaml b/agentuniverse/agent/default/nl2api_agent/default_en_prompt.yaml
new file mode 100644
index 00000000..31f8b411
--- /dev/null
+++ b/agentuniverse/agent/default/nl2api_agent/default_en_prompt.yaml
@@ -0,0 +1,26 @@
+introduction: You are an AI assistant proficient in tool selection.
+target: Your goal is to select the appropriate tools based on the user's questions.
+instruction: |
+  Your task is to select one or several tools from those provided by the user, based on their question and the context, in order to answer the user's query.
+  You must analyze the user's problem from multiple angles and dimensions, taking into account the background and context of the question, and decide which tools can be used to answer the user's question.
+  You may use the following tools:  
+  {tools}
+
+  Previous conversation:
+  {chat_history}
+  
+  The background information is:
+  {background}
+  
+  The response must follow the format below as a formatted JSON code snippet.
+  1. The tools field represents the full names of the selected tools in a list format, such as:[add, sub, mul, div]
+  2. The thought field represents the thinking process and reasons behind the selection of tools.
+  ```{{
+    "tools": list,
+    "thought": string
+  }}```
+  
+  Question: {input}
+metadata:
+  type: 'PROMPT'
+  version: 'default_nl2api_agent.en'
diff --git a/agentuniverse/agent/default/nl2api_agent/nl2api_agent.py b/agentuniverse/agent/default/nl2api_agent/nl2api_agent.py
new file mode 100644
index 00000000..a88892a8
--- /dev/null
+++ b/agentuniverse/agent/default/nl2api_agent/nl2api_agent.py
@@ -0,0 +1,45 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/6/11 17:14
+# @Author  : weizjajj 
+# @Email   : weizhongjie.wzj@antgroup.com
+# @FileName: nl2api_agent.py
+
+from agentuniverse.agent.agent import Agent
+from agentuniverse.agent.input_object import InputObject
+
+
+class Nl2ApiAgent(Agent):
+    """ReAct Agent class."""
+
+    def input_keys(self) -> list[str]:
+        """Return the input keys of the Agent."""
+        return ['input']
+
+    def output_keys(self) -> list[str]:
+        """Return the output keys of the Agent."""
+        return ['output']
+
+    def parse_input(self, input_object: InputObject, agent_input: dict) -> dict:
+        """Agent parameter parsing.
+
+        Args:
+            input_object (InputObject): input parameters passed by the user.
+            agent_input (dict): agent input preparsed by the agent.
+        Returns:
+            dict: agent input parsed from `input_object` by the user.
+        """
+        agent_input['input'] = input_object.get_data('input')
+        self.agent_model.profile.setdefault('prompt_version', 'default_nl2api_agent.cn')
+        return agent_input
+
+    def parse_result(self, planner_result: dict) -> dict:
+        """Planner result parser.
+
+        Args:
+            planner_result(dict): Planner result
+        Returns:
+            dict: Agent result object.
+        """
+        return planner_result
diff --git a/agentuniverse/agent/default/nl2api_agent/nl2api_agent.yaml b/agentuniverse/agent/default/nl2api_agent/nl2api_agent.yaml
new file mode 100644
index 00000000..79245c65
--- /dev/null
+++ b/agentuniverse/agent/default/nl2api_agent/nl2api_agent.yaml
@@ -0,0 +1,17 @@
+info:
+  name: 'nl2api_agent'
+  description: 'nl2api agent'
+profile:
+  llm_model:
+    name: 'default_openai_llm'
+    model_name: 'gpt-4o'
+action:
+  tool:
+    - ''
+plan:
+  planner:
+    name: 'nl2api_planner'
+metadata:
+  type: 'AGENT'
+  module: 'agentuniverse.agent.default.nl2api_agent.nl2api_agent'
+  class: 'Nl2ApiAgent'
\ No newline at end of file
diff --git a/agentuniverse/agent/default/react_agent/__init__.py b/agentuniverse/agent/default/react_agent/__init__.py
new file mode 100644
index 00000000..89d328f4
--- /dev/null
+++ b/agentuniverse/agent/default/react_agent/__init__.py
@@ -0,0 +1,7 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/6/4 21:21
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: __init__.py.py
diff --git a/agentuniverse/agent/default/react_agent/default_cn_prompt.yaml b/agentuniverse/agent/default/react_agent/default_cn_prompt.yaml
new file mode 100644
index 00000000..df8d8659
--- /dev/null
+++ b/agentuniverse/agent/default/react_agent/default_cn_prompt.yaml
@@ -0,0 +1,35 @@
+introduction: 你是一位精通信息分析的ai助手。
+target: 你的目标是根据用户的问题以及给出的背景信息给出答案。
+instruction: |
+  你必须优先选择使用提供的工具回答用户提出的问题，若用户没有提供工具可以根据你的通识能力解决问题。
+  你在回答时问题必须使用中文回答。
+  你必须从多个角度、维度分析用户的问题，帮助用户获取最全面的信息，需要根据背景和问题，决定搜索哪些信息可以回答问题。 
+  请注意: 你在给出最终答案时需要从多角度给出更详细的原因，而不是一个简单的结论。
+  
+  您可以使用以下工具:
+  {tools}
+  
+  你的回答必须严格使用以下格式:
+  
+    Question: 您必须回答的问题
+    Thought: 你应该经常想想该怎么做
+    Action: 要采取的行动应该是 one of [{tool_names}]
+    Action Input: 行动的输入
+    Observation: 行动的结果
+    ... (Thought/Action/Action Input/Observation 的过程可以重复 N 次)
+    Thought: 我现在知道最终答案了
+    Final Answer: 原输入问题的最终答案
+  
+  之前的对话:
+  {chat_history}
+  
+  背景信息是:
+  {background}
+  
+  开始!
+  
+  Question: {input}
+  Thought:{agent_scratchpad}
+metadata:
+  type: 'PROMPT'
+  version: 'default_react_agent.cn'
diff --git a/agentuniverse/agent/default/react_agent/default_en_prompt.yaml b/agentuniverse/agent/default/react_agent/default_en_prompt.yaml
new file mode 100644
index 00000000..92137f90
--- /dev/null
+++ b/agentuniverse/agent/default/react_agent/default_en_prompt.yaml
@@ -0,0 +1,31 @@
+introduction: You are an AI assistant who is proficient in information analysis.
+target: Your goal is to give answers based on the user's question and the context given.
+instruction: |
+  Answer the following questions as best you can. You have access to the following tools:
+
+  {tools}
+
+  Use the following format:
+
+    Question: the input question you must answer
+    Thought: you should always think about what to do
+    Action: the action to take, should be one of [{tool_names}]
+    Action Input: the input to the action
+    Observation: the result of the action
+    ... (this Thought/Action/Action Input/Observation can repeat N times)
+    Thought: I now know the final answer
+    Final Answer: the final answer to the original input question
+  
+  Previous conversion:
+  {chat_history}
+  
+  Background:
+  {background}
+  
+  Begin!
+
+  Question: {input}
+  Thought:{agent_scratchpad}
+metadata:
+  type: 'PROMPT'
+  version: 'default_react_agent.en'
diff --git a/agentuniverse/agent/default/react_agent/react_agent.py b/agentuniverse/agent/default/react_agent/react_agent.py
new file mode 100644
index 00000000..f50e7057
--- /dev/null
+++ b/agentuniverse/agent/default/react_agent/react_agent.py
@@ -0,0 +1,44 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/5/31 21:22
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: react_agent.py
+from agentuniverse.agent.agent import Agent
+from agentuniverse.agent.input_object import InputObject
+
+
+class ReActAgent(Agent):
+    """ReAct Agent class."""
+
+    def input_keys(self) -> list[str]:
+        """Return the input keys of the Agent."""
+        return ['input']
+
+    def output_keys(self) -> list[str]:
+        """Return the output keys of the Agent."""
+        return ['output']
+
+    def parse_input(self, input_object: InputObject, agent_input: dict) -> dict:
+        """Agent parameter parsing.
+
+        Args:
+            input_object (InputObject): input parameters passed by the user.
+            agent_input (dict): agent input preparsed by the agent.
+        Returns:
+            dict: agent input parsed from `input_object` by the user.
+        """
+        agent_input['input'] = input_object.get_data('input')
+        self.agent_model.profile.setdefault('prompt_version', 'default_react_agent.cn')
+        return agent_input
+
+    def parse_result(self, planner_result: dict) -> dict:
+        """Planner result parser.
+
+        Args:
+            planner_result(dict): Planner result
+        Returns:
+            dict: Agent result object.
+        """
+        return planner_result
diff --git a/agentuniverse/agent/default/react_agent/react_agent.yaml b/agentuniverse/agent/default/react_agent/react_agent.yaml
new file mode 100644
index 00000000..48309fc5
--- /dev/null
+++ b/agentuniverse/agent/default/react_agent/react_agent.yaml
@@ -0,0 +1,17 @@
+info:
+  name: 'react_agent'
+  description: 'react agent'
+profile:
+  llm_model:
+    name: 'default_openai_llm'
+    model_name: 'gpt-4o'
+action:
+  tool:
+    - ''
+plan:
+  planner:
+    name: 'react_planner'
+metadata:
+  type: 'AGENT'
+  module: 'agentuniverse.agent.default.react_agent.react_agent'
+  class: 'ReActAgent'
\ No newline at end of file
diff --git a/agentuniverse/agent/memory/default/default_memory.py b/agentuniverse/agent/memory/default/default_memory.py
index 260d534a..cf48d747 100644
--- a/agentuniverse/agent/memory/default/default_memory.py
+++ b/agentuniverse/agent/memory/default/default_memory.py
@@ -10,7 +10,7 @@
 
 
 class DefaultMemory(ChatMemory):
-    """The AFAF default memory module."""
+    """The aU default memory module."""
 
     def __init__(self, **kwargs):
         """The __init__ method.
diff --git a/agentuniverse/agent/plan/planner/executing_planner/executing_planner.py b/agentuniverse/agent/plan/planner/executing_planner/executing_planner.py
index 78526fba..f792fea7 100644
--- a/agentuniverse/agent/plan/planner/executing_planner/executing_planner.py
+++ b/agentuniverse/agent/plan/planner/executing_planner/executing_planner.py
@@ -8,6 +8,7 @@
 import asyncio
 
 from langchain_core.chat_history import InMemoryChatMessageHistory
+from langchain_core.output_parsers import StrOutputParser
 from langchain_core.runnables.history import RunnableWithMessageHistory
 
 from agentuniverse.agent.agent_model import AgentModel
@@ -38,7 +39,7 @@ def invoke(self, agent_model: AgentModel, planner_input: dict, input_object: Inp
 
         memory: ChatMemory = self.handle_memory(agent_model, planner_input)
 
-        self.handle_all_actions(agent_model, planner_input, input_object)
+        self.run_all_actions(agent_model, planner_input, input_object)
 
         llm: LLM = self.handle_llm(agent_model)
 
@@ -52,10 +53,10 @@ def invoke(self, agent_model: AgentModel, planner_input: dict, input_object: Inp
             lambda session_id: chat_history,
             history_messages_key="chat_history",
             input_messages_key=self.input_key,
-        )
+        ) | StrOutputParser()
         res = asyncio.run(
             chain_with_history.ainvoke(input=planner_input, config={"configurable": {"session_id": "unused"}}))
-        return {**planner_input, self.output_key: res.content, 'chat_history': generate_memories(chat_history)}
+        return {**planner_input, self.output_key: res, 'chat_history': generate_memories(chat_history)}
 
     def handle_prompt(self, agent_model: AgentModel, planner_input: dict) -> Prompt:
         """Prompt module processing.
diff --git a/agentuniverse/agent/plan/planner/expressing_planner/expressing_planner.py b/agentuniverse/agent/plan/planner/expressing_planner/expressing_planner.py
index a7204af1..928b723d 100644
--- a/agentuniverse/agent/plan/planner/expressing_planner/expressing_planner.py
+++ b/agentuniverse/agent/plan/planner/expressing_planner/expressing_planner.py
@@ -8,6 +8,7 @@
 import asyncio
 
 from langchain_core.chat_history import InMemoryChatMessageHistory
+from langchain_core.output_parsers import StrOutputParser
 from langchain_core.runnables.history import RunnableWithMessageHistory
 
 from agentuniverse.agent.agent_model import AgentModel
@@ -49,10 +50,10 @@ def invoke(self, agent_model: AgentModel, planner_input: dict, input_object: Inp
             lambda session_id: chat_history,
             history_messages_key="chat_history",
             input_messages_key=self.input_key,
-        )
+        ) | StrOutputParser()
         res = asyncio.run(
             chain_with_history.ainvoke(input=planner_input, config={"configurable": {"session_id": "unused"}}))
-        return {**planner_input, self.output_key: res.content, 'chat_history': generate_memories(chat_history)}
+        return {**planner_input, self.output_key: res, 'chat_history': generate_memories(chat_history)}
 
     def handle_prompt(self, agent_model: AgentModel, planner_input: dict) -> Prompt:
         """Prompt module processing.
diff --git a/agentuniverse/agent/plan/planner/nl2api_planner/__init__.py b/agentuniverse/agent/plan/planner/nl2api_planner/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/agentuniverse/agent/plan/planner/nl2api_planner/nl2api_planner.py b/agentuniverse/agent/plan/planner/nl2api_planner/nl2api_planner.py
new file mode 100644
index 00000000..55d7d8d7
--- /dev/null
+++ b/agentuniverse/agent/plan/planner/nl2api_planner/nl2api_planner.py
@@ -0,0 +1,111 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+# @Time    : 2024/3/18 10:50
+# @Author  : heji
+# @Email   : lc299034@antgroup.com
+# @FileName: expressing_planner.py
+"""Expressing planner module."""
+import asyncio
+
+from langchain_core.chat_history import InMemoryChatMessageHistory
+from langchain_core.output_parsers import JsonOutputParser
+from langchain_core.runnables.history import RunnableWithMessageHistory
+from langchain.tools import Tool as LangchainTool
+
+from agentuniverse.agent.action.tool.tool import Tool
+from agentuniverse.agent.action.tool.tool_manager import ToolManager
+from agentuniverse.agent.agent_model import AgentModel
+from agentuniverse.agent.input_object import InputObject
+from agentuniverse.agent.memory.chat_memory import ChatMemory
+from agentuniverse.agent.plan.planner.planner import Planner
+from agentuniverse.base.util.memory_util import generate_memories
+from agentuniverse.base.util.prompt_util import process_llm_token
+from agentuniverse.llm.llm import LLM
+from agentuniverse.prompt.prompt import Prompt
+from agentuniverse.prompt.prompt_manager import PromptManager
+from agentuniverse.prompt.prompt_model import AgentPromptModel
+
+
+class Nl2ApiPlanner(Planner):
+    """Expressing planner class."""
+
+    def invoke(self, agent_model: AgentModel, planner_input: dict, input_object: InputObject) -> dict:
+        """Invoke the planner.
+
+        Args:
+            agent_model (AgentModel): Agent model object.
+            planner_input (dict): Planner input object.
+            input_object (InputObject): The input parameters passed by the user.
+        Returns:
+            dict: The planner result.
+        """
+        memory: ChatMemory = self.handle_memory(agent_model, planner_input)
+
+        llm: LLM = self.handle_llm(agent_model)
+
+        prompt: Prompt = self.handle_prompt(agent_model, planner_input)
+
+        process_llm_token(llm, prompt.as_langchain(), agent_model.profile, planner_input)
+
+        chat_history = memory.as_langchain().chat_memory if memory else InMemoryChatMessageHistory()
+
+        chain_with_history = RunnableWithMessageHistory(
+            prompt.as_langchain() | llm.as_langchain(),
+            lambda session_id: chat_history,
+            history_messages_key="chat_history",
+            input_messages_key=self.input_key,
+        ) | JsonOutputParser()
+        res = asyncio.run(
+            chain_with_history.ainvoke(input=planner_input, config={"configurable": {"session_id": "unused"}}))
+        return {**planner_input, self.output_key: res, 'chat_history': generate_memories(chat_history)}
+
+    @staticmethod
+    def acquire_tools(action) -> list[LangchainTool]:
+        tool_names: list = action.get('tool') or list()
+        lc_tools: list[LangchainTool] = list()
+        for tool_name in tool_names:
+            tool: Tool = ToolManager().get_instance_obj(tool_name)
+            lc_tools.append(tool.as_langchain())
+        return lc_tools
+
+    def handle_prompt(self, agent_model: AgentModel, planner_input: dict) -> Prompt:
+        """
+        Prompt module processing.
+
+        Args:
+            agent_model (AgentModel): Agent model object.
+            planner_input (dict): Planner input object.
+        Returns:
+            ChatPrompt: The chat prompt instance.
+        """
+        tools = self.acquire_tools(action=agent_model.action)
+        lc_tools_str: str = ''
+        for lc_tool in tools:
+            lc_tools_str += "tool name:" + lc_tool.name + " " + "tool description:" + lc_tool.description + '\n'
+        lc_tool_names = "|".join([lc_tool.name for lc_tool in tools])
+        planner_input['tool_names'] = lc_tool_names
+        planner_input['tools'] = lc_tools_str
+        planner_input['agent_scratchpad'] = ''
+        #
+        profile: dict = agent_model.profile
+        #
+        profile_prompt_model: AgentPromptModel = AgentPromptModel(introduction=profile.get('introduction'),
+                                                                  target=profile.get('target'),
+                                                                  instruction=profile.get('instruction'))
+
+        # get the prompt by the prompt version
+        prompt_version: str = profile.get('prompt_version')
+        version_prompt: Prompt = PromptManager().get_instance_obj(prompt_version)
+
+        if version_prompt is None and not profile_prompt_model:
+            raise Exception("Either the `prompt_version` or `introduction & target & instruction`"
+                            " in agent profile configuration should be provided.")
+        if version_prompt:
+            version_prompt_model: AgentPromptModel = AgentPromptModel(
+                introduction=getattr(version_prompt, 'introduction', ''),
+                target=getattr(version_prompt, 'target', ''),
+                instruction=getattr(version_prompt, 'instruction', ''))
+            profile_prompt_model = profile_prompt_model + version_prompt_model
+
+        prompt = Prompt().build_prompt(profile_prompt_model, self.prompt_assemble_order)
+        return prompt
\ No newline at end of file
diff --git a/agentuniverse/agent/plan/planner/nl2api_planner/nl2api_planner.yaml b/agentuniverse/agent/plan/planner/nl2api_planner/nl2api_planner.yaml
new file mode 100644
index 00000000..1de5943f
--- /dev/null
+++ b/agentuniverse/agent/plan/planner/nl2api_planner/nl2api_planner.yaml
@@ -0,0 +1,6 @@
+name: 'nl2api_planner'
+description: 'nl2api planner'
+metadata:
+  type: 'PLANNER'
+  module: 'agentuniverse.agent.plan.planner.nl2api_planner.nl2api_planner'
+  class: 'Nl2ApiPlanner'
\ No newline at end of file
diff --git a/agentuniverse/agent/plan/planner/planner.py b/agentuniverse/agent/plan/planner/planner.py
index a9401807..c30fd311 100644
--- a/agentuniverse/agent/plan/planner/planner.py
+++ b/agentuniverse/agent/plan/planner/planner.py
@@ -74,10 +74,10 @@ def handle_memory(self, agent_model: AgentModel, planner_input: dict) -> ChatMem
         chat_history: list = planner_input.get('chat_history')
         memory_name = agent_model.memory.get('name')
         llm_model = agent_model.memory.get('llm_model') or dict()
-        llm_name = llm_model.get('name')
+        llm_name = llm_model.get('name') or agent_model.profile.get('llm_model').get('name')
 
         messages: list[Message] = generate_messages(chat_history)
-        llm: LLM = LLMManager().get_instance_obj(llm_name) if llm_name else None
+        llm: LLM = LLMManager().get_instance_obj(llm_name)
         params: dict = dict()
         params['messages'] = messages
         params['llm'] = llm
@@ -90,7 +90,7 @@ def handle_memory(self, agent_model: AgentModel, planner_input: dict) -> ChatMem
         memory.set_by_agent_model(**params)
         return memory
 
-    def handle_all_actions(self, agent_model: AgentModel, planner_input: dict, input_object: InputObject):
+    def run_all_actions(self, agent_model: AgentModel, planner_input: dict, input_object: InputObject):
         """Tool and knowledge processing.
 
         Args:
diff --git a/agentuniverse/agent/plan/planner/planning_planner/planning_planner.py b/agentuniverse/agent/plan/planner/planning_planner/planning_planner.py
index c983f14d..1ca05a0e 100644
--- a/agentuniverse/agent/plan/planner/planning_planner/planning_planner.py
+++ b/agentuniverse/agent/plan/planner/planning_planner/planning_planner.py
@@ -8,6 +8,7 @@
 import asyncio
 
 from langchain_core.chat_history import InMemoryChatMessageHistory
+from langchain_core.output_parsers import StrOutputParser
 from langchain_core.runnables.history import RunnableWithMessageHistory
 
 from agentuniverse.agent.agent_model import AgentModel
@@ -50,10 +51,10 @@ def invoke(self, agent_model: AgentModel, planner_input: dict,
             lambda session_id: chat_history,
             history_messages_key="chat_history",
             input_messages_key=self.input_key,
-        )
+        ) | StrOutputParser()
         res = asyncio.run(
             chain_with_history.ainvoke(input=planner_input, config={"configurable": {"session_id": "unused"}}))
-        return {**planner_input, self.output_key: res.content, 'chat_history': generate_memories(chat_history)}
+        return {**planner_input, self.output_key: res, 'chat_history': generate_memories(chat_history)}
 
     def handle_prompt(self, agent_model: AgentModel, planner_input: dict) -> Prompt:
         """Prompt module processing.
diff --git a/agentuniverse/agent/plan/planner/rag_planner/rag_planner.py b/agentuniverse/agent/plan/planner/rag_planner/rag_planner.py
index 29d38c1c..4edb1f6a 100644
--- a/agentuniverse/agent/plan/planner/rag_planner/rag_planner.py
+++ b/agentuniverse/agent/plan/planner/rag_planner/rag_planner.py
@@ -8,6 +8,7 @@
 import asyncio
 
 from langchain_core.chat_history import InMemoryChatMessageHistory
+from langchain_core.output_parsers import StrOutputParser
 from langchain_core.runnables.history import RunnableWithMessageHistory
 
 from agentuniverse.agent.agent_model import AgentModel
@@ -39,7 +40,7 @@ def invoke(self, agent_model: AgentModel, planner_input: dict,
         """
         memory: ChatMemory = self.handle_memory(agent_model, planner_input)
 
-        self.handle_all_actions(agent_model, planner_input, input_object)
+        self.run_all_actions(agent_model, planner_input, input_object)
 
         llm: LLM = self.handle_llm(agent_model)
 
@@ -53,10 +54,10 @@ def invoke(self, agent_model: AgentModel, planner_input: dict,
             lambda session_id: chat_history,
             history_messages_key="chat_history",
             input_messages_key=self.input_key,
-        )
+        ) | StrOutputParser()
         res = asyncio.run(
             chain_with_history.ainvoke(input=planner_input, config={"configurable": {"session_id": "unused"}}))
-        return {**planner_input, self.output_key: res.content, 'chat_history': generate_memories(chat_history)}
+        return {**planner_input, self.output_key: res, 'chat_history': generate_memories(chat_history)}
 
     def handle_prompt(self, agent_model: AgentModel, planner_input: dict) -> ChatPrompt:
         """Prompt module processing.
diff --git a/agentuniverse/agent/plan/planner/react_planner/__init__.py b/agentuniverse/agent/plan/planner/react_planner/__init__.py
new file mode 100644
index 00000000..233deb77
--- /dev/null
+++ b/agentuniverse/agent/plan/planner/react_planner/__init__.py
@@ -0,0 +1,7 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/6/4 21:00
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: __init__.py.py
diff --git a/agentuniverse/agent/plan/planner/react_planner/react_planner.py b/agentuniverse/agent/plan/planner/react_planner/react_planner.py
new file mode 100644
index 00000000..ef1f76f9
--- /dev/null
+++ b/agentuniverse/agent/plan/planner/react_planner/react_planner.py
@@ -0,0 +1,122 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/5/31 21:22
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: react_planner.py
+
+from langchain_core.chat_history import InMemoryChatMessageHistory
+from langchain.agents import AgentExecutor, create_react_agent
+from langchain.tools import Tool as LangchainTool
+from langchain_core.runnables import RunnableConfig
+
+from agentuniverse.agent.action.tool.tool import Tool
+from agentuniverse.agent.action.tool.tool_manager import ToolManager
+from agentuniverse.agent.agent_model import AgentModel
+from agentuniverse.agent.input_object import InputObject
+from agentuniverse.agent.memory.chat_memory import ChatMemory
+from agentuniverse.agent.plan.planner.planner import Planner
+from agentuniverse.agent.plan.planner.react_planner.stream_callback import StreamOutPutCallbackHandler
+from agentuniverse.base.util.prompt_util import process_llm_token
+from agentuniverse.llm.llm import LLM
+from agentuniverse.prompt.chat_prompt import ChatPrompt
+from agentuniverse.prompt.prompt import Prompt
+from agentuniverse.prompt.prompt_manager import PromptManager
+from agentuniverse.prompt.prompt_model import AgentPromptModel
+
+
+class ReActPlanner(Planner):
+    """ReAct planner class."""
+
+    tools: list[LangchainTool] = None
+
+    def invoke(self, agent_model: AgentModel, planner_input: dict,
+               input_object: InputObject) -> dict:
+        """Invoke the planner.
+
+        Args:
+            agent_model (AgentModel): Agent model object.
+            planner_input (dict): Planner input object.
+            input_object (InputObject): The input parameters passed by the user.
+        Returns:
+            dict: The planner result.
+        """
+
+        memory: ChatMemory = self.handle_memory(agent_model, planner_input)
+
+        llm: LLM = self.handle_llm(agent_model)
+
+        tools = self.acquire_tools(agent_model.action)
+
+        prompt: Prompt = self.handle_prompt(agent_model, planner_input)
+        process_llm_token(llm, prompt.as_langchain(), agent_model.profile, planner_input)
+        chat_history = memory.as_langchain().chat_memory if memory else InMemoryChatMessageHistory()
+
+        agent = create_react_agent(llm.as_langchain(), tools, prompt.as_langchain())
+        agent_executor = AgentExecutor(agent=agent, tools=tools,
+                                       verbose=True,
+                                       handle_parsing_errors=True,
+                                       max_iterations=agent_model.plan.get('planner').get("max_iterations", 15))
+
+        return agent_executor.invoke(input=planner_input, memory=memory.as_langchain() if memory else None,
+                                     chat_history=chat_history, config=self.get_run_config(input_object))
+
+    @staticmethod
+    def get_run_config(input_object: InputObject) -> RunnableConfig:
+        config = RunnableConfig()
+        callbacks = []
+        output_stream = input_object.get_data('output_stream')
+        callbacks.append(StreamOutPutCallbackHandler(output_stream))
+        config.setdefault("callbacks", callbacks)
+        return config
+
+    @staticmethod
+    def acquire_tools(action) -> list[LangchainTool]:
+        tool_names: list = action.get('tool') or list()
+        lc_tools: list[LangchainTool] = list()
+        for tool_name in tool_names:
+            tool: Tool = ToolManager().get_instance_obj(tool_name)
+            lc_tools.append(tool.as_langchain())
+        return lc_tools
+
+    def handle_prompt(self, agent_model: AgentModel, planner_input: dict) -> Prompt:
+        """Prompt module processing.
+
+        Args:
+            agent_model (AgentModel): Agent model object.
+            planner_input (dict): Planner input object.
+        Returns:
+            ChatPrompt: The chat prompt instance.
+        """
+        lc_tools_str: str = ''
+        tools = self.acquire_tools(agent_model.action)
+        for lc_tool in self.acquire_tools(agent_model.action):
+            lc_tools_str += "tool name:" + lc_tool.name + " " + "tool description:" + lc_tool.description + '\n'
+        lc_tool_names = "|".join([lc_tool.name for lc_tool in tools])
+        planner_input['tool_names'] = lc_tool_names
+        planner_input['tools'] = lc_tools_str
+        planner_input['agent_scratchpad'] = ''
+
+        profile: dict = agent_model.profile
+
+        profile_prompt_model: AgentPromptModel = AgentPromptModel(introduction=profile.get('introduction'),
+                                                                  target=profile.get('target'),
+                                                                  instruction=profile.get('instruction'))
+
+        # get the prompt by the prompt version
+        prompt_version: str = profile.get('prompt_version')
+        version_prompt: Prompt = PromptManager().get_instance_obj(prompt_version)
+
+        if version_prompt is None and not profile_prompt_model:
+            raise Exception("Either the `prompt_version` or `introduction & target & instruction`"
+                            " in agent profile configuration should be provided.")
+        if version_prompt:
+            version_prompt_model: AgentPromptModel = AgentPromptModel(
+                introduction=getattr(version_prompt, 'introduction', ''),
+                target=getattr(version_prompt, 'target', ''),
+                instruction=getattr(version_prompt, 'instruction', ''))
+            profile_prompt_model = profile_prompt_model + version_prompt_model
+
+        prompt = Prompt().build_prompt(profile_prompt_model, self.prompt_assemble_order)
+        return prompt
diff --git a/agentuniverse/agent/plan/planner/react_planner/react_planner.yaml b/agentuniverse/agent/plan/planner/react_planner/react_planner.yaml
new file mode 100644
index 00000000..8af5eefb
--- /dev/null
+++ b/agentuniverse/agent/plan/planner/react_planner/react_planner.yaml
@@ -0,0 +1,6 @@
+name: 'react_planner'
+description: 'react planner'
+metadata:
+  type: 'PLANNER'
+  module: 'agentuniverse.agent.plan.planner.react_planner.react_planner'
+  class: 'ReActPlanner'
\ No newline at end of file
diff --git a/agentuniverse/agent/plan/planner/react_planner/stream_callback.py b/agentuniverse/agent/plan/planner/react_planner/stream_callback.py
new file mode 100644
index 00000000..87ec6acd
--- /dev/null
+++ b/agentuniverse/agent/plan/planner/react_planner/stream_callback.py
@@ -0,0 +1,64 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/6/13 11:03
+# @Author  : weizjajj 
+# @Email   : weizhongjie.wzj@antgroup.com
+# @FileName: stream_callback.py
+
+import asyncio
+from typing import Optional, Dict, Any
+
+from langchain_core.agents import AgentAction, AgentFinish
+from langchain_core.callbacks import BaseCallbackHandler
+
+
+class StreamOutPutCallbackHandler(BaseCallbackHandler):
+    """Callback Handler that prints to std out."""
+
+    def __init__(self, queue_stream: asyncio.Queue, color: Optional[str] = None) -> None:
+        """Initialize callback handler."""
+        self.queueStream = queue_stream
+        self.color = color
+
+    def on_chain_start(
+            self, serialized: Dict[str, Any], inputs: Dict[str, Any], **kwargs: Any
+    ) -> None:
+        return
+
+    def on_chain_end(self, outputs: Dict[str, Any], **kwargs: Any) -> None:
+        """Print out that we finished a chain."""
+
+    def on_agent_action(
+            self, action: AgentAction, color: Optional[str] = None, **kwargs: Any
+    ) -> Any:
+        self.queueStream.put_nowait("Thought:"+action.log)
+
+    def on_tool_end(
+            self,
+            output: str,
+            color: Optional[str] = None,
+            observation_prefix: Optional[str] = None,
+            llm_prefix: Optional[str] = None,
+            **kwargs: Any,
+    ) -> None:
+        """If not the final action, print out observation."""
+        if observation_prefix is not None:
+            self.queueStream.put_nowait(observation_prefix + output)
+        else:
+            self.queueStream.put_nowait('Observation:'+output)
+
+    def on_text(
+            self,
+            text: str,
+            color: Optional[str] = None,
+            end: str = "",
+            **kwargs: Any,
+    ) -> None:
+        """Run when agent ends."""
+
+    def on_agent_finish(
+            self, finish: AgentFinish, color: Optional[str] = None, **kwargs: Any
+    ) -> None:
+        """Run on agent end."""
+        self.queueStream.put_nowait("Thought:" + finish.log + "\n")
diff --git a/agentuniverse/agent/plan/planner/reviewing_planner/reviewing_planner.py b/agentuniverse/agent/plan/planner/reviewing_planner/reviewing_planner.py
index 960f98d5..8702bee7 100644
--- a/agentuniverse/agent/plan/planner/reviewing_planner/reviewing_planner.py
+++ b/agentuniverse/agent/plan/planner/reviewing_planner/reviewing_planner.py
@@ -8,6 +8,7 @@
 import asyncio
 
 from langchain_core.chat_history import InMemoryChatMessageHistory
+from langchain_core.output_parsers import StrOutputParser
 from langchain_core.runnables.history import RunnableWithMessageHistory
 
 from agentuniverse.agent.agent_model import AgentModel
@@ -49,10 +50,10 @@ def invoke(self, agent_model: AgentModel, planner_input: dict, input_object: Inp
             lambda session_id: chat_history,
             history_messages_key="chat_history",
             input_messages_key=self.input_key,
-        )
+        ) | StrOutputParser()
         res = asyncio.run(
             chain_with_history.ainvoke(input=planner_input, config={"configurable": {"session_id": "unused"}}))
-        return {**planner_input, self.output_key: res.content, 'chat_history': generate_memories(chat_history)}
+        return {**planner_input, self.output_key: res, 'chat_history': generate_memories(chat_history)}
 
     def handle_prompt(self, agent_model: AgentModel, planner_input: dict) -> Prompt:
         """Generate prompt template for the planner.
diff --git a/agentuniverse/base/util/prompt_util.py b/agentuniverse/base/util/prompt_util.py
index ec6b2dcb..cc0b0612 100644
--- a/agentuniverse/base/util/prompt_util.py
+++ b/agentuniverse/base/util/prompt_util.py
@@ -163,6 +163,9 @@ def process_llm_token(agent_llm: LLM, lc_prompt_template, profile: dict, planner
     prompt_tokens: int = agent_llm.get_num_tokens(prompt)
 
     input_tokens = agent_llm.max_context_length() - agent_llm.max_tokens
+    if input_tokens <= 0:
+        raise Exception("The current output max tokens limit is greater than the context length of the LLM model, "
+                        "please adjust it by editing the `max_tokens` parameter in the llm yaml.")
 
     if prompt_tokens <= input_tokens:
         return
diff --git a/agentuniverse/llm/claude_langchain_instance.py b/agentuniverse/llm/claude_langchain_instance.py
new file mode 100644
index 00000000..e7876543
--- /dev/null
+++ b/agentuniverse/llm/claude_langchain_instance.py
@@ -0,0 +1,93 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/5/22 17:07
+# @Author  : weizjajj 
+# @Email   : weizhongjie.wzj@antgroup.com
+# @FileName: claude_langchain_instance.py
+
+import warnings
+from typing import List, Optional, Any
+
+from langchain_anthropic import ChatAnthropic
+from langchain_anthropic.chat_models import _tools_in_params
+from langchain_core.callbacks import CallbackManagerForLLMRun, AsyncCallbackManagerForLLMRun
+from langchain_core.language_models.chat_models import generate_from_stream, agenerate_from_stream
+from langchain_core.messages import BaseMessage, SystemMessage, HumanMessage
+from langchain_core.outputs import ChatResult
+
+from agentuniverse.llm.llm import LLM
+
+
+class ClaudeLangChainInstance(ChatAnthropic):
+    """
+    This class wraps the Claude API into a LangChain API.
+    """
+    llm: LLM = None
+
+    def __init__(self, llm: LLM):
+        init_params = {}
+        init_params['model'] = llm.model_name if llm.model_name else 'Claude-Instant-V1.3'
+        init_params['temperature'] = llm.temperature if llm.temperature else 0.7
+        init_params['default_request_timeout'] = llm.request_timeout
+        init_params['streaming'] = llm.streaming if llm.streaming else False
+        init_params['anthropic_api_key'] = llm.anthropic_api_key if llm.anthropic_api_key else 'blank'
+        init_params['max_tokens'] = llm.max_tokens
+        init_params['max_retries'] = llm.max_retries if llm.max_retries else 2
+        init_params['anthropic_api_url'] = llm.anthropic_api_url
+        init_params['streaming'] = llm.streaming
+        init_params['llm'] = llm
+        super().__init__(**init_params)
+
+    def _generate(
+            self,
+            messages: List[BaseMessage],
+            stop: Optional[List[str]] = None,
+            run_manager: Optional[CallbackManagerForLLMRun] = None,
+            **kwargs: Any,
+    ) -> ChatResult:
+        if len(messages) > 1 and isinstance(messages[1], SystemMessage):
+            messages[1] = HumanMessage(content=messages[1].content)
+        params = self._format_params(messages=messages, stop=stop, **kwargs)
+        if self.streaming:
+            if _tools_in_params(params):
+                warnings.warn(
+                    "stream: Tool use is not yet supported in streaming mode."
+                )
+            else:
+                stream_iter = self._stream(
+                    messages, stop=stop, run_manager=run_manager, **kwargs
+                )
+                return generate_from_stream(stream_iter)
+        if _tools_in_params(params):
+            data = self._client.beta.tools.messages.create(**params)
+        else:
+            data = self.llm.call(**params).raw
+        return self._format_output(data, **kwargs)
+
+    async def _agenerate(
+            self,
+            messages: List[BaseMessage],
+            stop: Optional[List[str]] = None,
+            run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
+            **kwargs: Any,
+    ) -> ChatResult:
+        if len(messages) > 1 and isinstance(messages[1], SystemMessage):
+            messages[1] = HumanMessage(content=messages[1].content)
+        params = self._format_params(messages=messages, stop=stop, **kwargs)
+        if self.streaming:
+            if _tools_in_params(params):
+                warnings.warn(
+                    "stream: Tool use is not yet supported in streaming mode."
+                )
+            else:
+                stream_iter = self._astream(
+                    messages, stop=stop, run_manager=run_manager, **kwargs
+                )
+                return await agenerate_from_stream(stream_iter)
+        if _tools_in_params(params):
+            data = await self._async_client.beta.tools.messages.create(**params)
+        else:
+            data = await self.llm.acall(**params)
+            data = data.raw
+        return self._format_output(data, **kwargs)
diff --git a/agentuniverse/llm/default/claude_llm.py b/agentuniverse/llm/default/claude_llm.py
new file mode 100644
index 00000000..bee1f820
--- /dev/null
+++ b/agentuniverse/llm/default/claude_llm.py
@@ -0,0 +1,154 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/5/21 17:49
+# @Author  : weizjajj 
+# @Email   : weizhongjie.wzj@antgroup.com
+# @FileName: claude_llm.py
+
+import asyncio
+from typing import Optional, Any, Union, Iterator, AsyncIterator
+
+import anthropic
+import httpx
+from langchain_core.language_models import BaseLanguageModel
+from pydantic import Field
+
+from agentuniverse.base.annotation.trace import trace_llm
+from agentuniverse.base.util.env_util import get_from_env
+from agentuniverse.llm.claude_langchain_instance import ClaudeLangChainInstance
+from agentuniverse.llm.llm import LLM
+from agentuniverse.llm.llm_output import LLMOutput
+
+ClaudeMAXCONTETNLENGTH = {
+    "claude-3-opus-20240229": 200000,
+    "claude-3-sonnet-20240229": 200000,
+    "claude-3-haiku-20240307": 200000,
+    "claude-2.1": 200000,
+    "claude-2.0": 100000,
+    "claude-instant-1.2": 100000
+}
+
+
+class ClaudeLLM(LLM):
+    """
+    This class implements an interface for interacting with the Anthropic Claude model.
+
+    Attribute:
+        anthropic_api_key (Optional[str]): The API key for the Anthropic API. Defaults to the value of the environment variable ANTHROPIC_API_KEY.
+        anthropic_api_url (Optional[str]): The URL for the Anthropic API. Defaults to the value of the environment variable ANTHROPIC_API_URL.
+        anthropic_proxy (Optional[str]): The proxy to use for the Anthropic API. Defaults to None.
+        connection_pool_limits (Optional[int]): The maximum number of connections to keep in a pool. Defaults to None.
+    """
+    anthropic_api_key: Optional[str] = Field(default_factory=lambda: get_from_env('ANTHROPIC_API_KEY'))
+    anthropic_api_url: Optional[str] = Field(default_factory=lambda: get_from_env('ANTHROPIC_API_URL'))
+    anthropic_proxy: Optional[str] = None
+    connection_pool_limits: Optional[int] = None
+
+    def _new_client(self):
+        client = anthropic.Anthropic(
+            api_key=self.anthropic_api_key,
+            base_url=self.anthropic_api_url,
+            timeout=self.request_timeout if self.request_timeout else 60,
+            max_retries=self.max_retries if self.max_retries else 2,
+            http_client=httpx.Client(proxy=self.anthropic_proxy) if self.anthropic_proxy else None,
+            connection_pool_limits=self.connection_pool_limits
+        )
+        return client
+
+    def _new_async_client(self):
+        client = anthropic.AsyncAnthropic(
+            api_key=self.anthropic_api_key,
+            base_url=self.anthropic_api_url,
+            timeout=self.request_timeout if self.request_timeout else 60,
+            max_retries=self.max_retries if self.max_retries else 2,
+            http_client=httpx.AsyncClient(proxy=self.anthropic_proxy) if self.anthropic_proxy else None,
+            connection_pool_limits=self.connection_pool_limits
+        )
+        return client
+    @trace_llm
+    def call(self, messages: list, **kwargs: Any) -> Union[LLMOutput, Iterator[LLMOutput]]:
+        """Run the Claude LLM.
+
+        Args:
+            messages (list): The messages to send to the LLM.
+            **kwargs: Arbitrary keyword arguments.
+        """
+        streaming = kwargs.pop("streaming") if "streaming" in kwargs else self.streaming
+        self.client = self._new_client()
+        chat_completion = self.client.messages.create(
+            messages=messages,
+            model=kwargs.pop('model', self.model_name),
+            temperature=kwargs.pop('temperature', self.temperature),
+            stream=kwargs.pop('stream', streaming),
+            max_tokens=kwargs.pop('max_tokens', self.max_tokens),
+            **kwargs,
+        )
+        if not streaming:
+            self.close()
+            return self.parse_result(chat_completion)
+        return self.generate_stream_result(chat_completion)
+
+    @trace_llm
+    async def acall(self, messages: list, **kwargs: Any) -> Union[LLMOutput, AsyncIterator[LLMOutput]]:
+        streaming = kwargs.pop("streaming") if "streaming" in kwargs else self.streaming
+        self.client = self._new_async_client()
+        chat_completion = await self.client.messages.create(
+            messages=messages,
+            model=kwargs.pop('model', self.model_name),
+            temperature=kwargs.pop('temperature', self.temperature),
+            stream=kwargs.pop('stream', streaming),
+            max_tokens=kwargs.pop('max_tokens', self.max_tokens),
+            **kwargs,
+        )
+        if not streaming:
+            await self.aclose()
+            return self.parse_result(chat_completion)
+        return self.agenerate_stream_result(chat_completion)
+
+    @staticmethod
+    def parse_result(data):
+        text = data.content[0].text
+        if not text:
+            return
+        return LLMOutput(text=text, raw=data)
+
+    def generate_stream_result(self, chat_completion: Iterator):
+        for chunk in chat_completion:
+            if chunk.type != 'content_block_delta':
+                continue
+            yield LLMOutput(text=chunk.delta.text, raw=chunk.model_dump())
+        self.close()
+
+    async def agenerate_stream_result(self, chat_completion: AsyncIterator):
+        async for chunk in chat_completion:
+            print(chunk)
+            if chunk.type != 'content_block_delta':
+                continue
+            yield LLMOutput(text=chunk.delta.text, raw=chunk.model_dump())
+        await self.aclose()
+
+    def as_langchain(self) -> BaseLanguageModel:
+        """
+        Convert this instance into a LangChain compatible object
+        """
+        return ClaudeLangChainInstance(self)
+
+    def get_num_tokens(self, text: str) -> int:
+        encode = self._new_client().count_tokens(text)
+        return encode
+
+    def max_context_length(self) -> int:
+        if super().max_context_length():
+            return super().max_context_length()
+        return ClaudeMAXCONTETNLENGTH[self.model_name]
+
+    def close(self):
+        """Close the client."""
+        if hasattr(self, 'client') and self.client:
+            self.client.close()
+
+    async def aclose(self):
+        """Async close the client."""
+        if hasattr(self, 'async_client') and self.async_client:
+            await self.async_client.aclose()
diff --git a/agentuniverse/llm/default/claude_llm.yaml b/agentuniverse/llm/default/claude_llm.yaml
new file mode 100644
index 00000000..31538a3a
--- /dev/null
+++ b/agentuniverse/llm/default/claude_llm.yaml
@@ -0,0 +1,8 @@
+name: 'default_claude_llm'
+description: 'default kimi llm with spi'
+model_name: 'claude-3-opus-20240229'
+max_tokens: 4096
+metadata:
+  type: 'LLM'
+  module: 'agentuniverse.llm.default.claude_llm'
+  class: 'ClaudeLLM'
\ No newline at end of file
diff --git a/agentuniverse/llm/default/default_ollama_llm.py b/agentuniverse/llm/default/default_ollama_llm.py
new file mode 100644
index 00000000..e8cec875
--- /dev/null
+++ b/agentuniverse/llm/default/default_ollama_llm.py
@@ -0,0 +1,100 @@
+import json
+from typing import Any, Union, AsyncIterator, Iterator, Optional, List, Sequence
+
+import tiktoken
+from langchain_core.language_models import BaseLanguageModel
+from ollama import Options
+from pydantic import Field
+
+from agentuniverse.base.annotation.trace import trace_llm
+from agentuniverse.base.config.component_configer.configers.llm_configer import LLMConfiger
+from agentuniverse.base.util.env_util import get_from_env
+from agentuniverse.llm.llm import LLM
+from agentuniverse.llm.llm_output import LLMOutput
+from agentuniverse.llm.ollama_langchain_instance import OllamaLangchainInstance
+
+
+class OllamaLLM(LLM):
+    base_url: Optional[str] = Field(
+        default_factory=lambda: get_from_env("OLLAMA_BASE_URL") if get_from_env(
+            "OLLAMA_BASE_URL") else "http://localhost:11434")
+    """Base url the model is hosted under."""
+
+    streaming: bool = True
+
+    def _new_client(self):
+        if self.client:
+            return self.client
+        from ollama import Client
+        return Client(
+            host=self.base_url,
+        )
+
+    def _new_async_client(self):
+        if self.async_client:
+            return self.async_client
+        from ollama import AsyncClient
+        return AsyncClient(
+            host=self.base_url,
+        )
+
+    def _options(self):
+        return Options(**{
+            "num_ctx": self.max_context_length(),
+            "num_predict": self.max_tokens,
+            "temperature": self.temperature,
+            "timeout": self.request_timeout,
+            **(self.ext_info if self.ext_info else {}),
+        })
+
+    @trace_llm
+    def call(self, messages, stop=None, **kwargs) -> Union[LLMOutput, Iterator[LLMOutput]]:
+        should_stream = kwargs.pop("stream", self.streaming)
+        client = self._new_client()
+        options = self._options()
+        options.setdefault("stop", stop)
+        res = client.chat(model=self.model_name, messages=messages, options=options, stream=should_stream)
+        if should_stream:
+            return self.generate_result(res)
+        else:
+            return LLMOutput(text=res.get("message").get('content'), raw=json.dumps(res))
+
+    @trace_llm
+    async def acall(self, messages, stop=None, **kwargs) -> Union[LLMOutput, AsyncIterator[LLMOutput]]:
+        client = self._new_async_client()
+        should_stream = kwargs.pop("stream", self.streaming)
+        options = self._options()
+        options.setdefault("stop", stop)
+        res = await client.chat(model=self.model_name, messages=messages, options=options, stream=should_stream)
+        if not should_stream:
+            return LLMOutput(text=res.get("message").get('content'), raw=json.dumps(res))
+        if should_stream:
+            return self.agenerate_result(res)
+
+    def generate_result(self, data):
+        for line in data:
+            yield LLMOutput(text=line.get("message").get('content'), raw=json.dumps(line))
+
+    async def agenerate_result(self, data):
+        async for line in data:
+            yield LLMOutput(text=line.get("message").get('content'), raw=json.dumps(line))
+
+    def as_langchain(self) -> BaseLanguageModel:
+        return OllamaLangchainInstance(
+            self
+        )
+
+    def initialize_by_component_configer(self, component_configer: LLMConfiger) -> 'LLM':
+        super().initialize_by_component_configer(component_configer)
+        if 'base_url' in component_configer.configer.value:
+            self.base_url = component_configer.configer.value['base_url']
+        if 'max_context_length' in component_configer.configer.value:
+            self._max_context_length = component_configer.configer.value['max_context_length']
+        return self
+
+    def get_num_tokens(self, text: str) -> int:
+        try:
+            encoding = tiktoken.encoding_for_model(self.model_name)
+        except KeyError:
+            encoding = tiktoken.get_encoding("cl100k_base")
+        return len(encoding.encode(text))
diff --git a/agentuniverse/llm/default/default_ollama_llm.yaml b/agentuniverse/llm/default/default_ollama_llm.yaml
new file mode 100644
index 00000000..84b7a284
--- /dev/null
+++ b/agentuniverse/llm/default/default_ollama_llm.yaml
@@ -0,0 +1,9 @@
+name: 'default_ollama_llm'
+description: 'default openai llm with spi'
+model_name: 'qwen2:7b'
+max_tokens: 1000
+max_context_length: 32000
+metadata:
+  type: 'LLM'
+  module: 'agentuniverse.llm.default.default_ollama_llm'
+  class: 'OllamaLLM'
\ No newline at end of file
diff --git a/agentuniverse/llm/llm.py b/agentuniverse/llm/llm.py
index 736e7f67..53c4fd67 100644
--- a/agentuniverse/llm/llm.py
+++ b/agentuniverse/llm/llm.py
@@ -45,7 +45,7 @@ class LLM(ComponentBase):
     streaming: Optional[bool] = False
     ext_info: Optional[dict] = None
     tracing: Optional[bool] = None
-    __max_context_length: Optional[int] = None
+    _max_context_length: Optional[int] = None
 
     def __init__(self, **kwargs):
         """Initialize the llm."""
@@ -120,14 +120,14 @@ def set_by_agent_model(self, **kwargs) -> None:
         if 'streaming' in kwargs and kwargs['streaming']:
             self.streaming = kwargs['streaming']
         if 'max_context_length' in kwargs and kwargs['max_context_length']:
-            self.__max_context_length = kwargs['max_context_length']
+            self._max_context_length = kwargs['max_context_length']
 
     def max_context_length(self) -> int:
         """Max context length.
 
         The total length of input tokens and generated tokens is limited by the model's context length.
         """
-        return self.__max_context_length
+        return self._max_context_length
 
     @abstractmethod
     def get_num_tokens(self, text: str) -> int:
diff --git a/agentuniverse/llm/ollama_langchain_instance.py b/agentuniverse/llm/ollama_langchain_instance.py
new file mode 100644
index 00000000..845ffa64
--- /dev/null
+++ b/agentuniverse/llm/ollama_langchain_instance.py
@@ -0,0 +1,39 @@
+from typing import List, Optional, Iterator, Any, AsyncIterator
+
+from langchain_community.chat_models import ChatOllama
+from langchain_core.messages import BaseMessage
+
+from agentuniverse.llm.llm import LLM
+
+
+class OllamaLangchainInstance(ChatOllama):
+    llm: LLM = None
+
+    def __init__(self, llm: LLM):
+        super().__init__()
+        self.llm = llm
+        self.model = llm.model_name
+
+    def _create_chat_stream(
+            self,
+            messages: List[BaseMessage],
+            stop: Optional[List[str]] = None,
+            **kwargs: Any,
+    ) -> Iterator[str]:
+        data = self.llm.call(
+            messages=self._convert_messages_to_ollama_messages(messages), stop=stop, **kwargs
+        )
+        for llm_output in data:
+            yield llm_output.raw
+
+    async def _acreate_chat_stream(
+            self,
+            messages: List[BaseMessage],
+            stop: Optional[List[str]] = None,
+            **kwargs: Any,
+    ) -> AsyncIterator[str]:
+        data = await self.llm.acall(
+                messages=self._convert_messages_to_ollama_messages(messages), stop=stop, **kwargs
+        )
+        async for llm_output in data:
+            yield llm_output.raw
diff --git a/agentuniverse/llm/openai_style_langchain_instance.py b/agentuniverse/llm/openai_style_langchain_instance.py
index 8b9506ce..f17e01e8 100644
--- a/agentuniverse/llm/openai_style_langchain_instance.py
+++ b/agentuniverse/llm/openai_style_langchain_instance.py
@@ -6,11 +6,12 @@
 # @Email   : weizhongjie.wzj@antgroup.com
 # @FileName: langchain_openai_style_instance.py
 
-from typing import Any, List, Optional, AsyncIterator
+from typing import Any, List, Optional, AsyncIterator, Iterator
 
 from langchain.callbacks.manager import AsyncCallbackManagerForLLMRun, CallbackManagerForLLMRun
 from langchain.schema import BaseMessage, ChatResult
-from langchain_community.chat_models.openai import _convert_delta_to_message_chunk
+from langchain_community.chat_models.openai import _convert_delta_to_message_chunk, _create_retry_decorator
+from langchain_community.utils.openai import is_openai_v1
 from langchain_core.language_models.chat_models import generate_from_stream, agenerate_from_stream
 from langchain_core.messages import AIMessageChunk, get_buffer_string
 from langchain_core.outputs import ChatGenerationChunk
@@ -19,6 +20,25 @@
 from agentuniverse.llm.llm import LLM
 
 
+async def acompletion_with_retry(
+        llm: ChatOpenAI,
+        run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
+        **kwargs: Any,
+) -> Any:
+    """Use tenacity to retry the async completion call."""
+    if is_openai_v1():
+        return await llm.llm.acall(**kwargs)
+
+    retry_decorator = _create_retry_decorator(llm, run_manager=run_manager)
+
+    @retry_decorator
+    async def _completion_with_retry(**kwargs: Any) -> Any:
+        # Use OpenAI's async api https://github.com/openai/openai-python#async-api
+        return await llm.llm.acall(**kwargs)
+
+    return await _completion_with_retry(**kwargs)
+
+
 class LangchainOpenAIStyleInstance(ChatOpenAI):
     """Langchain OpenAI LLM wrapper."""
 
@@ -134,3 +154,88 @@ async def as_langchain_achunk(stream_iterator: AsyncIterator, run_manager=None)
     def get_num_tokens_from_messages(self, messages: List[BaseMessage]) -> int:
         messages_str = get_buffer_string(messages)
         return self.llm.get_num_tokens(messages_str)
+
+    def completion_with_retry(
+            self, run_manager: Optional[CallbackManagerForLLMRun] = None, **kwargs: Any
+    ) -> Any:
+        """Use tenacity to retry the completion call."""
+        if is_openai_v1():
+            return self.llm.call(**kwargs)
+
+        retry_decorator = _create_retry_decorator(self, run_manager=run_manager)
+
+        @retry_decorator
+        def _completion_with_retry(**kwargs: Any) -> Any:
+            return self.llm.call(**kwargs)
+
+        return _completion_with_retry(**kwargs)
+
+    def _stream(
+            self,
+            messages: List[BaseMessage],
+            stop: Optional[List[str]] = None,
+            run_manager: Optional[CallbackManagerForLLMRun] = None,
+            **kwargs: Any,
+    ) -> Iterator[ChatGenerationChunk]:
+        message_dicts, params = self._create_message_dicts(messages, stop)
+        params = {**params, **kwargs, "stream": True}
+
+        default_chunk_class = AIMessageChunk
+        for chunk in self.completion_with_retry(
+                messages=message_dicts, run_manager=run_manager, **params
+        ):
+            chunk = chunk.raw
+            if not isinstance(chunk, dict):
+                chunk = chunk.dict()
+            if len(chunk["choices"]) == 0:
+                continue
+            choice = chunk["choices"][0]
+            chunk = _convert_delta_to_message_chunk(
+                choice["delta"], default_chunk_class
+            )
+            finish_reason = choice.get("finish_reason")
+            generation_info = (
+                dict(finish_reason=finish_reason) if finish_reason is not None else None
+            )
+            default_chunk_class = chunk.__class__
+            cg_chunk = ChatGenerationChunk(
+                message=chunk, generation_info=generation_info
+            )
+            if run_manager:
+                run_manager.on_llm_new_token(cg_chunk.text, chunk=cg_chunk)
+            yield cg_chunk
+
+    async def _astream(
+            self,
+            messages: List[BaseMessage],
+            stop: Optional[List[str]] = None,
+            run_manager: Optional[AsyncCallbackManagerForLLMRun] = None,
+            **kwargs: Any,
+    ) -> AsyncIterator[ChatGenerationChunk]:
+        message_dicts, params = self._create_message_dicts(messages, stop)
+        params = {**params, **kwargs, "stream": True}
+
+        default_chunk_class = AIMessageChunk
+        async for chunk in await acompletion_with_retry(
+                self, messages=message_dicts, run_manager=run_manager, **params
+        ):
+            chunk = chunk.raw
+            if not isinstance(chunk, dict):
+                chunk = chunk.dict()
+            if len(chunk["choices"]) == 0:
+                continue
+            choice = chunk["choices"][0]
+            chunk = _convert_delta_to_message_chunk(
+                choice["delta"], default_chunk_class
+            )
+            finish_reason = choice.get("finish_reason")
+            generation_info = (
+                dict(finish_reason=finish_reason) if finish_reason is not None else None
+            )
+            default_chunk_class = chunk.__class__
+            cg_chunk = ChatGenerationChunk(
+                message=chunk, generation_info=generation_info
+            )
+            if run_manager:
+                await run_manager.on_llm_new_token(token=cg_chunk.text, chunk=cg_chunk)
+            yield cg_chunk
diff --git a/agentuniverse/llm/openai_style_llm.py b/agentuniverse/llm/openai_style_llm.py
index c4a84da4..2d5a3ea0 100644
--- a/agentuniverse/llm/openai_style_llm.py
+++ b/agentuniverse/llm/openai_style_llm.py
@@ -71,6 +71,8 @@ def call(self, messages: list, **kwargs: Any) -> Union[LLMOutput, Iterator[LLMOu
             **kwargs: Arbitrary keyword arguments.
         """
         streaming = kwargs.pop("streaming") if "streaming" in kwargs else self.streaming
+        if 'stream' in kwargs:
+            streaming = kwargs.pop('stream')
         self.client = self._new_client()
         client = self.client
         chat_completion = client.chat.completions.create(
diff --git a/docs/guidebook/_picture/agent_universe_framework_resize.jpg b/docs/guidebook/_picture/agent_universe_framework_resize.jpg
index 49b98171..85803339 100644
Binary files a/docs/guidebook/_picture/agent_universe_framework_resize.jpg and b/docs/guidebook/_picture/agent_universe_framework_resize.jpg differ
diff --git a/docs/guidebook/_picture/chinese_or_western_medicine.png b/docs/guidebook/_picture/chinese_or_western_medicine.png
new file mode 100644
index 00000000..e611f6ba
Binary files /dev/null and b/docs/guidebook/_picture/chinese_or_western_medicine.png differ
diff --git a/docs/guidebook/_picture/coca-cola_or_pepsi.png b/docs/guidebook/_picture/coca-cola_or_pepsi.png
new file mode 100644
index 00000000..619b98dc
Binary files /dev/null and b/docs/guidebook/_picture/coca-cola_or_pepsi.png differ
diff --git a/docs/guidebook/_picture/law_agent_demo.png b/docs/guidebook/_picture/law_agent_demo.png
new file mode 100644
index 00000000..2f67ec55
Binary files /dev/null and b/docs/guidebook/_picture/law_agent_demo.png differ
diff --git a/docs/guidebook/_picture/react_demo_step.png b/docs/guidebook/_picture/react_demo_step.png
new file mode 100644
index 00000000..84ad6909
Binary files /dev/null and b/docs/guidebook/_picture/react_demo_step.png differ
diff --git a/docs/guidebook/_picture/sweet_or_salted_zongzi.png b/docs/guidebook/_picture/sweet_or_salted_zongzi.png
new file mode 100644
index 00000000..76720c44
Binary files /dev/null and b/docs/guidebook/_picture/sweet_or_salted_zongzi.png differ
diff --git a/docs/guidebook/en/0_index.md b/docs/guidebook/en/0_index.md
index 36bb852b..6fa4e741 100644
--- a/docs/guidebook/en/0_index.md
+++ b/docs/guidebook/en/0_index.md
@@ -52,6 +52,8 @@
     * 3.1.2.3 [WenXin Usage Instructions](3_1_2_WenXin_LLM_Use.md)
     * 3.1.2.4 [Kimi Usage Instructions](3_1_2_Kimi_LLM_Use.md)
     * 3.1.2.5 [BaiChuan Usage Instructions](3_1_2_BaiChuan_LLM_Use.md)
+    * 3.1.2.6 [Claude Usage Instructions](3_1_2_Claude_LLM_Use.md)
+    * 3.1.2.7 [Ollama Usage Instructions](3_1_2_Ollama_LLM_Use.md)
   * 3.1.3 List of Tools
   * 3.1.4 List of Knowledge
   * 3.1.5 List of Memories
@@ -62,6 +64,7 @@
   * 3.2.2 Store
     * 3.2.2.1 [SQLDBWrapper](2_3_1_SQLDB_WRAPPER.md)
     * 3.2.2.2 [Milvus](3_3_1_Milvus.md)
+    * 3.2.2.3 [ChromaDB](3_3_2_ChromaDB.md)
   * 3.2.3 Msg
   * 3.2.4 Logging
     * 3.2.4.1 [Alibaba Cloud SLS](3_2_4_Alibaba_Cloud_SLS.md)
@@ -73,8 +76,15 @@
   * 5.1.1 [Docker Containerization Solution](5_1_1_Docker_Container_Deployment.md)
   * 5.1.2 [K8S Solution](5_1_2_K8S_Deployment.md)
 
-**6. Series of Articles**
+**6. Use Cases**
+* 6.1 RAG-Type Agent Examples
+  * 6.1.1 [Legal Consultation Agent](7_1_1_Legal_Consultation_Case.md)
+* 6.2 ReAct-Type Agent Examples
+  * 6.2.1 [Python Code Generation and Execution Agent](7_1_1_Python_Auto_Runner.md)
+* 6.3 [Discussion Group Based on Multi-Turn Multi-Agent Mode](6_2_1_Discussion_Group.md)
 
-**7. Frequently Asked Questions (FAQ)**
+**7. Series of Articles**
 
-**[8. Contact Us](6_1_Contact_Us.md)**
+**8. Frequently Asked Questions (FAQ)**
+
+**[9. Contact Us](6_1_Contact_Us.md)**
diff --git a/docs/guidebook/en/2_2_6_Planner_Define_And_Use.md b/docs/guidebook/en/2_2_6_Planner_Define_And_Use.md
index b67897fa..6979676b 100644
--- a/docs/guidebook/en/2_2_6_Planner_Define_And_Use.md
+++ b/docs/guidebook/en/2_2_6_Planner_Define_And_Use.md
@@ -112,7 +112,7 @@ class RagPlanner(Planner):
         """
         memory: ChatMemory = self.handle_memory(agent_model, planner_input)
 
-        self.handle_all_actions(agent_model, planner_input, input_object)
+        self.run_all_actions(agent_model, planner_input, input_object)
 
         llm: LLM = self.handle_llm(agent_model)
 
diff --git a/docs/guidebook/en/3_1_2_0_List_Of_LLMs.md b/docs/guidebook/en/3_1_2_0_List_Of_LLMs.md
index 5d5975eb..a56aa83f 100644
--- a/docs/guidebook/en/3_1_2_0_List_Of_LLMs.md
+++ b/docs/guidebook/en/3_1_2_0_List_Of_LLMs.md
@@ -8,7 +8,9 @@ The platform has currently integrated the following list of models; please refer
 | [WenXin](3_1_2_WenXin_LLM_Use.md)     |
 | [Kimi](3_1_2_Kimi_LLM_Use.md)         |
 | [BaiChuan](3_1_2_BaiChuan_LLM_Use.md) |
+| [Claude](3_1_2_Claude_LLM_Use.md)     |
+| [ollama](3_1_2_Ollama_LLM_Use.md)     |
 
 For LLM not included in the list, you can customize the integration of any LLM according to the steps provided in the [LLM definition](2_2_3_Tool_Create_And_Use.md).
 
-At the same time, we are adding the integration methods for common LLMs such as Claude, Gemini, ollama, Llama, ZhipuAI, etc. If you have used these LLMs in your projects and have created your own instances, we welcome you to submit a PR to become a contributor to agentUniverse.
\ No newline at end of file
+At the same time, we are adding the integration methods for common LLMs such as Gemini, Llama, ZhipuAI, etc. If you have used these LLMs in your projects and have created your own instances, we welcome you to submit a PR to become a contributor to agentUniverse.
\ No newline at end of file
diff --git a/docs/guidebook/en/3_1_2_Claude_LLM_Use.md b/docs/guidebook/en/3_1_2_Claude_LLM_Use.md
new file mode 100644
index 00000000..b18de2fd
--- /dev/null
+++ b/docs/guidebook/en/3_1_2_Claude_LLM_Use.md
@@ -0,0 +1,34 @@
+# Calude Usage
+## 1. Create the relevant file.
+Create a YAML file, for example, user_claude.yaml
+Paste the following content into your user_claude.yaml file.
+```yaml
+name: 'user_claude_llm'
+description: 'user claude llm with spi'
+model_name: 'claude-3-opus-20240229'
+max_tokens: 4096
+metadata:
+  type: 'LLM'
+  module: 'agentuniverse.llm.default.claude_llm'
+  class: 'ClaudeLLM'
+```
+## 2. Environment Setup
+Must be configured: ANTHROPIC_API_KEY  
+Optional: ANTHROPIC_API_URL
+### 2.1 Configure through Python code
+```python
+import os
+os.environ['ANTHROPIC_API_KEY'] = 'sk-***'
+os.environ['ANTHROPIC_API_URL'] = 'https://xxxxxx'
+```
+### 2.2 Configure through the configuration file
+In the custom_key.toml file under the config directory of the project, add the configuration:
+```toml
+ANTHROPIC_API_KEY="sk-******"
+ANTHROPIC_API_URL="https://xxxxxx"
+```
+## 3. Obtaining the ANTHROPIC API KEY
+Reference Claude Official Documentation: https://docs.anthropic.com/zh-CN/docs/getting-access-to-claude
+
+## 4. Note
+In agentuniverse, we have already created an llm with the name default_claude_llm. After configuring the ANTHROPIC_API_KEY, users can directly use it.
\ No newline at end of file
diff --git a/docs/guidebook/en/3_1_2_Ollama_LLM_Use.md b/docs/guidebook/en/3_1_2_Ollama_LLM_Use.md
new file mode 100644
index 00000000..cce2b0e6
--- /dev/null
+++ b/docs/guidebook/en/3_1_2_Ollama_LLM_Use.md
@@ -0,0 +1,32 @@
+# Ollama Usage
+## 1. Create the relevant file.
+Create a YAML file, for example, user_ollama.yaml
+Paste the following content into your user_ollama.yaml file.
+```yaml
+name: 'user_ollama_llm'
+description: 'user ollama llm with spi'
+model_name: 'qwen2:7b'
+max_tokens: 1000
+max_context_length: 32000
+metadata:
+  type: 'LLM'
+  module: 'agentuniverse.llm.default.default_ollama_llm'
+  class: 'OllamaLLM'
+```
+## 2. Environment Setup
+### 2.1 Configure through Python code
+Must be configured: OLLAMA_BASE_URL
+```python
+import os
+os.environ['OLLAMA_BASE_URL'] = 'https://xxxxxx'
+```
+### 2.2 Configure through the configuration file
+In the custom_key.toml file under the config directory of the project, add the configuration:
+```toml
+OLLAMA_BASE_URL="https://xxxxxx"
+```
+
+## 4. Tips
+In agentuniverse, we have already created an llm with the name default_ollama_llm. After configuring the OLLAMA_BASE_URL, users can directly use it.
+Reference: https://www.ollama.com/library/qwen2
+
diff --git a/docs/guidebook/en/3_3_1_Milvus.md b/docs/guidebook/en/3_3_1_Milvus.md
index a0c83538..cc23c7ae 100644
--- a/docs/guidebook/en/3_3_1_Milvus.md
+++ b/docs/guidebook/en/3_3_1_Milvus.md
@@ -18,7 +18,8 @@ pip install pymilvus
 ```
 
 ### What can I do with Milvus
-You can use Milvus in the Knowledge component to store and query knowledge. You can create a storage component using Milvus as follows:
+
+You can use Milvus in the [Knowledge component](2_2_4_Knowledge.md) to store and query knowledge. You can create a storage component using Milvus as follows:
 
 ```python
 from agentuniverse.agent.action.knowledge.store.milvus_store import MilvusStore
@@ -37,4 +38,5 @@ init_params['store'] = MilvusStore(
 )
 knowledge = Knowledge(**init_params)
 ```
-The above code will create a Milvus-based Knowledge instance. For detailed usage of Knowledge, you can refer to the [Knowledge documentation]() or the code `tests/test_agentuniverse/unit/agent/action/knowledge/test_knowledge_with_milvus.py`.
\ No newline at end of file
+
+The above code will create a Milvus-based Knowledge instance. For detailed usage of Knowledge, you can refer to the [Knowledge component](2_2_4_Knowledge.md) or the code `tests/test_agentuniverse/unit/agent/action/knowledge/test_knowledge_with_milvus.py`.
diff --git a/docs/guidebook/en/3_3_2_ChromaDB.md b/docs/guidebook/en/3_3_2_ChromaDB.md
new file mode 100644
index 00000000..d48ffc2b
--- /dev/null
+++ b/docs/guidebook/en/3_3_2_ChromaDB.md
@@ -0,0 +1,24 @@
+## ChromaDB
+
+The agentUniverse already integrates ChromaDB-related dependencies, so you do not need to install additional packages to use ChromaDB's features.
+If you want to learn about the underlying principles of ChromaDB, you can visit the [official ChromaDB website](https://www.trychroma.com/).
+
+### What can I do with ChromaDB?
+
+
+You can use ChromaDB in the [Knowledge component](2_2_4_Knowledge.md) to store and query knowledge. You can create a storage component using ChromaDB with the following method:
+```python
+from agentuniverse.agent.action.knowledge.embedding.openai_embedding import OpenAIEmbedding
+from agentuniverse.agent.action.knowledge.knowledge import Knowledge
+from agentuniverse.agent.action.knowledge.store.chroma_store import ChromaStore
+
+
+init_params = dict()
+init_params['name'] = 'test_knowledge'
+init_params['description'] = 'test_knowledge_description'
+init_params['store'] = ChromaStore(collection_name="test_knowledge", embedding_model=OpenAIEmbedding(
+    embedding_model_name='text-embedding-ada-002'))
+knowledge = Knowledge(**init_params)
+```
+
+The above code will create a Knowledge component based on ChromaDB. For more details on how to use the Knowledge component, you can refer to the [Knowledge component](2_2_4_Knowledge.md)，or check the code in `tests/test_agentuniverse/unit/agent/action/knowledge/test_knowledge.py`。
diff --git a/docs/guidebook/en/6_2_1_Discussion_Group.md b/docs/guidebook/en/6_2_1_Discussion_Group.md
new file mode 100644
index 00000000..bf8ee3c7
--- /dev/null
+++ b/docs/guidebook/en/6_2_1_Discussion_Group.md
@@ -0,0 +1,122 @@
+# Discussion: Multi-Agent Discussion Group
+In this use case, we will demonstrate how to use agentUniverse for multi-agent discussions.
+
+There are two agent roles: discussion group host (one) and discussion group participants (several).
+
+The user initiates a discussion topic, and the host organizes the participants to start the discussion. In each round, each participant expresses his or her own views according to the topic of the discussion (the views of each participant are not immutable and will be constantly adjusted as the discussion goes on). After several rounds of discussion, the host will summarize the discussion process and return the results of the participants after several rounds of discussion to the user.
+
+Many heads are better than one, imagine that you have a question you want to answer and submit it directly to the agentUniverse discussion group, The host will organize multiple agents with different ideas together, focus on your question, and finally give you a comprehensive and intelligent answer, which is an interesting agent experiment.
+
+## Quick Start
+### Configure API Key
+For example, configure key information in the file `custom_ key.toml` in which agentUniverse manages private key configuration (The agentUniverse discussion group uses GPT as the base model and Serper as the Google search tool by default. The following describes how to use other models or tools).
+```toml
+[KEY_LIST]
+# serper google search key
+SERPER_API_KEY='xxx'
+# openai api key
+OPENAI_API_KEY='xxx'
+```
+### Modify Prompt Version
+Modify the prompt version of agents to the english version, the discussion group multi-agent configuration file is located in the app/core/agent/discussion_agent_case directory in the `sample_standard_app` sample project. Find the host_agent.yaml and change `prompt_version` to `host_agent.en`, similarly find the participants yaml file and change the `prompt_version` to `participant_agent.en`.
+
+```yaml
+info:
+  name: 'host_agent'
+  description: 'host agent'
+profile:
+  prompt_version: host_agent.en
+  llm_model:
+    name: 'demo_llm'
+    temperature: 0.6
+plan:
+  planner:
+    name: 'discussion_planner'
+    round: 2
+    participant:
+      name:
+        - 'participant_agent_one'
+        - 'participant_agent_two'
+memory:
+  name: 'demo_memory'
+metadata:
+  type: 'AGENT'
+  module: 'sample_standard_app.app.core.agent.discussion_agent_case.host_agent'
+  class: 'HostAgent'
+```
+
+
+### Run Discussion Group
+In the sample project of agentUnvierse `sample_standard_app`, find the `discussion_chat_bots.py` file in the app/examples directory, enter the question you want to answer in the chat method, and run it.
+
+For example, enter the question: Which tastes better, Coca-Cola or Pepsi
+```python
+from agentuniverse.base.agentuniverse import AgentUniverse
+from agentuniverse.agent.agent import Agent
+from agentuniverse.agent.agent_manager import AgentManager
+
+AgentUniverse().start(config_path='../../config/config.toml')
+
+
+def chat(question: str):
+    instance: Agent = AgentManager().get_instance_obj('host_agent')
+    instance.run(input=question)
+
+
+if __name__ == '__main__':
+    chat("Which tastes better, Coca-Cola or Pepsi")
+```
+### Result Demonstration
+Which tastes better, Coca-Cola or Pepsi：
+
+![Picture](../_picture/coca-cola_or_pepsi.png)
+
+## More Details
+### Agent Configuration
+The discussion group multi-agent configuration files are located in the app/core/agent/discussion_agent_case directory in the `sample_standard_app` sample project.
+
+The host corresponds to `host_agent.yaml` and the participant corresponds to `participant_agent_*.yaml`.
+
+
+The prompt is managed by the prompt version. For example, the default prompt_version of host_agent is `host_agent.cn`, and the corresponding prompt file is `host_agent.cn.yaml` under the app/core/prompt directory.
+
+If the LLM Model will be modified to another, such as the Qwen model, change the `llm_model` name information (such as the `qwen_llm` built into the aU system).
+
+The number of discussion rounds in agent plan defaults to 2, which users can adjust as needed. The default participants are two agents built into aU, which can add discussion group members by creating new agents and configuring the agent name parameter to the `participant` of the planner.
+
+```yaml
+info:
+  name: 'host_agent'
+  description: 'host agent'
+profile:
+  prompt_version: host_agent.cn
+  llm_model:
+    name: 'qwen_llm'
+    temperature: 0.6
+plan:
+  planner:
+    name: 'discussion_planner'
+    round: 2
+    participant:
+      name:
+        - 'participant_agent_one'
+        - 'participant_agent_two'
+memory:
+  name: 'demo_memory'
+metadata:
+  type: 'AGENT'
+  module: 'sample_standard_app.app.core.agent.discussion_agent_case.host_agent'
+  class: 'HostAgent'
+```
+
+### Memory Configuration
+Participants in the aU discussion group configure `demo_memory` in the `sample_standard_app` sample project by default to store common memory information for the entire discussion group.
+
+### Planner Configuration
+The planner configuration file is located in the app/core/planner directory of the `sample_standard_app` sample project, where the `discussion_planner.py` file is the specific plan process code of the discussion group. If you are interested, you can read it yourself.
+
+### Prompt Configuration
+The prompt is managed by the prompt version, and the default prompt files of the aU discussion group agent are configured in the app/core/prompt directory. Corresponding to the Chinese and English versions (host_agent_xx.yaml/participant_agent_xx.yaml), users can change the prompt_version in the agent configuration to complete fast switching.
+
+### Tool Configuration
+Two participants in the aU discussion group are configured with google_search_tool by default. Users can change the `tool name` in the `participant_agent_xxx.yaml` under the app/core/agent/discussion_agent_case directory in the `sample_standard_app` sample project to switch tool calls.
diff --git a/docs/guidebook/en/7_1_1_Legal_Consultation_Case.md b/docs/guidebook/en/7_1_1_Legal_Consultation_Case.md
new file mode 100644
index 00000000..14782290
--- /dev/null
+++ b/docs/guidebook/en/7_1_1_Legal_Consultation_Case.md
@@ -0,0 +1,35 @@
+# Legal Consultation Case
+## Case Description
+This case is based on RagPlanner and builds a simple legal consultation agent. It provides relevant legal advice by retrieving related articles from the Civil Code and Criminal Law and combining them with the case background.
+
+This case utilizes the Qianwen large model and the DashScope embedding feature. Before using it, you need to configure the DASHSCOPE_API_KEY in your environment variables.
+
+## Components
+### Legal Knowledge Base
+The legal knowledge base is based on the [Knowledge Component ](2_2_4_知识.md) in agentUniverse. By embedding the original text of legal articles and storing them in the ChromaDB vector database, it creates a knowledge base that the agent can easily reference and retrieve.  
+Original legal texts:
+- [Civil Code.pdf](../../../sample_standard_app/app/resources/民法典.pdf)
+- [Criminal Law.pdf](../../../sample_standard_app/app/resources/刑法.pdf)
+
+You can refer to the following code:
+- [Civil Code Knowledge Base](../../../sample_standard_app/app/core/knowledge/civil_law_knowledge.py)
+- [Criminal Law Knowledge Base](../../../sample_standard_app/app/core/knowledge/criminal_law_knowledge.py)
+
+To make it convenient for you, we have placed the database files with relevant information in [this directory](../../../sample_standard_app/DB/), If you want to build the knowledge base from scratch, you can modify the following part of the code:
+```python
+# Initialize the knowledge
+# self.insert_knowledge()
+```
+Remove the comment from self.insert_knowledge() to rebuild the database.
+
+### Law Agent
+This agent involves the following two files:
+- [law_rag_agent.py](../../../sample_standard_app/app/core/agent/rag_agent_case/law_rag_agent.py): Defines the agent's input and output
+- [law_rag_agent.yaml](../../../sample_standard_app/app/core/agent/rag_agent_case/law_rag_agent.yaml): Defines the agent's related prompts
+
+
+### Demonstration Code
+[CodeLink](../../../sample_standard_app/app/examples/law_chat_bot.py)
+
+## Demonstration
+![Demonstration Image](../_picture/law_agent_demo.png)
\ No newline at end of file
diff --git a/docs/guidebook/en/7_1_1_Python_Auto_Runner.md b/docs/guidebook/en/7_1_1_Python_Auto_Runner.md
new file mode 100644
index 00000000..1832cf62
--- /dev/null
+++ b/docs/guidebook/en/7_1_1_Python_Auto_Runner.md
@@ -0,0 +1,73 @@
+# Python Auto Runner
+## Case Illustration
+This case is based on ReactPlanner, building a simple case that can automatically generate and execute Python code.
+This case is based on the QianWen large language model and the google_search function, requiring you to configure the environment variables DASHSCOPE_API_KEY, SERPER_API_KEY before use.
+
+## Quick Start
+### Configure API Key
+For example, configure key information in the file custom_key.toml where agentUniverse manages private keys (the default discussion group uses qwen as the base model and serper as the google search tool).
+```toml
+[KEY_LIST]
+# serper google search key
+SERPER_API_KEY='xxx'
+# openai api key
+DASHSCOPE_API_KEY='xxx'
+```
+
+### Agent Configuration
+```yaml
+info:
+  name: 'demo_react_agent'
+  description: 'react agent'
+profile:
+  prompt_version: qwen_react_agent.cn
+  llm_model:
+    name: 'default_qwen_llm'
+    model_name : 'qwen-max'
+    temperature: 0
+action:
+  tool:
+    - 'google_search_tool'
+    - 'python_runner'
+plan:
+  planner:
+    name: 'react_planner'
+metadata:
+  type: 'AGENT'
+  module: 'agentuniverse.agent.default.react_agent.react_agent'
+  class: 'ReActAgent'
+```
+
+Here we used two tools: google_search_tool and python_runner. The relevant tool code links are as follows:
+- [google_search_tool](../../../sample_standard_app/app/core/tool/google_search_tool.yaml)
+- [python_runner](../../../sample_standard_app/app/core/tool/python_repl_tool.yaml)
+
+
+### Case Run
+1. Test Case Run
+Directly run with test code[test_case](../../../sample_standard_app/app/test/test_react_agent.py)
+2. Interface Run
+After configuring the related keys, start the web service and use the following curl for testing.
+```shell
+curl --location --request POST 'http://localhost:8888/service_run' \
+--header 'Cookie: spanner=fQ47DxJmWYzf8rKDhs69LExySZYZFUiVXt2T4qEYgj0' \
+--header 'Content-Type: application/json' \
+--data-raw '{
+    
+    "service_id": "demo_react_service",
+    "params": {
+        "input": "请帮我生成一段python代码，可以计算三数之和"
+    }
+}'
+```
+
+### Result
+![test_case](../_picture/react_demo_step.png)
+
+In the image, React went through three steps in total:  
+Step 1: The model provided a piece of Python code and handed it over to the Python Runner tool for execution, but the execution failed due to the failure to use print to output the execution result.  
+Step 2: The model realized the mistake and proactively modified the code. It then used the Python Runner tool again for execution, which was successful.  
+Step 3: The model conveyed the successfully executed code to the user.  
+
+### Please note
+Due to limitations of the model's capabilities, it is recommended to use the qwen-max model for testing.
\ No newline at end of file
diff --git "a/docs/guidebook/zh/0_\347\233\256\345\275\225.md" "b/docs/guidebook/zh/0_\347\233\256\345\275\225.md"
index 4b26c3de..43a9b654 100644
--- "a/docs/guidebook/zh/0_\347\233\256\345\275\225.md"
+++ "b/docs/guidebook/zh/0_\347\233\256\345\275\225.md"
@@ -56,6 +56,8 @@
     * 3.1.2.3 [文心一言使用说明](3_1_2_文心使用.md)
     * 3.1.2.4 [Kimi使用说明](3_1_2_Kimi使用.md)
     * 3.1.2.5 [百川使用说明](3_1_2_百川使用.md)
+    * 3.1.2.6 [Claude使用说明](3_1_2_Claude使用.md)
+    * 3.1.2.7 [Ollama使用说明](3_1_2_Ollama使用.md)
   * 3.1.3 工具列表(Tool)
   * 3.1.4 知识列表(Knowledge)
   * 3.1.5 记忆列表(Memory)
@@ -66,6 +68,7 @@
   * 3.2.2 存储 (Store)
     * 3.2.2.1 [SQLDBWrapper](2_3_1_SQLDB_WRAPPER.md)
     * 3.2.2.2 [Milvus](3_3_1_Milvus.md)
+    * 3.2.2.3 [ChromaDB](3_3_2_ChromaDB.md)
   * 3.2.3 消息(Msg)
   * 3.2.4 日志(Logging)
     * 3.2.4.1 [阿里云SLS](3_2_4_阿里云SLS.md)
@@ -77,8 +80,15 @@
   * 5.1.1 [Docker容器化方案](5_1_1_Docker容器化部署.md)
   * 5.1.2 [K8S部署方案](5_1_2_K8S部署.md)
 
-**6.系列文章**
+**6.使用案例**
+* 6.1 RAG类Agent案例
+  * 6.1.1 [法律咨询Agent](7_1_1_法律咨询案例.md)
+* 6.2 ReAct类Agent案例
+  * 6.2.1 [Python代码生成与执行Agent](7_1_1_Python自动执行案例.md)
+* 6.3 [基于多轮多Agent的讨论小组](6_2_1_讨论组.md)
 
-**7.常见问题FAQ**
+**7.系列文章**
 
-**[8.联系我们](6_1_联系我们.md)**
+**8.常见问题FAQ**
+
+**[9.联系我们](6_1_联系我们.md)**
diff --git "a/docs/guidebook/zh/2_2_6_\350\256\241\345\210\222\345\256\232\344\271\211\344\270\216\344\275\277\347\224\250.md" "b/docs/guidebook/zh/2_2_6_\350\256\241\345\210\222\345\256\232\344\271\211\344\270\216\344\275\277\347\224\250.md"
index 0f6946db..1b8485cc 100644
--- "a/docs/guidebook/zh/2_2_6_\350\256\241\345\210\222\345\256\232\344\271\211\344\270\216\344\275\277\347\224\250.md"
+++ "b/docs/guidebook/zh/2_2_6_\350\256\241\345\210\222\345\256\232\344\271\211\344\270\216\344\275\277\347\224\250.md"
@@ -112,7 +112,7 @@ class RagPlanner(Planner):
         """
         memory: ChatMemory = self.handle_memory(agent_model, planner_input)
 
-        self.handle_all_actions(agent_model, planner_input, input_object)
+        self.run_all_actions(agent_model, planner_input, input_object)
 
         llm: LLM = self.handle_llm(agent_model)
 
diff --git "a/docs/guidebook/zh/3_1_2_0_\346\250\241\345\236\213\345\210\227\350\241\250.md" "b/docs/guidebook/zh/3_1_2_0_\346\250\241\345\236\213\345\210\227\350\241\250.md"
index 4791894c..5e62a724 100644
--- "a/docs/guidebook/zh/3_1_2_0_\346\250\241\345\236\213\345\210\227\350\241\250.md"
+++ "b/docs/guidebook/zh/3_1_2_0_\346\250\241\345\236\213\345\210\227\350\241\250.md"
@@ -1,14 +1,16 @@
 # 模型（LLM）列表
 目前平台已经接入了如下模型列表，详细使用方式请关注本章节各LLM的说明。
 
-| 模型LLM(系列)名称                  |
-|------------------------------|
-| [OpenAI](3_1_2_OpenAI使用.md)  |
-| [通义千问](3_1_2_Qwen使用.md)      |
-| [文心一言](3_1_2_文心使用.md)        |
-| [Kimi](3_1_2_Kimi使用.md)      |
-| [百川](3_1_2_百川使用.md)          |
+| 模型LLM(系列)名称                      |
+|----------------------------------|
+| [OpenAI](3_1_2_OpenAI使用.md)      |
+| [通义千问](3_1_2_Qwen使用.md)          |
+| [文心一言](3_1_2_文心使用.md)            |
+| [Kimi](3_1_2_Kimi使用.md)          |
+| [百川](3_1_2_百川使用.md)              |
+| [Claude](3_1_2_Claude使用.md)      |
+| [ollama](3_1_2_Ollama使用.md)      |
 
 未在列表中的模型您可以根据[模型定义](2_2_2_模型定义与使用.md)中的步骤自定义接入任何模型。
 
-同时我们正在添加Claude、Gemini、ollama、Llama、ZhipuAI等常见LLM的接入方式，如果您在工程中使用了这些LLM并创建了属于自己的实例，欢迎您提交pr成为agentUniverse的contributor。
\ No newline at end of file
+同时我们正在添加Gemini、Llama、ZhipuAI等常见LLM的接入方式，如果您在工程中使用了这些LLM并创建了属于自己的实例，欢迎您提交pr成为agentUniverse的contributor。
\ No newline at end of file
diff --git "a/docs/guidebook/zh/3_1_2_Claude\344\275\277\347\224\250.md" "b/docs/guidebook/zh/3_1_2_Claude\344\275\277\347\224\250.md"
new file mode 100644
index 00000000..af62c192
--- /dev/null
+++ "b/docs/guidebook/zh/3_1_2_Claude\344\275\277\347\224\250.md"
@@ -0,0 +1,34 @@
+# Claude 使用
+## 1. 创建相关文件
+创建一个yaml文件，例如 user_claude.yaml
+将以下内容粘贴到您的user_claude.yaml文件当中
+```yaml
+name: 'user_claude_llm'
+description: 'user claude llm with spi'
+model_name: 'claude-3-opus-20240229'
+max_tokens: 4096
+metadata:
+  type: 'LLM'
+  module: 'agentuniverse.llm.default.claude_llm'
+  class: 'ClaudeLLM'
+```
+## 2. 环境设置
+必须配置：ANTHROPIC_API_KEY  
+选配：ANTHROPIC_API_URL
+### 2.1 通过python代码配置
+```python
+import os
+os.environ['ANTHROPIC_API_KEY'] = 'sk-***'
+os.environ['ANTHROPIC_API_URL'] = 'https://xxxxxx'
+```
+### 2.2 通过配置文件配置
+在项目的config目录下的custom_key.toml当中，添加配置：
+```toml
+ANTHROPIC_API_KEY="sk-******"
+ANTHROPIC_API_URL="https://xxxxxx"
+```
+## 3. Claude API KEY 获取
+参考 Claude 官方文档：https://docs.anthropic.com/zh-CN/docs/getting-access-to-claude
+
+## 4. 注意
+在agentuniverse中，我们已经创建了一个name为default_claude_llm的llm,用户在配置ANTHROPIC_API_KEY之后可以直接使用
\ No newline at end of file
diff --git "a/docs/guidebook/zh/3_1_2_Ollama\344\275\277\347\224\250.md" "b/docs/guidebook/zh/3_1_2_Ollama\344\275\277\347\224\250.md"
new file mode 100644
index 00000000..dbf3ed3a
--- /dev/null
+++ "b/docs/guidebook/zh/3_1_2_Ollama\344\275\277\347\224\250.md"
@@ -0,0 +1,32 @@
+# Ollama 使用
+## 1. 创建相关文件
+创建一个yaml文件，例如 user_ollama.yaml
+将以下内容粘贴到您的user_ollama.yaml文件当中
+```yaml
+name: 'user_ollama_llm'
+description: 'user ollama llm with spi'
+model_name: 'qwen2:7b'
+max_tokens: 1000
+max_context_length: 32000
+metadata:
+  type: 'LLM'
+  module: 'agentuniverse.llm.default.default_ollama_llm'
+  class: 'OllamaLLM'
+```
+## 2. 环境设置
+### 2.1 通过python代码配置
+必须配置：OLLAMA_BASE_URL
+```python
+import os
+os.environ['OLLAMA_BASE_URL'] = 'https://xxxxxx'
+```
+### 2.2 通过配置文件配置
+在项目的config目录下的custom_key.toml当中，添加配置：
+```toml
+OLLAMA_BASE_URL="https://xxxxxx"
+```
+
+## 3. Tips
+在agentuniverse中，我们已经创建了一个name为default_ollama_llm的llm,用户在配置OLLAMA_BASE_URL之后可以直接使用。
+使用ollama参考官方地址：https://www.ollama.com/library/qwen2
+
diff --git a/docs/guidebook/zh/3_3_1_Milvus.md b/docs/guidebook/zh/3_3_1_Milvus.md
index 0f97daaa..f898f8c5 100644
--- a/docs/guidebook/zh/3_3_1_Milvus.md
+++ b/docs/guidebook/zh/3_3_1_Milvus.md
@@ -20,7 +20,7 @@ pip install pymilvus
 
 ### 我可以用Milvus做些什么
 
-您可以在[Knowledge组件]()中使用Milvus来存储和查询知识，你可以使用以下方式来创建一个使用Milvus的存储组件:
+您可以在[知识组件](2_2_4_知识.md)中使用Milvus来存储和查询知识，你可以使用以下方式来创建一个使用Milvus的存储组件:
 ```python
 from agentuniverse.agent.action.knowledge.store.milvus_store import MilvusStore
 from agentuniverse.agent.action.knowledge.embedding.openai_embedding import OpenAIEmbedding
@@ -38,4 +38,5 @@ init_params['store'] = MilvusStore(
 )
 knowledge = Knowledge(**init_params)
 ```
-上面的代码会创建一个基于Milvus的Knowledge，关于Knowledge的具体用法您可以参考[Knowledge文档]()，或是参考代码`tests/test_agentuniverse/unit/agent/action/knowledge/test_knowledge_with_milvus.py`。
\ No newline at end of file
+
+上面的代码会创建一个基于Milvus的Knowledge，关于Knowledge的具体用法您可以参考[知识组件](2_2_4_知识.md)，或是参考代码`tests/test_agentuniverse/unit/agent/action/knowledge/test_knowledge_with_milvus.py`。
diff --git a/docs/guidebook/zh/3_3_2_ChromaDB.md b/docs/guidebook/zh/3_3_2_ChromaDB.md
new file mode 100644
index 00000000..8ea84f0f
--- /dev/null
+++ b/docs/guidebook/zh/3_3_2_ChromaDB.md
@@ -0,0 +1,24 @@
+## ChromaDB
+
+agentUniverse中已集成ChromaDB相关依赖，您无需额外安装包即可使用ChromaDB的相关功能。
+如果您想学习ChromaDB相关的底层原理，您可以查阅ChromaDB的[官方网站](https://www.trychroma.com/)。
+
+### 我可以用ChromaDB做些什么
+
+
+您可以在[知识组件](2_2_4_知识.md)中使用ChromaDB来存储和查询知识，你可以使用以下方式来创建一个使用ChromaDB的存储组件:
+```python
+from agentuniverse.agent.action.knowledge.embedding.openai_embedding import OpenAIEmbedding
+from agentuniverse.agent.action.knowledge.knowledge import Knowledge
+from agentuniverse.agent.action.knowledge.store.chroma_store import ChromaStore
+
+
+init_params = dict()
+init_params['name'] = 'test_knowledge'
+init_params['description'] = 'test_knowledge_description'
+init_params['store'] = ChromaStore(collection_name="test_knowledge", embedding_model=OpenAIEmbedding(
+    embedding_model_name='text-embedding-ada-002'))
+knowledge = Knowledge(**init_params)
+```
+
+上面的代码会创建一个基于ChromaDB的Knowledge，关于Knowledge的具体用法您可以参考[知识组件](2_2_4_知识.md)，或是参考代码`tests/test_agentuniverse/unit/agent/action/knowledge/test_knowledge.py`。
\ No newline at end of file
diff --git "a/docs/guidebook/zh/6_2_1_\350\256\250\350\256\272\347\273\204.md" "b/docs/guidebook/zh/6_2_1_\350\256\250\350\256\272\347\273\204.md"
new file mode 100644
index 00000000..e974458e
--- /dev/null
+++ "b/docs/guidebook/zh/6_2_1_\350\256\250\350\256\272\347\273\204.md"
@@ -0,0 +1,97 @@
+# 讨论：多智能体讨论组
+示例演示如何使用 agentUniverse 进行多智能体讨论。
+
+共两个智能体角色：讨论组主持人（一名）和讨论组参与者（若干）。
+
+用户发起一个话题，主持人组织各位参与者开始讨论，每轮每个参与者根据讨论话题发表自己的观点（每个参与者的观点并非一成不变，会随着讨论的深入不断调整），几轮讨论后，主持人会对讨论过程进行总结并将参与者们经过几轮讨论后的结果返回给用户。
+
+三个臭皮匠顶个诸葛亮，想象一下你有个想要解答的问题，直接交给agentUniverse讨论组，主持人将具有不同想法的多个智能体组织在一起，对你的问题进行集中讨论，最终给你一个全面且聚集智慧的答案，这是一个有趣的智能体实验。
+
+## 快速开始
+### 配置API密钥
+比如在agentUniverse管理私有密钥配置的文件`custom_key.toml`中配置密钥信息（讨论组默认使用gpt作为基座模型，serper作为google search工具，下文讲述其他模型或工具使用方法）
+```toml
+[KEY_LIST]
+# serper google search key
+SERPER_API_KEY='xxx'
+# openai api key
+OPENAI_API_KEY='xxx'
+```
+
+### 运行讨论组
+在agentUnvierse的`sample_standard_app`示例工程中，找到app/examples目录下的`discussion_chat_bots.py`文件，chat方法中输入想要解答的问题，运行即可。
+
+例如，输入问题甜粽子好吃还是咸粽子好吃
+```python
+from agentuniverse.base.agentuniverse import AgentUniverse
+from agentuniverse.agent.agent import Agent
+from agentuniverse.agent.agent_manager import AgentManager
+
+AgentUniverse().start(config_path='../../config/config.toml')
+
+
+def chat(question: str):
+    instance: Agent = AgentManager().get_instance_obj('host_agent')
+    instance.run(input=question)
+
+
+if __name__ == '__main__':
+    chat("甜粽子好吃还是咸粽子好吃")
+```
+### 效果演示
+甜粽子好吃还是咸粽子好吃：
+
+![演示图片](../_picture/sweet_or_salted_zongzi.png)
+
+中医好还是西医好：
+
+![演示图片](../_picture/chinese_or_western_medicine.png)
+
+## 更多细节
+### 智能体配置
+讨论组多智能体配置文件在`sample_standard_app`示例工程中的app/core/agent/discussion_agent_case目录下。
+
+主持人对应`host_agent.yaml`，参与者对应`participant_agent_*.yaml`。
+
+prompt通过版本号管理，例如host_agent的默认prompt_version为`host_agent.cn`，对应prompt文件为app/core/prompt目录下的`host_agent.cn.yaml`
+
+llm_model若修改为其他模型（如qwen模型），请更改`llm_model` name信息（如aU系统内置的`qwen_llm`）。
+
+agent plan中的round讨论轮数默认为2，用户可以按需调整；默认参与者为aU内置的两个智能体，可以通过建立新的智能体，并配置agent name在`participant`中增加讨论组成员。
+```yaml
+info:
+  name: 'host_agent'
+  description: 'host agent'
+profile:
+  prompt_version: host_agent.cn
+  llm_model:
+    name: 'qwen_llm'
+    temperature: 0.6
+plan:
+  planner:
+    name: 'discussion_planner'
+    round: 2
+    participant:
+      name:
+        - 'participant_agent_one'
+        - 'participant_agent_two'
+memory:
+  name: 'demo_memory'
+metadata:
+  type: 'AGENT'
+  module: 'sample_standard_app.app.core.agent.discussion_agent_case.host_agent'
+  class: 'HostAgent'
+```
+
+### Memory配置
+aU讨论组的参与者默认配置了`sample_standard_app`示例工程中的`demo_memory`，用于存储整个讨论组的公共记忆信息。
+
+### Planner配置
+planner配置文件在`sample_standard_app`示例工程中的app/core/planner目录下，其中`discussion_planner.py`文件为讨论组的具体plan流程代码，感兴趣可自行阅读。
+
+### Prompt配置
+prompt通过版本号管理，aU讨论组智能体默认prompt文件配置在app/core/prompt目录下，对应中英文两种版本（host_agent_xx.yaml/participant_agent_xx.yaml），用户可以在智能体配置中更改prompt_version完成快速切换。
+
+
+### Tool配置
+aU讨论组的两位参与者默认配置了google_search_tool，用户可以更改`sample_standard_app`示例工程中的app/core/agent/discussion_agent_case目录下`participant_agent_xxx.yaml`中的`tool name`，实现工具调用的切换。
diff --git "a/docs/guidebook/zh/7_1_1_Python\350\207\252\345\212\250\346\211\247\350\241\214\346\241\210\344\276\213.md" "b/docs/guidebook/zh/7_1_1_Python\350\207\252\345\212\250\346\211\247\350\241\214\346\241\210\344\276\213.md"
new file mode 100644
index 00000000..729c2773
--- /dev/null
+++ "b/docs/guidebook/zh/7_1_1_Python\350\207\252\345\212\250\346\211\247\350\241\214\346\241\210\344\276\213.md"
@@ -0,0 +1,74 @@
+# Python自动执行案例
+## 案例说明
+本案例基于ReactPlanner，搭建了一个简单可以自动生成python代码并执行的案例。
+
+该案例基于千问大模型和`goolge_search`功能，使用前需要您在环境变量中配置`DASHSCOPE_API_KEY`、`SERPER_API_KEY`。
+
+## 快速开始
+### 配置API密钥
+比如在agentUniverse管理私有密钥配置的文件`custom_key.toml`中配置密钥信息（讨论组默认使用qwen作为基座模型，serper作为google search工具）
+```toml
+[KEY_LIST]
+# serper google search key
+SERPER_API_KEY='xxx'
+# openai api key
+DASHSCOPE_API_KEY='xxx'
+```
+
+### 创建Agent
+```yaml
+info:
+  name: 'demo_react_agent'
+  description: 'react agent'
+profile:
+  prompt_version: qwen_react_agent.cn
+  llm_model:
+    name: 'default_qwen_llm'
+    model_name : 'qwen-max'
+    temperature: 0
+action:
+  tool:
+    - 'google_search_tool'
+    - 'python_runner'
+plan:
+  planner:
+    name: 'react_planner'
+metadata:
+  type: 'AGENT'
+  module: 'agentuniverse.agent.default.react_agent.react_agent'
+  class: 'ReActAgent'
+```
+
+这里使用了google_search_tool与python_runner两个工具，相关工具代码链接如下：
+- [google_search_tool](../../../sample_standard_app/app/core/tool/google_search_tool.yaml)
+- [python_runner](../../../sample_standard_app/app/core/tool/python_repl_tool.yaml)
+
+
+### 代码运行
+1. 测试用例运行
+直接使用测试代码运行[test_case](../../../sample_standard_app/app/test/test_react_agent.py)
+2. 接口运行
+配置好相关key之后，启动web服务，使用下面的curl进行测试
+```shell
+curl --location --request POST 'http://localhost:8888/service_run' \
+--header 'Cookie: spanner=fQ47DxJmWYzf8rKDhs69LExySZYZFUiVXt2T4qEYgj0' \
+--header 'Content-Type: application/json' \
+--data-raw '{
+    
+    "service_id": "demo_react_service",
+    "params": {
+        "input": "请帮我生成一段python代码，可以计算三数之和"
+    }
+}'
+```
+
+### 执行结果
+![test_case](../_picture/react_demo_step.png)
+
+图片中，react一共执行了三步：  
+    第一步，模型根据问题给出了一段python代码，并交给python_runner工具执行，但是执行失败了，失败原因是没有使用print打印执行结果。  
+    第二步，模型意识到错误，主动修改了代码，再次使用python_runner工具执行，执行成功。  
+    第三步，模型将执行成功的代码告诉给用户。  
+
+### 注意
+受限于模型能力问题，建议使用qwen-max模型进行测试
\ No newline at end of file
diff --git "a/docs/guidebook/zh/7_1_1_\346\263\225\345\276\213\345\222\250\350\257\242\346\241\210\344\276\213.md" "b/docs/guidebook/zh/7_1_1_\346\263\225\345\276\213\345\222\250\350\257\242\346\241\210\344\276\213.md"
new file mode 100644
index 00000000..c7d8b7c7
--- /dev/null
+++ "b/docs/guidebook/zh/7_1_1_\346\263\225\345\276\213\345\222\250\350\257\242\346\241\210\344\276\213.md"
@@ -0,0 +1,35 @@
+# 法律咨询案例
+## 案例说明
+本案例基于RagPlanner，搭建了一个简单的法律咨询智能体，通过检索民法典和刑法中的相关条例并结合案件背景给出相关的法律建议。
+
+该案例基于千文大模型和`DashScope`的embedding功能，使用前需要您在环境变量中配置`DASHSCOPE_API_KEY`。
+
+## 构成
+### 法律知识库
+法律知识库基于agentUniverse中的[知识组件](2_2_4_知识.md)，通过将法律条款原文embedding后存储至ChromaDB的向量数据库中，构建方便智能体查阅检索的知识库。  
+法律书籍原本：
+- [民法典.pdf](../../../sample_standard_app/app/resources/民法典.pdf)
+- [刑法.pdf](../../../sample_standard_app/app/resources/刑法.pdf)
+
+具体代码可以参考：
+- [民法典知识库](../../../sample_standard_app/app/core/knowledge/civil_law_knowledge.py)
+- [刑法知识库](../../../sample_standard_app/app/core/knowledge/criminal_law_knowledge.py)
+
+为了方便您使用，我们已经将存储有相关信息的数据库文件放在[该目录下](../../../sample_standard_app/DB/)，如果您想从头构建知识库的话，您可以修改代码中的如下部分：
+```python
+# Initialize the knowledge
+# self.insert_knowledge()
+```
+将`self.insert_knowledge()`前的注释去掉，即可重新构建数据库。
+
+### 法律智能体
+该智能体涉及如下两个文件： 
+- [law_rag_agent.py](../../../sample_standard_app/app/core/agent/rag_agent_case/law_rag_agent.py): 定义了智能体的输入和输出
+- [law_rag_agent.yaml](../../../sample_standard_app/app/core/agent/rag_agent_case/law_rag_agent.yaml): 定义了智能体的相关提示词
+
+
+### 演示代码
+[代码链接](../../../sample_standard_app/app/examples/law_chat_bot.py)
+
+## 效果演示
+![演示图片](../_picture/law_agent_demo.png)
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
index d725b8f9..e29498b8 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "agentUniverse"
-version = "0.0.8"
+version = "0.0.9"
 description = "agentUniverse is a framework for developing applications powered by multi-agent base on large language model."
 
 authors = ["AntGroup <jerry.zzw@antgroup.com>"]
@@ -37,6 +37,7 @@ pydantic = "^2.6.4"
 gunicorn = "^22.0.0"
 grpcio = "1.63.0"
 chromadb = "0.4.24"
+opentelemetry-exporter-otlp-proto-grpc = "^1.25.0"
 sphinx = "^7.2.6"
 Jinja2 = "^3.1.4"
 tqdm = "^4.66.3"
@@ -48,6 +49,8 @@ myst-parser = "^2.0.0"
 qianfan = "^0.3.12"
 dashscope = "^1.19.1"
 anthropic = "^0.26.0"
+ollama = '^0.2.1'
+langchain-anthropic = '^0.1.13'
 
 [tool.poetry.extras]
 log_ext = ["aliyun-log-python-sdk"]
diff --git a/sample_standard_app/DB/civil_law.db/373b58cb-6652-4697-8788-5e639678e409/data_level0.bin b/sample_standard_app/DB/civil_law.db/373b58cb-6652-4697-8788-5e639678e409/data_level0.bin
new file mode 100644
index 00000000..ea3192e8
Binary files /dev/null and b/sample_standard_app/DB/civil_law.db/373b58cb-6652-4697-8788-5e639678e409/data_level0.bin differ
diff --git a/sample_standard_app/DB/civil_law.db/373b58cb-6652-4697-8788-5e639678e409/header.bin b/sample_standard_app/DB/civil_law.db/373b58cb-6652-4697-8788-5e639678e409/header.bin
new file mode 100644
index 00000000..3e0932a7
Binary files /dev/null and b/sample_standard_app/DB/civil_law.db/373b58cb-6652-4697-8788-5e639678e409/header.bin differ
diff --git a/sample_standard_app/DB/civil_law.db/373b58cb-6652-4697-8788-5e639678e409/length.bin b/sample_standard_app/DB/civil_law.db/373b58cb-6652-4697-8788-5e639678e409/length.bin
new file mode 100644
index 00000000..1dc89f8e
Binary files /dev/null and b/sample_standard_app/DB/civil_law.db/373b58cb-6652-4697-8788-5e639678e409/length.bin differ
diff --git a/sample_standard_app/DB/civil_law.db/373b58cb-6652-4697-8788-5e639678e409/link_lists.bin b/sample_standard_app/DB/civil_law.db/373b58cb-6652-4697-8788-5e639678e409/link_lists.bin
new file mode 100644
index 00000000..e69de29b
diff --git a/sample_standard_app/DB/civil_law.db/chroma.sqlite3 b/sample_standard_app/DB/civil_law.db/chroma.sqlite3
new file mode 100644
index 00000000..a107ddd5
Binary files /dev/null and b/sample_standard_app/DB/civil_law.db/chroma.sqlite3 differ
diff --git a/sample_standard_app/DB/criminal_law.db/c93232cd-8eec-4ac4-a4a2-e64315265207/data_level0.bin b/sample_standard_app/DB/criminal_law.db/c93232cd-8eec-4ac4-a4a2-e64315265207/data_level0.bin
new file mode 100644
index 00000000..ea3192e8
Binary files /dev/null and b/sample_standard_app/DB/criminal_law.db/c93232cd-8eec-4ac4-a4a2-e64315265207/data_level0.bin differ
diff --git a/sample_standard_app/DB/criminal_law.db/c93232cd-8eec-4ac4-a4a2-e64315265207/header.bin b/sample_standard_app/DB/criminal_law.db/c93232cd-8eec-4ac4-a4a2-e64315265207/header.bin
new file mode 100644
index 00000000..3e0932a7
Binary files /dev/null and b/sample_standard_app/DB/criminal_law.db/c93232cd-8eec-4ac4-a4a2-e64315265207/header.bin differ
diff --git a/sample_standard_app/DB/criminal_law.db/c93232cd-8eec-4ac4-a4a2-e64315265207/length.bin b/sample_standard_app/DB/criminal_law.db/c93232cd-8eec-4ac4-a4a2-e64315265207/length.bin
new file mode 100644
index 00000000..73385e9b
Binary files /dev/null and b/sample_standard_app/DB/criminal_law.db/c93232cd-8eec-4ac4-a4a2-e64315265207/length.bin differ
diff --git a/sample_standard_app/DB/criminal_law.db/c93232cd-8eec-4ac4-a4a2-e64315265207/link_lists.bin b/sample_standard_app/DB/criminal_law.db/c93232cd-8eec-4ac4-a4a2-e64315265207/link_lists.bin
new file mode 100644
index 00000000..e69de29b
diff --git a/sample_standard_app/DB/criminal_law.db/chroma.sqlite3 b/sample_standard_app/DB/criminal_law.db/chroma.sqlite3
new file mode 100644
index 00000000..37142723
Binary files /dev/null and b/sample_standard_app/DB/criminal_law.db/chroma.sqlite3 differ
diff --git a/sample_standard_app/app/bootstrap/server_application.py b/sample_standard_app/app/bootstrap/server_application.py
index 3f59fb94..cb5cb908 100644
--- a/sample_standard_app/app/bootstrap/server_application.py
+++ b/sample_standard_app/app/bootstrap/server_application.py
@@ -5,6 +5,7 @@
 # @Author  : jerry.zzw 
 # @Email   : jerry.zzw@antgroup.com
 # @FileName: server_application.py
+
 from agentuniverse.agent_serve.web.web_booster import start_web_server
 from agentuniverse.base.agentuniverse import AgentUniverse
 
diff --git a/sample_standard_app/app/core/agent/discussion_agent_case/__init__.py b/sample_standard_app/app/core/agent/discussion_agent_case/__init__.py
new file mode 100644
index 00000000..7ed18ab8
--- /dev/null
+++ b/sample_standard_app/app/core/agent/discussion_agent_case/__init__.py
@@ -0,0 +1,7 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/6/12 10:07
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: __init__.py.py
diff --git a/sample_standard_app/app/core/agent/discussion_agent_case/host_agent.py b/sample_standard_app/app/core/agent/discussion_agent_case/host_agent.py
new file mode 100644
index 00000000..5abf97cd
--- /dev/null
+++ b/sample_standard_app/app/core/agent/discussion_agent_case/host_agent.py
@@ -0,0 +1,44 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/6/6 22:05
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: host_agent.py
+from agentuniverse.agent.agent import Agent
+from agentuniverse.agent.input_object import InputObject
+
+
+class HostAgent(Agent):
+
+    def input_keys(self) -> list[str]:
+        """Return the input keys of the Agent."""
+        return ['input']
+
+    def output_keys(self) -> list[str]:
+        """Return the output keys of the Agent."""
+        return ['output']
+
+    def parse_input(self, input_object: InputObject, agent_input: dict) -> dict:
+        """Agent parameter parsing.
+
+        Args:
+            input_object(InputObject): input parameters passed by the user.
+            agent_input(dict): agent input preparsed by the agent.
+        Returns:
+            dict: agent input parsed from `input_object` by the user.
+        """
+        agent_input['input'] = input_object.get_data('input')
+        agent_input['participants'] = input_object.get_data('participants')
+        agent_input['total_round'] = input_object.get_data('total_round')
+        return agent_input
+
+    def parse_result(self, planner_result: dict) -> dict:
+        """Planner result parser.
+
+        Args:
+            planner_result(dict): Planner result
+        Returns:
+            dict: Agent result object.
+        """
+        return planner_result
diff --git a/sample_standard_app/app/core/agent/discussion_agent_case/host_agent.yaml b/sample_standard_app/app/core/agent/discussion_agent_case/host_agent.yaml
new file mode 100644
index 00000000..50b65aa7
--- /dev/null
+++ b/sample_standard_app/app/core/agent/discussion_agent_case/host_agent.yaml
@@ -0,0 +1,22 @@
+info:
+  name: 'host_agent'
+  description: 'host agent'
+profile:
+  prompt_version: host_agent.cn
+  llm_model:
+    name: 'demo_llm'
+    temperature: 0.6
+plan:
+  planner:
+    name: 'discussion_planner'
+    round: 2
+    participant:
+      name:
+        - 'participant_agent_one'
+        - 'participant_agent_two'
+memory:
+  name: 'demo_memory'
+metadata:
+  type: 'AGENT'
+  module: 'sample_standard_app.app.core.agent.discussion_agent_case.host_agent'
+  class: 'HostAgent'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/agent/discussion_agent_case/participant_agent.py b/sample_standard_app/app/core/agent/discussion_agent_case/participant_agent.py
new file mode 100644
index 00000000..c1f817cc
--- /dev/null
+++ b/sample_standard_app/app/core/agent/discussion_agent_case/participant_agent.py
@@ -0,0 +1,28 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/6/6 22:05
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: participant_agent.py
+from agentuniverse.agent.agent import Agent
+from agentuniverse.agent.input_object import InputObject
+
+
+class ParticipantAgent(Agent):
+    def input_keys(self) -> list[str]:
+        return ['input']
+
+    def output_keys(self) -> list[str]:
+        return ['output']
+
+    def parse_input(self, input_object: InputObject, agent_input: dict) -> dict:
+        agent_input['input'] = input_object.get_data('input')
+        agent_input['agent_name'] = input_object.get_data('agent_name')
+        agent_input['total_round'] = input_object.get_data('total_round')
+        agent_input['cur_round'] = input_object.get_data('cur_round')
+        agent_input['participants'] = input_object.get_data('participants')
+        return agent_input
+
+    def parse_result(self, planner_result: dict) -> dict:
+        return planner_result
diff --git a/sample_standard_app/app/core/agent/discussion_agent_case/participant_agent_one.yaml b/sample_standard_app/app/core/agent/discussion_agent_case/participant_agent_one.yaml
new file mode 100644
index 00000000..fb2b74ba
--- /dev/null
+++ b/sample_standard_app/app/core/agent/discussion_agent_case/participant_agent_one.yaml
@@ -0,0 +1,20 @@
+info:
+  name: 'participant_agent_one'
+  description: 'demo participant agent'
+profile:
+  prompt_version: participant_agent.cn
+  llm_model:
+    name: 'demo_llm'
+    temperature: 0.3
+plan:
+  planner:
+    name: 'rag_planner'
+action:
+  tool:
+    - 'google_search_tool'
+memory:
+  name: 'demo_memory'
+metadata:
+  type: 'AGENT'
+  module: 'sample_standard_app.app.core.agent.discussion_agent_case.participant_agent'
+  class: 'ParticipantAgent'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/agent/discussion_agent_case/participant_agent_two.yaml b/sample_standard_app/app/core/agent/discussion_agent_case/participant_agent_two.yaml
new file mode 100644
index 00000000..f45acdf8
--- /dev/null
+++ b/sample_standard_app/app/core/agent/discussion_agent_case/participant_agent_two.yaml
@@ -0,0 +1,20 @@
+info:
+  name: 'participant_agent_two'
+  description: 'demo participant agent'
+profile:
+  prompt_version: participant_agent.cn
+  llm_model:
+    name: 'demo_llm'
+    temperature: 0.3
+plan:
+  planner:
+    name: 'rag_planner'
+action:
+  tool:
+    - 'google_search_tool'
+memory:
+  name: 'demo_memory'
+metadata:
+  type: 'AGENT'
+  module: 'sample_standard_app.app.core.agent.discussion_agent_case.participant_agent'
+  class: 'ParticipantAgent'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/agent/nl2api_agent_case/__init__.py b/sample_standard_app/app/core/agent/nl2api_agent_case/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/sample_standard_app/app/core/agent/nl2api_agent_case/nl2api_agent.yaml b/sample_standard_app/app/core/agent/nl2api_agent_case/nl2api_agent.yaml
new file mode 100644
index 00000000..2bf6c79d
--- /dev/null
+++ b/sample_standard_app/app/core/agent/nl2api_agent_case/nl2api_agent.yaml
@@ -0,0 +1,20 @@
+info:
+  name: 'demo_nl2api_agent'
+  description: 'demo nl2api agent'
+profile:
+  llm_model:
+    name: 'default_qwen_llm'
+action:
+  tool:
+    - 'add'
+    - 'sub'
+    - 'mul'
+    - 'div'
+    - 'google_search_tool'
+plan:
+  planner:
+    name: 'nl2api_planner'
+metadata:
+  type: 'AGENT'
+  module: 'agentuniverse.agent.default.nl2api_agent.nl2api_agent'
+  class: 'Nl2ApiAgent'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/agent/peer_agent_case/demo_executing_agent.yaml b/sample_standard_app/app/core/agent/peer_agent_case/demo_executing_agent.yaml
index fa2e29f7..91daba1d 100644
--- a/sample_standard_app/app/core/agent/peer_agent_case/demo_executing_agent.yaml
+++ b/sample_standard_app/app/core/agent/peer_agent_case/demo_executing_agent.yaml
@@ -5,7 +5,6 @@ profile:
   prompt_version: demo_executing_agent.cn
   llm_model:
     name: 'demo_llm'
-    model_name: 'gpt-4o'
     temperature: 0.4
 plan:
   planner:
diff --git a/sample_standard_app/app/core/agent/peer_agent_case/demo_expressing_agent.yaml b/sample_standard_app/app/core/agent/peer_agent_case/demo_expressing_agent.yaml
index b5189daf..64ca635d 100644
--- a/sample_standard_app/app/core/agent/peer_agent_case/demo_expressing_agent.yaml
+++ b/sample_standard_app/app/core/agent/peer_agent_case/demo_expressing_agent.yaml
@@ -5,7 +5,6 @@ profile:
   prompt_version: demo_expressing_agent.cn
   llm_model:
     name: demo_llm
-    model_name: gpt-4o
     temperature: 0.2
     prompt_processor:
       type: stuff
diff --git a/sample_standard_app/app/core/agent/peer_agent_case/demo_planning_agent.yaml b/sample_standard_app/app/core/agent/peer_agent_case/demo_planning_agent.yaml
index 278b6fff..b50071da 100644
--- a/sample_standard_app/app/core/agent/peer_agent_case/demo_planning_agent.yaml
+++ b/sample_standard_app/app/core/agent/peer_agent_case/demo_planning_agent.yaml
@@ -5,7 +5,6 @@ profile:
   prompt_version: demo_planning_agent.cn
   llm_model:
     name: 'demo_llm'
-    model_name: 'gpt-4o'
     temperature: 0.5
 plan:
   planner:
diff --git a/sample_standard_app/app/core/agent/peer_agent_case/demo_reviewing_agent.yaml b/sample_standard_app/app/core/agent/peer_agent_case/demo_reviewing_agent.yaml
index 38f45076..b1280a14 100644
--- a/sample_standard_app/app/core/agent/peer_agent_case/demo_reviewing_agent.yaml
+++ b/sample_standard_app/app/core/agent/peer_agent_case/demo_reviewing_agent.yaml
@@ -4,7 +4,6 @@ info:
 profile:
   llm_model:
     name: 'demo_llm'
-    model_name: 'gpt-3.5-turbo-0125'
     temperature: 0.5
 plan:
   planner:
diff --git a/sample_standard_app/app/core/agent/rag_agent_case/demo_rag_agent.yaml b/sample_standard_app/app/core/agent/rag_agent_case/demo_rag_agent.yaml
index 8457d2df..fecdd274 100644
--- a/sample_standard_app/app/core/agent/rag_agent_case/demo_rag_agent.yaml
+++ b/sample_standard_app/app/core/agent/rag_agent_case/demo_rag_agent.yaml
@@ -24,8 +24,8 @@ profile:
 
     需要回答的问题是: {input}
   llm_model:
-    name: 'demo_llm'
-    model_name: 'gpt-4o'
+    name: 'default_qwen_llm'
+#    model_name: 'gpt-4o'
 plan:
   planner:
     name: 'rag_planner'
diff --git a/sample_standard_app/app/core/agent/rag_agent_case/law_rag_agent.py b/sample_standard_app/app/core/agent/rag_agent_case/law_rag_agent.py
new file mode 100644
index 00000000..6726f620
--- /dev/null
+++ b/sample_standard_app/app/core/agent/rag_agent_case/law_rag_agent.py
@@ -0,0 +1,24 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/6/12 19:56
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: law_rag_agent.py
+from agentuniverse.agent.agent import Agent
+from agentuniverse.agent.input_object import InputObject
+
+
+class LawRagAgent(Agent):
+    def input_keys(self) -> list[str]:
+        return ['input']
+
+    def output_keys(self) -> list[str]:
+        return ['output']
+
+    def parse_input(self, input_object: InputObject, agent_input: dict) -> dict:
+        agent_input['input'] = input_object.get_data('input')
+        return agent_input
+
+    def parse_result(self, planner_result: dict) -> dict:
+        return planner_result
diff --git a/sample_standard_app/app/core/agent/rag_agent_case/law_rag_agent.yaml b/sample_standard_app/app/core/agent/rag_agent_case/law_rag_agent.yaml
new file mode 100644
index 00000000..bf917fcd
--- /dev/null
+++ b/sample_standard_app/app/core/agent/rag_agent_case/law_rag_agent.yaml
@@ -0,0 +1,33 @@
+info:
+  name: 'law_rag_agent'
+  description: 'law rag agent'
+profile:
+  introduction: 你是一位精通信息分析的ai法律顾问。
+  target: 你的目标是根据给出的事件，以及提供的背景知识做出客观的司法判断。
+  instruction: |
+    你需要遵守的规则是:
+    1. 必须使用中文结合背景信息做出判决，没有在背景知识中的条例不允许引用。
+    2. 结构化答案生成，必要时通过空行提升阅读体验。
+    3. 多考虑背景知识和场景的关联性。
+    4. 多使用“根据民法典第XX条”“根据刑法第XX条”这种句式开头，但要求事件内容确实和对应条目相关，否则不要提及。
+    5. 如果背景信息和内容无关则不要引用，引用条例时不要再强调“根据背景信息”这一点。
+    
+
+    背景信息是:
+    {background}
+
+    事件是: {input}
+  llm_model:
+    name: 'qwen_llm'
+    model_name: 'qwen-max'
+plan:
+  planner:
+    name: 'rag_planner'
+action:
+  knowledge:
+    - 'civil_law_knowledge'
+    - 'criminal_law_knowledge'
+metadata:
+  type: 'AGENT'
+  module: 'sample_standard_app.app.core.agent.rag_agent_case.law_rag_agent'
+  class: 'LawRagAgent'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/agent/react_agent_case/__init__.py b/sample_standard_app/app/core/agent/react_agent_case/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/sample_standard_app/app/core/agent/react_agent_case/demo_react_agent.yaml b/sample_standard_app/app/core/agent/react_agent_case/demo_react_agent.yaml
new file mode 100644
index 00000000..8a38838d
--- /dev/null
+++ b/sample_standard_app/app/core/agent/react_agent_case/demo_react_agent.yaml
@@ -0,0 +1,19 @@
+info:
+  name: 'demo_react_agent'
+  description: 'react agent'
+profile:
+  prompt_version: qwen_react_agent.cn
+  llm_model:
+    name: 'default_qwen_llm'
+    temperature: 0
+action:
+  tool:
+    - 'google_search_tool'
+    - 'python_runner'
+plan:
+  planner:
+    name: 'react_planner'
+metadata:
+  type: 'AGENT'
+  module: 'agentuniverse.agent.default.react_agent.react_agent'
+  class: 'ReActAgent'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/knowledge/civil_law_knowledge.py b/sample_standard_app/app/core/knowledge/civil_law_knowledge.py
new file mode 100644
index 00000000..fa38fac7
--- /dev/null
+++ b/sample_standard_app/app/core/knowledge/civil_law_knowledge.py
@@ -0,0 +1,44 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/3/28 19:28
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: demo_knowledge.py
+
+from agentuniverse.agent.action.knowledge.embedding.dashscope_embedding import DashscopeEmbedding
+from agentuniverse.agent.action.knowledge.knowledge import Knowledge
+from agentuniverse.agent.action.knowledge.reader.file.pdf_reader import PdfReader
+from agentuniverse.agent.action.knowledge.store.chroma_store import ChromaStore
+from agentuniverse.agent.action.knowledge.store.document import Document
+from langchain.text_splitter import TokenTextSplitter
+from pathlib import Path
+
+SPLITTER = TokenTextSplitter(chunk_size=600, chunk_overlap=100)
+
+
+class CivilLawKnowledge(Knowledge):
+    """The demo knowledge."""
+
+    def __init__(self, **kwargs):
+        super().__init__(**kwargs)
+        self.store = ChromaStore(
+            collection_name="law_store",
+            persist_path="../../DB/civil_law.db",
+            embedding_model=DashscopeEmbedding(
+                embedding_model_name='text-embedding-v2'
+            ),
+            dimensions=1536)
+        self.reader = PdfReader()
+        # Initialize the knowledge
+        # self.insert_knowledge()
+
+    def insert_knowledge(self, **kwargs) -> None:
+        """
+        Load civil law pdf and save into vector database.
+        """
+        civil_law_docs = self.reader.load_data(Path("../resources/民法典.pdf"))
+        lc_doc_list = SPLITTER.split_documents(Document.as_langchain_list(
+            civil_law_docs
+        ))
+        self.store.insert_documents(Document.from_langchain_list(lc_doc_list))
diff --git a/sample_standard_app/app/core/knowledge/civil_law_knowledge.yaml b/sample_standard_app/app/core/knowledge/civil_law_knowledge.yaml
new file mode 100644
index 00000000..86ddd6b0
--- /dev/null
+++ b/sample_standard_app/app/core/knowledge/civil_law_knowledge.yaml
@@ -0,0 +1,6 @@
+name: 'civil_law_knowledge'
+description: 'civil law knowledge'
+metadata:
+  type: 'KNOWLEDGE'
+  module: 'sample_standard_app.app.core.knowledge.civil_law_knowledge'
+  class: 'CivilLawKnowledge'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/knowledge/criminal_law_knowledge.py b/sample_standard_app/app/core/knowledge/criminal_law_knowledge.py
new file mode 100644
index 00000000..124baa83
--- /dev/null
+++ b/sample_standard_app/app/core/knowledge/criminal_law_knowledge.py
@@ -0,0 +1,62 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/3/28 19:28
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: demo_knowledge.py
+
+from agentuniverse.agent.action.knowledge.embedding.dashscope_embedding import DashscopeEmbedding
+from agentuniverse.agent.action.knowledge.knowledge import Knowledge
+from agentuniverse.agent.action.knowledge.reader.file.pdf_reader import PdfReader
+from agentuniverse.agent.action.knowledge.store.chroma_store import ChromaStore
+from agentuniverse.agent.action.knowledge.store.document import Document
+from langchain.text_splitter import TokenTextSplitter
+from pathlib import Path
+
+SPLITTER = TokenTextSplitter(chunk_size=600, chunk_overlap=100)
+
+
+class CriminalLawKnowledge(Knowledge):
+    """The demo knowledge."""
+
+    def __init__(self, **kwargs):
+        """The __init__ method.
+
+        Some parameters, such as name and description,
+        are injected into this class by the demo_knowledge.yaml configuration.
+
+
+        Args:
+            name (str): Name of the knowledge.
+
+            description (str): Description of the knowledge.
+
+            store (Store): Store of the knowledge, store class is used to store knowledge
+            and provide retrieval capabilities, such as ChromaDB store or Redis Store,
+            demo knowledge uses ChromaDB as the knowledge storage.
+
+            reader (Reader): Reader is used to load data,
+            the demo knowledge uses WebPdfReader to load pdf files from web.
+        """
+        super().__init__(**kwargs)
+        self.store = ChromaStore(
+            collection_name="law_store",
+            persist_path="../../DB/criminal_law.db",
+            embedding_model=DashscopeEmbedding(
+                embedding_model_name='text-embedding-v2'
+            ),
+            dimensions=1536)
+        self.reader = PdfReader()
+        # Initialize the knowledge
+        # self.insert_knowledge()
+
+    def insert_knowledge(self, **kwargs) -> None:
+        """
+        Load criminal law pdf and save into vector database.
+        """
+        criminal_law_docs = self.reader.load_data(Path("../resources/刑法.pdf"))
+        lc_doc_list = SPLITTER.split_documents(Document.as_langchain_list(
+            criminal_law_docs
+        ))
+        self.store.insert_documents(Document.from_langchain_list(lc_doc_list))
diff --git a/sample_standard_app/app/core/knowledge/criminal_law_knowledge.yaml b/sample_standard_app/app/core/knowledge/criminal_law_knowledge.yaml
new file mode 100644
index 00000000..5a1b2a8c
--- /dev/null
+++ b/sample_standard_app/app/core/knowledge/criminal_law_knowledge.yaml
@@ -0,0 +1,6 @@
+name: 'criminal_law_knowledge'
+description: 'criminal law knowledge'
+metadata:
+  type: 'KNOWLEDGE'
+  module: 'sample_standard_app.app.core.knowledge.criminal_law_knowledge'
+  class: 'CriminalLawKnowledge'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/llm/demo_llm.yaml b/sample_standard_app/app/core/llm/demo_llm.yaml
index 919ccb1f..48aa12bd 100644
--- a/sample_standard_app/app/core/llm/demo_llm.yaml
+++ b/sample_standard_app/app/core/llm/demo_llm.yaml
@@ -1,6 +1,6 @@
 name: 'demo_llm'
 description: 'demo openai'
-model_name: 'gpt-3.5-turbo'
+model_name: 'gpt-4o'
 max_tokens: 1000
 max_retries: 2
 metadata:
diff --git a/sample_standard_app/app/core/llm/qwen_llm.yaml b/sample_standard_app/app/core/llm/qwen_llm.yaml
index 4d2e7a88..1115947c 100644
--- a/sample_standard_app/app/core/llm/qwen_llm.yaml
+++ b/sample_standard_app/app/core/llm/qwen_llm.yaml
@@ -1,7 +1,7 @@
 name: 'qwen_llm'
 description: 'demo qwen llm with spi'
-model_name: 'qwen-turbo'
-max_tokens: 1000
+model_name: 'qwen-max'
+max_tokens: 2000
 metadata:
   type: 'LLM'
   module: 'agentuniverse.llm.default.qwen_openai_style_llm'
diff --git a/sample_standard_app/app/core/memory/demo_memory.py b/sample_standard_app/app/core/memory/demo_memory.py
new file mode 100644
index 00000000..1a893132
--- /dev/null
+++ b/sample_standard_app/app/core/memory/demo_memory.py
@@ -0,0 +1,25 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/6/11 18:23
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: demo_memory.py
+from agentuniverse.agent.memory.chat_memory import ChatMemory
+from agentuniverse.llm.default.qwen_openai_style_llm import QWenOpenAIStyleLLM
+
+
+class DemoMemory(ChatMemory):
+    """The aU demo memory module."""
+
+    def __init__(self, **kwargs):
+        """The __init__ method.
+
+        Some parameters, such as name/description/type/memory_key,
+        are injected into this class by the demo.yaml configuration.
+
+
+        Args:
+            llm (LLM): the LLM instance used by this memory.
+        """
+        super().__init__(**kwargs)
diff --git a/sample_standard_app/app/core/memory/demo_memory.yaml b/sample_standard_app/app/core/memory/demo_memory.yaml
new file mode 100644
index 00000000..6d83359d
--- /dev/null
+++ b/sample_standard_app/app/core/memory/demo_memory.yaml
@@ -0,0 +1,12 @@
+name: 'demo_memory'
+description: 'demo memory with spi'
+type: 'long_term'
+memory_key: 'chat_history'
+input_key: 'input'
+output_key: 'output'
+max_tokens: 1000
+prompt_version: 'chat_memory.summarizer_cn'
+metadata:
+  type: 'MEMORY'
+  module: 'sample_standard_app.app.core.memory.demo_memory'
+  class: 'DemoMemory'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/planner/discussion_planner.py b/sample_standard_app/app/core/planner/discussion_planner.py
new file mode 100644
index 00000000..e4518923
--- /dev/null
+++ b/sample_standard_app/app/core/planner/discussion_planner.py
@@ -0,0 +1,172 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/6/7 10:47
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: discussion_planner.py
+import asyncio
+
+from langchain_core.chat_history import InMemoryChatMessageHistory
+from langchain_core.output_parsers import StrOutputParser
+from langchain_core.runnables.history import RunnableWithMessageHistory
+
+from agentuniverse.agent.agent_manager import AgentManager
+from agentuniverse.agent.agent_model import AgentModel
+from agentuniverse.agent.input_object import InputObject
+from agentuniverse.agent.memory.chat_memory import ChatMemory
+from agentuniverse.agent.output_object import OutputObject
+from agentuniverse.agent.plan.planner.planner import Planner
+from agentuniverse.base.util.logging.logging_util import LOGGER
+from agentuniverse.base.util.memory_util import generate_memories
+from agentuniverse.base.util.prompt_util import process_llm_token
+from agentuniverse.llm.llm import LLM
+from agentuniverse.prompt.chat_prompt import ChatPrompt
+from agentuniverse.prompt.prompt import Prompt
+from agentuniverse.prompt.prompt_manager import PromptManager
+from agentuniverse.prompt.prompt_model import AgentPromptModel
+
+default_round = 2
+
+
+class DiscussionPlanner(Planner):
+    """Discussion planner class."""
+
+    def invoke(self, agent_model: AgentModel, planner_input: dict, input_object: InputObject) -> dict:
+        """Invoke the planner.
+
+        Args:
+            agent_model (AgentModel): Agent model object.
+            planner_input (dict): Planner input object.
+            input_object (InputObject): The input parameters passed by the user.
+        Returns:
+            dict: The planner result.
+        """
+        planner_config = agent_model.plan.get('planner')
+        # generate participant agents
+        participant_agents = self.generate_participant_agents(planner_config)
+        # invoke agents
+        return self.agents_run(participant_agents, planner_config, agent_model, planner_input)
+
+    @staticmethod
+    def generate_participant_agents(planner_config: dict) -> dict:
+        """Generate participant agents."""
+        participant = planner_config.get('participant', {})
+        participant_names = participant.get('name', [])
+        if len(participant_names) == 0:
+            raise NotImplementedError
+        agents = dict()
+        for participant_name in participant_names:
+            agents[participant_name] = AgentManager().get_instance_obj(participant_name)
+        return agents
+
+    def agents_run(self, participant_agents: dict, planner_config: dict, agent_model: AgentModel,
+                   agent_input: dict) -> dict:
+        """ Invoke the participant agents and host agent.
+
+        Args:
+            participant_agents (dict): Participant agents.
+            planner_config (dict): Planner config.
+            agent_model (AgentModel): Agent model object.
+            agent_input (dict): Agent input object.
+        Returns:
+            dict: The planner result.
+        """
+        total_round: int = planner_config.get('round', default_round)
+        chat_history = []
+        LOGGER.info(f"The topic of discussion is {agent_input.get(self.input_key)}")
+        LOGGER.info(f"The participant agents are {'|'.join(participant_agents.keys())}")
+        agent_input['total_round'] = total_round
+        agent_input['participants'] = ' and '.join(participant_agents.keys())
+        for i in range(total_round):
+            LOGGER.info("------------------------------------------------------------------")
+            LOGGER.info(f"Start a discussion, round is {i + 1}.")
+            for agent_name, agent in participant_agents.items():
+                LOGGER.info("------------------------------------------------------------------")
+                LOGGER.info(f"Start speaking: agent is {agent_name}.")
+                LOGGER.info("------------------------------------------------------------------")
+                # invoke participant agent
+                agent_input['agent_name'] = agent_name
+                agent_input['cur_round'] = i + 1
+                output_object: OutputObject = agent.run(**agent_input)
+                current_output = output_object.get_data('output', '')
+
+                # process chat history
+                chat_history.append({'content': agent_input.get('input'), 'type': 'human'})
+                chat_history.append(
+                    {'content': f'the round {i + 1} agent {agent_name} thought: {current_output}', 'type': 'ai'})
+                agent_input['chat_history'] = chat_history
+
+                LOGGER.info(f"the round {i + 1} agent {agent_name} thought: {output_object.get_data('output', '')}")
+
+        agent_input['chat_history'] = chat_history
+        # finally invoke host agent
+        return self.invoke_host_agent(agent_model, agent_input)
+
+    def invoke_host_agent(self, agent_model: AgentModel, planner_input: dict) -> dict:
+        """ Invoke the host agent.
+
+        Args:
+            agent_model (AgentModel): Agent model object.
+            planner_input (dict): Planner input object.
+        Returns:
+            dict: The planner result.
+        """
+        LOGGER.info("------------------------------------------------------------------")
+        LOGGER.info(f"Discussion end.")
+        LOGGER.info(f"Host agent starts summarize the discussion.")
+        LOGGER.info("------------------------------------------------------------------")
+        memory: ChatMemory = self.handle_memory(agent_model, planner_input)
+
+        llm: LLM = self.handle_llm(agent_model)
+
+        prompt: ChatPrompt = self.handle_prompt(agent_model, planner_input)
+        process_llm_token(llm, prompt.as_langchain(), agent_model.profile, planner_input)
+
+        chat_history = memory.as_langchain().chat_memory if memory else InMemoryChatMessageHistory()
+
+        chain_with_history = RunnableWithMessageHistory(
+            prompt.as_langchain() | llm.as_langchain(),
+            lambda session_id: chat_history,
+            history_messages_key="chat_history",
+            input_messages_key=self.input_key,
+        ) | StrOutputParser()
+        res = asyncio.run(
+            chain_with_history.ainvoke(input=planner_input, config={"configurable": {"session_id": "unused"}}))
+        LOGGER.info(f"Discussion summary is: {res}")
+        return {**planner_input, self.output_key: res, 'chat_history': generate_memories(chat_history)}
+
+    def handle_prompt(self, agent_model: AgentModel, planner_input: dict) -> ChatPrompt:
+        """Prompt module processing.
+
+        Args:
+            agent_model (AgentModel): Agent model object.
+            planner_input (dict): Planner input object.
+        Returns:
+            ChatPrompt: The chat prompt instance.
+        """
+        profile: dict = agent_model.profile
+
+        profile_prompt_model: AgentPromptModel = AgentPromptModel(introduction=profile.get('introduction'),
+                                                                  target=profile.get('target'),
+                                                                  instruction=profile.get('instruction'))
+
+        # get the prompt by the prompt version
+        prompt_version: str = profile.get('prompt_version')
+        version_prompt: Prompt = PromptManager().get_instance_obj(prompt_version)
+
+        if version_prompt is None and not profile_prompt_model:
+            raise Exception("Either the `prompt_version` or `introduction & target & instruction`"
+                            " in agent profile configuration should be provided.")
+        if version_prompt:
+            version_prompt_model: AgentPromptModel = AgentPromptModel(
+                introduction=getattr(version_prompt, 'introduction', ''),
+                target=getattr(version_prompt, 'target', ''),
+                instruction=getattr(version_prompt, 'instruction', ''))
+            profile_prompt_model = profile_prompt_model + version_prompt_model
+
+        chat_prompt = ChatPrompt().build_prompt(profile_prompt_model, self.prompt_assemble_order)
+        image_urls: list = planner_input.pop('image_urls', []) or []
+        if image_urls:
+            chat_prompt.generate_image_prompt(image_urls)
+        return chat_prompt
diff --git a/sample_standard_app/app/core/planner/discussion_planner.yaml b/sample_standard_app/app/core/planner/discussion_planner.yaml
new file mode 100644
index 00000000..319e59e4
--- /dev/null
+++ b/sample_standard_app/app/core/planner/discussion_planner.yaml
@@ -0,0 +1,6 @@
+name: 'discussion_planner'
+description: 'discussion_planner'
+metadata:
+  type: 'PLANNER'
+  module: 'sample_standard_app.app.core.planner.discussion_planner'
+  class: 'DiscussionPlanner'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/prompt/demo_react_prompt.yaml b/sample_standard_app/app/core/prompt/demo_react_prompt.yaml
new file mode 100644
index 00000000..4282da89
--- /dev/null
+++ b/sample_standard_app/app/core/prompt/demo_react_prompt.yaml
@@ -0,0 +1,40 @@
+introduction: 你是一个精通工具使用的AI助手。
+target: 你的目标是根据用户的问题以及给出的背景信息，使用工具回答用户的问题。尤其擅长使用搜索或者使用执行python代码解决问题
+instruction: |
+  你必须优先选择使用提供的工具回答用户提出的问题，若用户没有提供工具可以根据你的通识能力解决问题。
+  你在回答时问题必须使用中文回答。
+  你必须从多个角度、维度分析用户的问题，帮助用户获取最全面的信息，需要根据背景和问题，决定搜索哪些信息可以回答问题。 
+  你必须把大问题拆解为多个小问题，并规划解决步骤。
+  
+  您可以使用以下工具:
+  {tools}
+  
+  你的回答必须严格使用以下格式:
+  
+    Question: 您必须回答的问题
+    Thought: 我这一步应该做什么，为什么要这么做，我现在要使用一个工具, 不允许回答Final Answer
+    Action: 要使用的工具应该，值必须是 [{tool_names}] 之一
+    Action Input: 工具的输入
+    Observation: 工具的执行结果
+    ... (Thought/Action/Action Input/Observation 的过程可以重复 N 次)
+    Thought: 我现在知道所有问题的最终答案了
+    Final Answer: 所有问题的最终答案
+  
+  之前的对话:
+  {chat_history}
+  
+  背景信息是:
+  {background}
+  
+  开始！
+    注意：
+      1.你的回答必须是（Thought/Action/Observation）与（Thought/Final Answer）两种格式之一
+      2.你现在必须根据上一步Observation的结果（成功、失败、报错，信息不完整），判断下一步要执行的动作
+  
+  Question: {input}
+  Thought: {agent_scratchpad}
+  
+
+metadata:
+  type: 'PROMPT'
+  version: 'qwen_react_agent.cn'
diff --git a/sample_standard_app/app/core/prompt/host_agent_cn.yaml b/sample_standard_app/app/core/prompt/host_agent_cn.yaml
new file mode 100644
index 00000000..e8d01aac
--- /dev/null
+++ b/sample_standard_app/app/core/prompt/host_agent_cn.yaml
@@ -0,0 +1,21 @@
+introduction: 你是一位精通信息分析的问答助手。
+target: 人类给你一个问题，你的目标是根据几个讨论组里参与者多轮讨论的结果，给人类一个准确的答案。
+instruction: |
+  你需要遵守的规则是:
+  1. 回答用户问题前需要先详细总结下讨论组里参与者多轮讨论的结果。
+  2. 肯定每个人在讨论组中参与的多轮讨论工作。
+  3. 根据几个讨论组里参与者多轮讨论的结果，回答用户提出的问题，要求尽量详细，有理有据。
+
+  今天的日期是: {date}
+
+  讨论组中参与者多轮讨论的对话结果是:
+  {chat_history}
+
+  开始!
+  
+  一共{total_round}轮讨论，讨论组的参与者包括: {participants}.
+
+  请用中文回答，需要回答的问题是: {input}
+metadata:
+  type: 'PROMPT'
+  version: host_agent.cn
diff --git a/sample_standard_app/app/core/prompt/host_agent_en.yaml b/sample_standard_app/app/core/prompt/host_agent_en.yaml
new file mode 100644
index 00000000..16beaaf9
--- /dev/null
+++ b/sample_standard_app/app/core/prompt/host_agent_en.yaml
@@ -0,0 +1,21 @@
+introduction: You are a Q&A assistant proficient in information analysis.
+target: Human gives you a question, and your goal is to give human an accurate answer based on the results of multiple rounds of discussion among the participants in the discussion group.
+instruction: |
+  The rules you need to follow are:
+  1. Before answering the user's questions, you need to briefly summarize in detail the results of several rounds of discussions among the participants in the discussion group.
+  2. Briefly summarize the multi-round discussion process of each participant in the discussion group.
+  3. Based on the multi-round discussion results from the discussion group, answer the questions posed by users as thoroughly and substantiated as possible.
+
+  Today's date is: {date}
+
+  The dialogue results from the participants' multi-round discussions in the discussion group are:
+  {chat_history}
+
+  Begin!
+  
+  There are totally {total_round} rounds of discussion, participants in the discussion group include: {participants}.
+
+  Please answer in English, the question to be answered is: {input}
+metadata:
+  type: 'PROMPT'
+  version: host_agent.en
diff --git a/sample_standard_app/app/core/prompt/participant_agent_cn.yaml b/sample_standard_app/app/core/prompt/participant_agent_cn.yaml
new file mode 100644
index 00000000..39774c99
--- /dev/null
+++ b/sample_standard_app/app/core/prompt/participant_agent_cn.yaml
@@ -0,0 +1,29 @@
+introduction: 你是一位精通信息分析的问答助手。
+target: 人类给你一个问题，你的目标是和另外几个讨论的参与者共同讨论，最后结合多轮的讨论对话结果，给人类一个准确的答案。
+instruction: |
+  你需要遵守的规则是:
+  1. 回答用户问题时不需要对查询到的背景信息进行总结。
+  2. 如果有讨论组中参与者多轮讨论的对话结果时：在提出自己的观点前，先对上一个讨论参与者提出的讨论观点，表达自己的看法，是否赞同或反对，需要给出详细的理由，但不必重新复述上一个讨论参与者提出的观点是什么，简单提及即可。
+  3. 如果有讨论组中参与者多轮讨论的对话结果时：你作为讨论组中的参与者，不要和之前多轮讨论的结果一摸一样，如果有相同的观点，则对前几轮的观点进行其他方面、维度的补充，如果有不同的观点，给出自己观点的详细理由。
+  4. 每一轮你都需要发言一次，尽量坚持自己多轮一直持有的观点，如果发现其他讨论参与者说的更有道理，也可以改变自己最开始的观点。
+  5. 最后一轮的时候，根据讨论组参与者多轮讨论的对话结果，以及自己多轮发表的观点，回答用户提出的问题，要求尽量详细，有理有据。
+
+  背景信息是:
+  {background}
+  
+  今天的日期是: {date}
+
+  讨论组中参与者多轮讨论的对话结果是:
+  {chat_history}
+  
+  开始!
+  
+  你是讨论组参与者，你的名字是:{agent_name}，讨论参与者包括:{participants}
+  
+  一共{total_round}轮讨论，当前是第{cur_round}轮讨论。
+  
+
+  请用中文回答，需要回答的问题是: {input}
+metadata:
+  type: 'PROMPT'
+  version: participant_agent.cn
diff --git a/sample_standard_app/app/core/prompt/participant_agent_en.yaml b/sample_standard_app/app/core/prompt/participant_agent_en.yaml
new file mode 100644
index 00000000..aa39313e
--- /dev/null
+++ b/sample_standard_app/app/core/prompt/participant_agent_en.yaml
@@ -0,0 +1,30 @@
+introduction: You are a Q&A assistant proficient in information analysis.
+target: Human gives you a question, and your goal is to discuss with several other participants in the discussion, and finally, combined with the results of many rounds of discussion, to give human an accurate answer.
+instruction: |
+  The rules you need to follow are:
+  1. There is no need to summarize the background information when answering users' questions.
+  2. If there is a dialogue result of multiple rounds of discussion among the participants in the discussion group: 
+  Before putting forward your own point of view, you need to give detailed reasons for expressing your views on the discussion put forward by the participants in the previous discussion, whether you agree or disagree, but it is not necessary to repeat what the participants in the previous discussion put forward. Simply mention it.
+  3. If there is a dialogue result of multiple rounds of discussion among the participants in the discussion group: 
+  As a participant in the discussion group, you should not feel the same as the results of previous rounds of discussions. if you have the same point of view, supplement the views of the previous rounds in other aspects and dimensions, and if you have different views, give detailed reasons for your own point of view.
+  4. You need to speak once in each round, try to stick to the views you have held for many rounds, and if you find that what other discussion participants have said is more reasonable, you can also change your original point of view.
+  5. In the last round, according to the dialogue results of many rounds of discussion among the participants in the discussion group, as well as your own views expressed in many rounds, answer the questions raised by the users and ask them to be as detailed and justified as possible.。
+
+  Background is:
+  {background}
+  
+  Today's date is: {date}
+
+  The dialogue results from the participants' multi-round discussions in the discussion group are:
+  {chat_history}
+
+  Begin!
+
+  You are the participant of this discussion group, your name is : {agent_name}, participants in the discussion group include: {participants}.
+  
+  There are totally {total_round} rounds of discussion, and this is currently the {cur_round} round of discussions.
+  
+  Please answer in English, the question to be answered is: {input}
+metadata:
+  type: 'PROMPT'
+  version: participant_agent.en
diff --git a/sample_standard_app/app/core/service/demo_react_service.yaml b/sample_standard_app/app/core/service/demo_react_service.yaml
new file mode 100644
index 00000000..a8718c13
--- /dev/null
+++ b/sample_standard_app/app/core/service/demo_react_service.yaml
@@ -0,0 +1,5 @@
+name: 'demo_react_service'
+description: 'demo react service of demo agent'
+agent: 'demo_react_agent'
+metadata:
+  type: 'SERVICE'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/service/law_service.yaml b/sample_standard_app/app/core/service/law_service.yaml
new file mode 100644
index 00000000..aaf6fe9c
--- /dev/null
+++ b/sample_standard_app/app/core/service/law_service.yaml
@@ -0,0 +1,5 @@
+name: 'law_service'
+description: 'law service of law agent'
+agent: 'law_rag_agent'
+metadata:
+  type: 'SERVICE'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/tool/add_simple_tool.yaml b/sample_standard_app/app/core/tool/add_simple_tool.yaml
new file mode 100644
index 00000000..d5dda037
--- /dev/null
+++ b/sample_standard_app/app/core/tool/add_simple_tool.yaml
@@ -0,0 +1,8 @@
+name: 'add'
+description: 'Adding two float number, input_params with 2 num spilt with comma, return result. For example, input_params = 1, 2 , the result = 3'
+tool_type: 'api'
+input_keys: ['input']
+metadata:
+  type: 'TOOL'
+  module: 'sample_standard_app.app.core.tool.simple_math_tool'
+  class: 'AddTool'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/tool/bing_search_tool.py b/sample_standard_app/app/core/tool/bing_search_tool.py
new file mode 100644
index 00000000..f269c59b
--- /dev/null
+++ b/sample_standard_app/app/core/tool/bing_search_tool.py
@@ -0,0 +1,34 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/6/12 10:45
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: bing_search_tool.py
+from typing import Optional
+
+from pydantic import Field
+from langchain_community.utilities import BingSearchAPIWrapper
+from agentuniverse.agent.action.tool.tool import Tool, ToolInput
+from agentuniverse.base.util.env_util import get_from_env
+
+from sample_standard_app.app.core.tool.mock_search_tool import MockSearchTool
+
+
+class BingSearchTool(Tool):
+    """The demo bing search tool.
+
+    Implement the execute method of demo bing search tool, using the `BingSearchAPIWrapper` to implement a simple Bing search.
+    """
+
+    bing_subscription_key: Optional[str] = Field(default_factory=lambda: get_from_env("BING_SUBSCRIPTION_KEY"))
+    bing_search_url: Optional[str] = Field(default='https://api.bing.microsoft.com/v7.0/search')
+
+    def execute(self, tool_input: ToolInput):
+        if self.bing_subscription_key is None:
+            return MockSearchTool().execute(tool_input)
+        query = tool_input.get_data("input")
+        # get top5 results from Bing search.
+        search = BingSearchAPIWrapper(bing_subscription_key=self.bing_subscription_key, k=5,
+                                      bing_search_url=self.bing_search_url)
+        return search.run(query=query)
diff --git a/sample_standard_app/app/core/tool/bing_search_tool.yaml b/sample_standard_app/app/core/tool/bing_search_tool.yaml
new file mode 100644
index 00000000..afdc1f05
--- /dev/null
+++ b/sample_standard_app/app/core/tool/bing_search_tool.yaml
@@ -0,0 +1,8 @@
+name: 'bing_search_tool'
+description: 'demo bing search tool'
+tool_type: 'api'
+input_keys: ['input']
+metadata:
+  type: 'TOOL'
+  module: 'sample_standard_app.app.core.tool.bing_search_tool'
+  class: 'BingSearchTool'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/tool/div_simple_tool.yaml b/sample_standard_app/app/core/tool/div_simple_tool.yaml
new file mode 100644
index 00000000..eea3425d
--- /dev/null
+++ b/sample_standard_app/app/core/tool/div_simple_tool.yaml
@@ -0,0 +1,8 @@
+name: 'div'
+description: 'Dividing two float number, input_params with 2 num spilt with comma, return result. For example, input_params = 6, 3 , the result = 2'
+tool_type: 'api'
+input_keys: ['input']
+metadata:
+  type: 'TOOL'
+  module: 'sample_standard_app.app.core.tool.simple_math_tool'
+  class: 'MultiplyTool'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/tool/google_search_tool.py b/sample_standard_app/app/core/tool/google_search_tool.py
index 50b14d7e..22da460a 100644
--- a/sample_standard_app/app/core/tool/google_search_tool.py
+++ b/sample_standard_app/app/core/tool/google_search_tool.py
@@ -9,6 +9,7 @@
 from pydantic import Field
 from langchain_community.utilities.google_serper import GoogleSerperAPIWrapper
 from agentuniverse.agent.action.tool.tool import Tool, ToolInput
+from agentuniverse.base.config.component_configer.configers.tool_configer import ToolConfiger
 from agentuniverse.base.util.env_util import get_from_env
 
 from sample_standard_app.app.core.tool.mock_search_tool import MockSearchTool
@@ -26,9 +27,9 @@ class GoogleSearchTool(Tool):
     serper_api_key: Optional[str] = Field(default_factory=lambda: get_from_env("SERPER_API_KEY"))
 
     def execute(self, tool_input: ToolInput):
+        input = tool_input.get_data("input")
         if self.serper_api_key is None:
-            return MockSearchTool().execute(tool_input)
-        query = tool_input.get_data("input")
+            return MockSearchTool().execute(tool_input=tool_input)
         # get top10 results from Google search.
         search = GoogleSerperAPIWrapper(serper_api_key=self.serper_api_key, k=10, gl="us", hl="en", type="search")
-        return search.run(query=query)
+        return search.run(query=input)
\ No newline at end of file
diff --git a/sample_standard_app/app/core/tool/google_search_tool.yaml b/sample_standard_app/app/core/tool/google_search_tool.yaml
index 93ca5659..c8ed4af3 100644
--- a/sample_standard_app/app/core/tool/google_search_tool.yaml
+++ b/sample_standard_app/app/core/tool/google_search_tool.yaml
@@ -1,5 +1,9 @@
 name: 'google_search_tool'
-description: 'demo google search tool'
+description: |
+  该工具可以用来进行谷歌搜索，工具的输入是你想搜索的内容。
+  工具输入示例：
+    示例1: 你想要搜索上海的天气时，工具的输入应该是：上海今天的天气
+    示例2: 你想要搜索日本的天气时，工具的输入应该是：日本的天气
 tool_type: 'api'
 input_keys: ['input']
 metadata:
diff --git a/sample_standard_app/app/core/tool/mock_search_tool.py b/sample_standard_app/app/core/tool/mock_search_tool.py
index ebd78516..f0b85660 100644
--- a/sample_standard_app/app/core/tool/mock_search_tool.py
+++ b/sample_standard_app/app/core/tool/mock_search_tool.py
@@ -41,5 +41,6 @@ class MockSearchTool(Tool):
     """
 
     def execute(self, tool_input: ToolInput):
+        input = tool_input.get_data("input")
         """Demonstrates the execute method of the Tool class."""
         return MOCK_SEARCH_RESULT
diff --git a/sample_standard_app/app/core/tool/mul_simple_tool.yaml b/sample_standard_app/app/core/tool/mul_simple_tool.yaml
new file mode 100644
index 00000000..ca5e95c7
--- /dev/null
+++ b/sample_standard_app/app/core/tool/mul_simple_tool.yaml
@@ -0,0 +1,8 @@
+name: 'mul'
+description: 'Multiplying two float number, input_params with 2 num spilt with comma, return result. For example, a = 2, 1 , the result = 2'
+tool_type: 'api'
+input_keys: ['input']
+metadata:
+  type: 'TOOL'
+  module: 'sample_standard_app.app.core.tool.simple_math_tool'
+  class: 'MultiplyTool'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/tool/python_repl.py b/sample_standard_app/app/core/tool/python_repl.py
new file mode 100644
index 00000000..04af11c1
--- /dev/null
+++ b/sample_standard_app/app/core/tool/python_repl.py
@@ -0,0 +1,41 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/6/12 16:36
+# @Author  : weizjajj 
+# @Email   : weizhongjie.wzj@antgroup.com
+# @FileName: python_repl.py
+
+import re
+
+from langchain_community.utilities import PythonREPL
+from pydantic import Field
+from agentuniverse.agent.action.tool.tool import Tool, ToolInput
+
+
+class PythonREPLTool(Tool):
+    """The mock search tool.
+
+    In this tool, we mocked the search engine's answers to search for information about BYD and Warren Buffett.
+
+    Note:
+        The tool is only suitable for users searching for Buffett or BYD related queries.
+        We recommend that you configure your `SERPER_API_KEY` and use google_search_tool to get information.
+    """
+    client: PythonREPL = Field(default_factory=lambda: PythonREPL())
+
+    def execute(self, tool_input: ToolInput):
+        input = tool_input.get_data("input")
+        """Demonstrates the execute method of the Tool class."""
+        pattern = re.compile(r"```python(.*?)``", re.DOTALL)
+        matches = pattern.findall(input)
+        if len(matches) == 0:
+            pattern = re.compile(r"```py(.*?)``", re.DOTALL)
+            matches = pattern.findall(input)
+        if len(matches) == 0:
+            return self.client.run(input)
+        res = self.client.run(matches[0])
+        if res == "" or res is None:
+            return "ERROR: 你的python代码中没有使用print输出任何内容，请参考工具示例"
+        else:
+            return res
diff --git a/sample_standard_app/app/core/tool/python_repl_tool.yaml b/sample_standard_app/app/core/tool/python_repl_tool.yaml
new file mode 100644
index 00000000..5ec69b46
--- /dev/null
+++ b/sample_standard_app/app/core/tool/python_repl_tool.yaml
@@ -0,0 +1,19 @@
+name: 'python_runner'
+description: '使用该工具可以执行python代码，可以在pycharm中直接运行的代码.工具的输入必须时一段有效的python代码. 如何你想要查看工具的执行结果, 必须在python代码中使用print(...)打印你想查看的内容。
+    工具输入示例：
+      你想要计算1+3等于多少时，工具的输入应该是：
+        ```py 
+        print(1+3)
+        ```
+      你想要获取百度页面的信息时，工具的输入应该是: 
+        ```py 
+        import requests
+        resp=requests.get("https://www.baidu.com")
+        print(resp.content)
+        ```'
+tool_type: 'api'
+input_keys: ['input']
+metadata:
+  type: 'TOOL'
+  module: 'sample_standard_app.app.core.tool.python_repl'
+  class: 'PythonREPLTool'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/tool/search_api_baidu_tool.yaml b/sample_standard_app/app/core/tool/search_api_baidu_tool.yaml
new file mode 100644
index 00000000..ed1c4e84
--- /dev/null
+++ b/sample_standard_app/app/core/tool/search_api_baidu_tool.yaml
@@ -0,0 +1,12 @@
+name: 'search_api_baidu_tool'
+description: '百度(必应)搜索工具，输入为一个要搜索内容的字符串，例如：input=黄金价格是多少'
+tool_type: 'api'
+input_keys: ['input']
+engine: 'baidu'
+search_type: 'json'
+search_params:
+  num: 10
+metadata:
+  type: 'TOOL'
+  module: 'sample_standard_app.app.core.tool.search_api_tool'
+  class: 'SearchAPITool'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/tool/search_api_bing_tool.yaml b/sample_standard_app/app/core/tool/search_api_bing_tool.yaml
new file mode 100644
index 00000000..f4e8d08f
--- /dev/null
+++ b/sample_standard_app/app/core/tool/search_api_bing_tool.yaml
@@ -0,0 +1,12 @@
+name: 'search_api_bing_tool'
+description: 'Bing(必应)搜索工具，输入为一个要搜索内容的字符串，例如：input=黄金价格是多少'
+tool_type: 'api'
+input_keys: ['input']
+engine: 'bing'
+search_type: 'common'
+search_params:
+  num: 10
+metadata:
+  type: 'TOOL'
+  module: 'sample_standard_app.app.core.tool.search_api_tool'
+  class: 'SearchAPITool'
\ No newline at end of file
diff --git a/sample_standard_app/app/core/tool/search_api_tool.py b/sample_standard_app/app/core/tool/search_api_tool.py
new file mode 100644
index 00000000..20032ca1
--- /dev/null
+++ b/sample_standard_app/app/core/tool/search_api_tool.py
@@ -0,0 +1,68 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+import os
+# @Time    : 2024/6/12 09:44
+# @Author  : weizjajj 
+# @Email   : weizhongjie.wzj@antgroup.com
+# @FileName: search_api_tool.py
+
+
+from typing import Optional
+
+from langchain_community.utilities import SearchApiAPIWrapper
+from pydantic import Field
+
+from agentuniverse.agent.action.tool.tool import Tool, ToolInput
+from agentuniverse.base.config.component_configer.configers.tool_configer import ToolConfiger
+from agentuniverse.base.util.env_util import get_from_env
+
+
+class SearchAPITool(Tool):
+    """
+    The demo search tool.
+
+    Implement the execute method of demo google search tool, using the `SearchApiAPIWrapper` to implement a simple search.
+
+    Note:
+        You need to sign up for a free account at https://www.searchapi.io/ and get the SEARCHAPI_API_KEY api key (100 free queries).
+
+    Args:
+        search_api_key: Optional[str] = Field(default_factory=lambda: get_from_env("SEARCHAPI_API_KEY")),
+        engine: str = "google" engine type you want to use
+        search_params: dict = {} engine search parameters
+        search_type: str = "common" result type you want to get ,common string or json
+    """
+
+    search_api_key: Optional[str] = Field(default_factory=lambda: get_from_env("SEARCHAPI_API_KEY"))
+    engine: str = "google"
+    search_params: dict = {}
+    search_api_wrapper: Optional[SearchApiAPIWrapper] = None
+    search_type: str = "common"
+
+    def _load_api_wapper(self):
+        if not self.search_api_key:
+            raise ValueError("Please set the SEARCHAPI_API_KEY environment variable.")
+        if not self.search_api_wrapper:
+            self.search_api_wrapper = SearchApiAPIWrapper(searchapi_api_key=self.search_api_key, engine=self.engine)
+        return self.search_api_wrapper
+
+    def execute(self, tool_input: ToolInput):
+        self._load_api_wapper()
+        search_params = {}
+        for k, v in self.search_params.items():
+            if k in tool_input.to_dict():
+                search_params[k] = tool_input.get_data(k)
+                continue
+            search_params[k] = v
+        input = tool_input.get_data("input")
+        if self.search_type == "json":
+            return self.search_api_wrapper.results(query=input, **search_params)
+        return self.search_api_wrapper.run(query=input, **search_params)
+
+    def initialize_by_component_configer(self, component_configer: ToolConfiger) -> 'Tool':
+        """Initialize the tool by the component configer."""
+        super().initialize_by_component_configer(component_configer)
+        self.engine = component_configer.configer.value.get('engine', 'google')
+        self.search_params = component_configer.configer.value.get('search_params', {})
+        self.search_type = component_configer.configer.value.get('search_type', 'common')
+        return self
diff --git a/sample_standard_app/app/core/tool/simple_math_tool.py b/sample_standard_app/app/core/tool/simple_math_tool.py
new file mode 100644
index 00000000..bca1e0e2
--- /dev/null
+++ b/sample_standard_app/app/core/tool/simple_math_tool.py
@@ -0,0 +1,43 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+from langchain_core.utils.json import parse_json_markdown
+
+# @Time    : 2024/6/11 09:49
+# @Author  : weizjajj 
+# @Email   : weizhongjie.wzj@antgroup.com
+# @FileName: simple_math_tool.py
+
+
+from agentuniverse.agent.action.tool.tool import Tool, ToolInput
+
+
+class AddTool(Tool):
+    def execute(self, tool_input: ToolInput):
+        input_params = tool_input.get_data('input')
+        a, b = input_params.split(',')
+        result = float(a) + float(b)
+        return result
+
+
+class SubtractTool(Tool):
+    def execute(self,  tool_input: ToolInput):
+        input_params = tool_input.get_data('input')
+        a, b = input_params.split(',')
+        result = float(a) - float(b)
+        return result
+
+
+class MultiplyTool(Tool):
+    def execute(self,  tool_input: ToolInput):
+        input_params = tool_input.get_data('input')
+        a, b = input_params.split(',')
+        result = float(a) * float(b)
+        return result
+
+
+class DivideTool(Tool):
+    def execute(self,  tool_input: ToolInput):
+        input_params = tool_input.get_data('input')
+        a, b = input_params.split(',')
+        result = float(a) / float(b)
+        return result
diff --git a/sample_standard_app/app/core/tool/sub_simple_tool.yaml b/sample_standard_app/app/core/tool/sub_simple_tool.yaml
new file mode 100644
index 00000000..2a2e6706
--- /dev/null
+++ b/sample_standard_app/app/core/tool/sub_simple_tool.yaml
@@ -0,0 +1,8 @@
+name: 'sub'
+description: 'Subtracting two float number, input_params with 2 num spilt with comma, return result. For example, input_params = 2, 1 , the result = 1'
+tool_type: 'api'
+input_keys: ['input']
+metadata:
+  type: 'TOOL'
+  module: 'sample_standard_app.app.core.tool.simple_math_tool'
+  class: 'SubtractTool'
\ No newline at end of file
diff --git a/sample_standard_app/app/examples/discussion_chat_bots.py b/sample_standard_app/app/examples/discussion_chat_bots.py
new file mode 100644
index 00000000..a163e308
--- /dev/null
+++ b/sample_standard_app/app/examples/discussion_chat_bots.py
@@ -0,0 +1,21 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/6/7 11:22
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: discussion_chat_bots.py
+from agentuniverse.base.agentuniverse import AgentUniverse
+from agentuniverse.agent.agent import Agent
+from agentuniverse.agent.agent_manager import AgentManager
+
+AgentUniverse().start(config_path='../../config/config.toml')
+
+
+def chat(question: str):
+    instance: Agent = AgentManager().get_instance_obj('host_agent')
+    instance.run(input=question)
+
+
+if __name__ == '__main__':
+    chat("甜粽子好吃还是咸粽子好吃")
diff --git a/sample_standard_app/app/examples/law_chat_bot.py b/sample_standard_app/app/examples/law_chat_bot.py
new file mode 100644
index 00000000..0d8e9ba0
--- /dev/null
+++ b/sample_standard_app/app/examples/law_chat_bot.py
@@ -0,0 +1,39 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/5/8 11:44
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: law_chat_bot.py
+from agentuniverse.agent.output_object import OutputObject
+from agentuniverse.agent.agent import Agent
+from agentuniverse.agent.agent_manager import AgentManager
+from agentuniverse.base.agentuniverse import AgentUniverse
+
+AgentUniverse().start(config_path='../../config/config.toml')
+
+
+def chat(question: str):
+    """ Rag agent example.
+
+    The rag agent in agentUniverse becomes a chatbot and can ask questions to get the answer.
+    """
+
+    instance: Agent = AgentManager().get_instance_obj('law_rag_agent')
+    output_object: OutputObject = instance.run(input=question)
+
+    question = f"\nYour event is :\n"
+    question += output_object.get_data('input')
+    print(question)
+
+    background_info = f"\nRetrieved background is :\n"
+    background_info += output_object.get_data('background').replace("\n","")
+    print(background_info)
+
+    res_info = f"\nRag chat bot execution result is :\n"
+    res_info += output_object.get_data('output')
+    print(res_info)
+
+
+if __name__ == '__main__':
+    chat("张三在景区拍摄景区风景，李四闯入了镜头并被拍下。李四能否起诉张三侵犯肖像权，能否要求删除照片")
diff --git "a/sample_standard_app/app/resources/\345\210\221\346\263\225.pdf" "b/sample_standard_app/app/resources/\345\210\221\346\263\225.pdf"
new file mode 100644
index 00000000..5ec96398
Binary files /dev/null and "b/sample_standard_app/app/resources/\345\210\221\346\263\225.pdf" differ
diff --git "a/sample_standard_app/app/resources/\346\260\221\346\263\225\345\205\270.pdf" "b/sample_standard_app/app/resources/\346\260\221\346\263\225\345\205\270.pdf"
new file mode 100644
index 00000000..caa80d99
Binary files /dev/null and "b/sample_standard_app/app/resources/\346\260\221\346\263\225\345\205\270.pdf" differ


Test patch:
diff --git a/sample_standard_app/app/test/test_discussion_agents.py b/sample_standard_app/app/test/test_discussion_agents.py
new file mode 100644
index 00000000..2af73710
--- /dev/null
+++ b/sample_standard_app/app/test/test_discussion_agents.py
@@ -0,0 +1,27 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/6/7 10:49
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: test_discussion_agents.py
+import unittest
+
+from agentuniverse.agent.agent import Agent
+from agentuniverse.agent.agent_manager import AgentManager
+from agentuniverse.agent.output_object import OutputObject
+from agentuniverse.base.agentuniverse import AgentUniverse
+
+
+class DiscussionAgentsTest(unittest.TestCase):
+
+    def setUp(self) -> None:
+        AgentUniverse().start(config_path='../../config/config.toml')
+
+    def test_discussion_agents(self):
+        instance: Agent = AgentManager().get_instance_obj('host_agent')
+        output_object: OutputObject = instance.run(input='甜粽子好吃还是咸粽子好吃')
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/sample_standard_app/app/test/test_nl2api_agent.py b/sample_standard_app/app/test/test_nl2api_agent.py
new file mode 100644
index 00000000..6ab794c8
--- /dev/null
+++ b/sample_standard_app/app/test/test_nl2api_agent.py
@@ -0,0 +1,29 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/6/4 21:27
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: test_react_agent.py
+import unittest
+
+from agentuniverse.agent.agent import Agent
+from agentuniverse.agent.agent_manager import AgentManager
+from agentuniverse.agent.output_object import OutputObject
+from agentuniverse.base.agentuniverse import AgentUniverse
+
+
+class ReActAgentTest(unittest.TestCase):
+
+    def setUp(self) -> None:
+        AgentUniverse().start(config_path='../../config/config.toml')
+
+    def test_react_agent(self):
+        """Test demo reAct agent."""
+        instance: Agent = AgentManager().get_instance_obj('demo_nl2api_agent')
+        output_object: OutputObject = instance.run(input='1+3/2+10-4*3等于多少')
+        print(output_object.to_dict())
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/sample_standard_app/app/test/test_react_agent.py b/sample_standard_app/app/test/test_react_agent.py
new file mode 100644
index 00000000..77534dbd
--- /dev/null
+++ b/sample_standard_app/app/test/test_react_agent.py
@@ -0,0 +1,28 @@
+# !/usr/bin/env python3
+# -*- coding:utf-8 -*-
+
+# @Time    : 2024/6/4 21:27
+# @Author  : wangchongshi
+# @Email   : wangchongshi.wcs@antgroup.com
+# @FileName: test_react_agent.py
+import unittest
+
+from agentuniverse.agent.agent import Agent
+from agentuniverse.agent.agent_manager import AgentManager
+from agentuniverse.agent.output_object import OutputObject
+from agentuniverse.base.agentuniverse import AgentUniverse
+
+
+class ReActAgentTest(unittest.TestCase):
+
+    def setUp(self) -> None:
+        AgentUniverse().start(config_path='../../config/config.toml')
+
+    def test_react_agent(self):
+        """Test demo reAct agent."""
+        instance: Agent = AgentManager().get_instance_obj('demo_react_agent')
+        output_object: OutputObject = instance.run(input='请给出一段python代码，可以计算三数之和，给出之前必须验证代码是否可以运行，最少验证三次')
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/sample_standard_app/app/test/test_search_tool.py b/sample_standard_app/app/test/test_search_tool.py
new file mode 100644
index 00000000..f442fad5
--- /dev/null
+++ b/sample_standard_app/app/test/test_search_tool.py
@@ -0,0 +1,23 @@
+import os
+import unittest
+
+from agentuniverse.agent.action.tool.tool_manager import ToolManager
+from agentuniverse.base.agentuniverse import AgentUniverse
+
+
+class SearchToolTest(unittest.TestCase):
+    """
+    Test cases for the rag agent
+    """
+
+    def setUp(self) -> None:
+        AgentUniverse().start(config_path='../../config/config.toml')
+
+    def test_rag_agent(self):
+        """Test demo rag agent."""
+        res = ToolManager().get_instance_obj("baidu_search_tool").run(input="今日黄金价格")
+        print(res)
+
+
+if __name__ == '__main__':
+    unittest.main()