diff --git a/backend/apps/webui/internal/migrations/015_add_functions.py b/backend/apps/webui/internal/migrations/015_add_functions.py
new file mode 100644
index 000000000..8316a9333
--- /dev/null
+++ b/backend/apps/webui/internal/migrations/015_add_functions.py
@@ -0,0 +1,61 @@
+"""Peewee migrations -- 009_add_models.py.
+
+Some examples (model - class or model name)::
+
+    > Model = migrator.orm['table_name']            # Return model in current state by name
+    > Model = migrator.ModelClass                   # Return model in current state by name
+
+    > migrator.sql(sql)                             # Run custom SQL
+    > migrator.run(func, *args, **kwargs)           # Run python function with the given args
+    > migrator.create_model(Model)                  # Create a model (could be used as decorator)
+    > migrator.remove_model(model, cascade=True)    # Remove a model
+    > migrator.add_fields(model, **fields)          # Add fields to a model
+    > migrator.change_fields(model, **fields)       # Change fields
+    > migrator.remove_fields(model, *field_names, cascade=True)
+    > migrator.rename_field(model, old_field_name, new_field_name)
+    > migrator.rename_table(model, new_table_name)
+    > migrator.add_index(model, *col_names, unique=False)
+    > migrator.add_not_null(model, *field_names)
+    > migrator.add_default(model, field_name, default)
+    > migrator.add_constraint(model, name, sql)
+    > migrator.drop_index(model, *col_names)
+    > migrator.drop_not_null(model, *field_names)
+    > migrator.drop_constraints(model, *constraints)
+
+"""
+
+from contextlib import suppress
+
+import peewee as pw
+from peewee_migrate import Migrator
+
+
+with suppress(ImportError):
+    import playhouse.postgres_ext as pw_pext
+
+
+def migrate(migrator: Migrator, database: pw.Database, *, fake=False):
+    """Write your migrations here."""
+
+    @migrator.create_model
+    class Function(pw.Model):
+        id = pw.TextField(unique=True)
+        user_id = pw.TextField()
+
+        name = pw.TextField()
+        type = pw.TextField()
+
+        content = pw.TextField()
+        meta = pw.TextField()
+
+        created_at = pw.BigIntegerField(null=False)
+        updated_at = pw.BigIntegerField(null=False)
+
+        class Meta:
+            table_name = "function"
+
+
+def rollback(migrator: Migrator, database: pw.Database, *, fake=False):
+    """Write your rollback migrations here."""
+
+    migrator.remove_model("function")
diff --git a/backend/apps/webui/main.py b/backend/apps/webui/main.py
index ee5957224..4a53b15bf 100644
--- a/backend/apps/webui/main.py
+++ b/backend/apps/webui/main.py
@@ -13,6 +13,7 @@ from apps.webui.routers import (
     memories,
     utils,
     files,
+    functions,
 )
 from config import (
     WEBUI_BUILD_HASH,
@@ -70,19 +71,22 @@ app.add_middleware(
     allow_headers=["*"],
 )
 
+
+app.include_router(configs.router, prefix="/configs", tags=["configs"])
 app.include_router(auths.router, prefix="/auths", tags=["auths"])
 app.include_router(users.router, prefix="/users", tags=["users"])
 app.include_router(chats.router, prefix="/chats", tags=["chats"])
 
 app.include_router(documents.router, prefix="/documents", tags=["documents"])
-app.include_router(tools.router, prefix="/tools", tags=["tools"])
 app.include_router(models.router, prefix="/models", tags=["models"])
 app.include_router(prompts.router, prefix="/prompts", tags=["prompts"])
-app.include_router(memories.router, prefix="/memories", tags=["memories"])
 
-app.include_router(configs.router, prefix="/configs", tags=["configs"])
-app.include_router(utils.router, prefix="/utils", tags=["utils"])
+app.include_router(memories.router, prefix="/memories", tags=["memories"])
 app.include_router(files.router, prefix="/files", tags=["files"])
+app.include_router(tools.router, prefix="/tools", tags=["tools"])
+app.include_router(functions.router, prefix="/functions", tags=["functions"])
+
+app.include_router(utils.router, prefix="/utils", tags=["utils"])
 
 
 @app.get("/")
diff --git a/src/lib/apis/functions/index.ts b/src/lib/apis/functions/index.ts
new file mode 100644
index 000000000..e035ef1c1
--- /dev/null
+++ b/src/lib/apis/functions/index.ts
@@ -0,0 +1,193 @@
+import { WEBUI_API_BASE_URL } from '$lib/constants';
+
+export const createNewFunction = async (token: string, func: object) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/functions/create`, {
+		method: 'POST',
+		headers: {
+			Accept: 'application/json',
+			'Content-Type': 'application/json',
+			authorization: `Bearer ${token}`
+		},
+		body: JSON.stringify({
+			...func
+		})
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.catch((err) => {
+			error = err.detail;
+			console.log(err);
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
+export const getFunctions = async (token: string = '') => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/functions/`, {
+		method: 'GET',
+		headers: {
+			Accept: 'application/json',
+			'Content-Type': 'application/json',
+			authorization: `Bearer ${token}`
+		}
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.then((json) => {
+			return json;
+		})
+		.catch((err) => {
+			error = err.detail;
+			console.log(err);
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
+export const exportFunctions = async (token: string = '') => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/functions/export`, {
+		method: 'GET',
+		headers: {
+			Accept: 'application/json',
+			'Content-Type': 'application/json',
+			authorization: `Bearer ${token}`
+		}
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.then((json) => {
+			return json;
+		})
+		.catch((err) => {
+			error = err.detail;
+			console.log(err);
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
+export const getFunctionById = async (token: string, id: string) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/functions/id/${id}`, {
+		method: 'GET',
+		headers: {
+			Accept: 'application/json',
+			'Content-Type': 'application/json',
+			authorization: `Bearer ${token}`
+		}
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.then((json) => {
+			return json;
+		})
+		.catch((err) => {
+			error = err.detail;
+
+			console.log(err);
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
+export const updateFunctionById = async (token: string, id: string, func: object) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/functions/id/${id}/update`, {
+		method: 'POST',
+		headers: {
+			Accept: 'application/json',
+			'Content-Type': 'application/json',
+			authorization: `Bearer ${token}`
+		},
+		body: JSON.stringify({
+			...func
+		})
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.then((json) => {
+			return json;
+		})
+		.catch((err) => {
+			error = err.detail;
+
+			console.log(err);
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
+export const deleteFunctionById = async (token: string, id: string) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/functions/id/${id}/delete`, {
+		method: 'DELETE',
+		headers: {
+			Accept: 'application/json',
+			'Content-Type': 'application/json',
+			authorization: `Bearer ${token}`
+		}
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.then((json) => {
+			return json;
+		})
+		.catch((err) => {
+			error = err.detail;
+
+			console.log(err);
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
diff --git a/src/lib/components/workspace/Functions.svelte b/src/lib/components/workspace/Functions.svelte
index f00e9ad2f..ebadce50c 100644
--- a/src/lib/components/workspace/Functions.svelte
+++ b/src/lib/components/workspace/Functions.svelte
@@ -3,29 +3,39 @@
 	import fileSaver from 'file-saver';
 	const { saveAs } = fileSaver;
 
+	import { WEBUI_NAME } from '$lib/stores';
 	import { onMount, getContext } from 'svelte';
-	import { WEBUI_NAME, prompts, tools } from '$lib/stores';
 	import { createNewPrompt, deletePromptByCommand, getPrompts } from '$lib/apis/prompts';
 
 	import { goto } from '$app/navigation';
 	import {
-		createNewTool,
-		deleteToolById,
-		exportTools,
-		getToolById,
-		getTools
-	} from '$lib/apis/tools';
+		createNewFunction,
+		deleteFunctionById,
+		exportFunctions,
+		getFunctionById,
+		getFunctions
+	} from '$lib/apis/functions';
+
 	import ArrowDownTray from '../icons/ArrowDownTray.svelte';
 	import Tooltip from '../common/Tooltip.svelte';
 	import ConfirmDialog from '../common/ConfirmDialog.svelte';
 
 	const i18n = getContext('i18n');
 
-	let toolsImportInputElement: HTMLInputElement;
+	let functionsImportInputElement: HTMLInputElement;
 	let importFiles;
 
 	let showConfirm = false;
 	let query = '';
+
+	let functions = [];
+
+	onMount(async () => {
+		functions = await getFunctions(localStorage.token).catch((error) => {
+			toast.error(error);
+			return [];
+		});
+	});
 </script>
 
 <svelte:head>
@@ -82,30 +92,30 @@
 <hr class=" dark:border-gray-850 my-2.5" />
 
 <div class="my-3 mb-5">
-	{#each $tools.filter((t) => query === '' || t.name
+	{#each functions.filter((f) => query === '' || f.name
 				.toLowerCase()
-				.includes(query.toLowerCase()) || t.id.toLowerCase().includes(query.toLowerCase())) as tool}
+				.includes(query.toLowerCase()) || f.id.toLowerCase().includes(query.toLowerCase())) as func}
 		<button
 			class=" flex space-x-4 cursor-pointer w-full px-3 py-2 dark:hover:bg-white/5 hover:bg-black/5 rounded-xl"
 			type="button"
 			on:click={() => {
-				goto(`/workspace/tools/edit?id=${encodeURIComponent(tool.id)}`);
+				goto(`/workspace/functions/edit?id=${encodeURIComponent(func.id)}`);
 			}}
 		>
 			<div class=" flex flex-1 space-x-4 cursor-pointer w-full">
 				<a
-					href={`/workspace/tools/edit?id=${encodeURIComponent(tool.id)}`}
+					href={`/workspace/functions/edit?id=${encodeURIComponent(func.id)}`}
 					class="flex items-center text-left"
 				>
 					<div class=" flex-1 self-center pl-5">
 						<div class=" font-semibold flex items-center gap-1.5">
 							<div>
-								{tool.name}
+								{func.name}
 							</div>
-							<div class=" text-gray-500 text-xs font-medium">{tool.id}</div>
+							<div class=" text-gray-500 text-xs font-medium">{func.id}</div>
 						</div>
 						<div class=" text-xs overflow-hidden text-ellipsis line-clamp-1">
-							{tool.meta.description}
+							{func.meta.description}
 						</div>
 					</div>
 				</a>
@@ -115,7 +125,7 @@
 					<a
 						class="self-center w-fit text-sm px-2 py-2 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
 						type="button"
-						href={`/workspace/tools/edit?id=${encodeURIComponent(tool.id)}`}
+						href={`/workspace/functions/edit?id=${encodeURIComponent(func.id)}`}
 					>
 						<svg
 							xmlns="http://www.w3.org/2000/svg"
@@ -141,18 +151,20 @@
 						on:click={async (e) => {
 							e.stopPropagation();
 
-							const _tool = await getToolById(localStorage.token, tool.id).catch((error) => {
-								toast.error(error);
-								return null;
-							});
+							const _function = await getFunctionById(localStorage.token, func.id).catch(
+								(error) => {
+									toast.error(error);
+									return null;
+								}
+							);
 
-							if (_tool) {
-								sessionStorage.tool = JSON.stringify({
-									..._tool,
-									id: `${_tool.id}_clone`,
-									name: `${_tool.name} (Clone)`
+							if (_function) {
+								sessionStorage.function = JSON.stringify({
+									..._function,
+									id: `${_function.id}_clone`,
+									name: `${_function.name} (Clone)`
 								});
-								goto('/workspace/tools/create');
+								goto('/workspace/functions/create');
 							}
 						}}
 					>
@@ -180,16 +192,18 @@
 						on:click={async (e) => {
 							e.stopPropagation();
 
-							const _tool = await getToolById(localStorage.token, tool.id).catch((error) => {
-								toast.error(error);
-								return null;
-							});
+							const _function = await getFunctionById(localStorage.token, func.id).catch(
+								(error) => {
+									toast.error(error);
+									return null;
+								}
+							);
 
-							if (_tool) {
-								let blob = new Blob([JSON.stringify([_tool])], {
+							if (_function) {
+								let blob = new Blob([JSON.stringify([_function])], {
 									type: 'application/json'
 								});
-								saveAs(blob, `tool-${_tool.id}-export-${Date.now()}.json`);
+								saveAs(blob, `function-${_function.id}-export-${Date.now()}.json`);
 							}
 						}}
 					>
@@ -204,14 +218,18 @@
 						on:click={async (e) => {
 							e.stopPropagation();
 
-							const res = await deleteToolById(localStorage.token, tool.id).catch((error) => {
+							const res = await deleteFunctionById(localStorage.token, func.id).catch((error) => {
 								toast.error(error);
 								return null;
 							});
 
 							if (res) {
-								toast.success('Tool deleted successfully');
-								tools.set(await getTools(localStorage.token));
+								toast.success('Function deleted successfully');
+
+								functions = await getFunctions(localStorage.token).catch((error) => {
+									toast.error(error);
+									return [];
+								});
 							}
 						}}
 					>
@@ -246,7 +264,7 @@
 	<div class="flex space-x-2">
 		<input
 			id="documents-import-input"
-			bind:this={toolsImportInputElement}
+			bind:this={functionsImportInputElement}
 			bind:files={importFiles}
 			type="file"
 			accept=".json"
@@ -260,7 +278,7 @@
 		<button
 			class="flex text-xs items-center space-x-1 px-3 py-1.5 rounded-xl bg-gray-50 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 dark:text-gray-200 transition"
 			on:click={() => {
-				toolsImportInputElement.click();
+				functionsImportInputElement.click();
 			}}
 		>
 			<div class=" self-center mr-2 font-medium">{$i18n.t('Import Functions')}</div>
@@ -284,16 +302,16 @@
 		<button
 			class="flex text-xs items-center space-x-1 px-3 py-1.5 rounded-xl bg-gray-50 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 dark:text-gray-200 transition"
 			on:click={async () => {
-				const _tools = await exportTools(localStorage.token).catch((error) => {
+				const _functions = await exportFunctions(localStorage.token).catch((error) => {
 					toast.error(error);
 					return null;
 				});
 
-				if (_tools) {
-					let blob = new Blob([JSON.stringify(_tools)], {
+				if (_functions) {
+					let blob = new Blob([JSON.stringify(_functions)], {
 						type: 'application/json'
 					});
-					saveAs(blob, `tools-export-${Date.now()}.json`);
+					saveAs(blob, `functions-export-${Date.now()}.json`);
 				}
 			}}
 		>
@@ -322,18 +340,22 @@
 	on:confirm={() => {
 		const reader = new FileReader();
 		reader.onload = async (event) => {
-			const _tools = JSON.parse(event.target.result);
-			console.log(_tools);
+			const _functions = JSON.parse(event.target.result);
+			console.log(_functions);
 
-			for (const tool of _tools) {
-				const res = await createNewTool(localStorage.token, tool).catch((error) => {
+			for (const func of _functions) {
+				const res = await createNewFunction(localStorage.token, func).catch((error) => {
 					toast.error(error);
 					return null;
 				});
 			}
 
-			toast.success('Tool imported successfully');
-			tools.set(await getTools(localStorage.token));
+			toast.success('Functions imported successfully');
+
+			functions = await getFunctions(localStorage.token).catch((error) => {
+				toast.error(error);
+				return [];
+			});
 		};
 
 		reader.readAsText(importFiles[0]);
@@ -344,8 +366,8 @@
 			<div>Please carefully review the following warnings:</div>
 
 			<ul class=" mt-1 list-disc pl-4 text-xs">
-				<li>Tools have a function calling system that allows arbitrary code execution.</li>
-				<li>Do not install tools from sources you do not fully trust.</li>
+				<li>Functions allow arbitrary code execution.</li>
+				<li>Do not install functions from sources you do not fully trust.</li>
 			</ul>
 		</div>