文章总结: 火山引擎推出火山Supabase,一款兼容开源生态的BaaS产品,旨在解决AIAgent开发中的后端基建难题。该产品通过全链路Serverless架构实现弹性伸缩与成本节约,提供企业级数据安全体系与AI原生交互,显著提升开发效率。文档阐述了其基于PostgreSQL的核心架构与组件,并利用代码实例演示了在Agent任务管理及RAG功能中的集成应用。 综合评分: 70 文章分类: 产品介绍,应用安全,云安全,解决方案
Vibe Coding 一键部署——火山引擎推出 Supabase, 驱动Agent 应用快速上线
火山引擎数据库 火山引擎数据库
字节跳动技术团队
2026年3月9日 18:05 北京
Agent 开发者几乎都会遇到这样的场景:脑海中智能交互的蓝图清晰无比,动手时却被繁杂的后端基建卡住——搭建服务架构、设计数据库表结构、配置认证体系、编写海量 API……好不容易让应用上线,新的问题又接踵而至:用户量未起时,闲置服务器空耗成本;用量起来后,流量洪峰又易引发服务崩溃。
在构建 AI Agent 的浪潮中,是否有一种方案,能快速扫清后端障碍,让创意一键落地?
为此,火山引擎推出火山 Supabase ——一个让开发者能专注业务逻辑的“云上开发工具箱”,旨在让开发者摆脱后端基建的束缚,实现高效的 Vibe Coding,并聚焦于 Agent 交互逻辑与体验创新。
Supabase,作为一款广受欢迎的开源 BaaS(Backend as a Service,后端即服务),将数据库、用户认证、文件存储、实时通信等所有通用后端能力,打包成即取即用的标准化服务。
Vercel 创始人,Next.js 之父 Guillermo Rauch 称 Supabase 是 PostgreSQL 的最佳 BaaS 实现,为 Vibe Coding 提供了坚实的“道路”和数据基础,是开发者构建应用时不可或缺的后端平台。
火山 Supabase 100% 兼容开源 Supabase 生态,保障开源开发者能向云上无缝迁移,更在成本控制、数据安全、开发效率三大核心维度实现突破性升级,让开发者摆脱基建内耗,聚焦核心业务创新与价值落地。目前火山 Supabase 已服务于字节内外客户,如豆包、扣子、TRAE 等典型的 AI Agent 平台。
助力Agent 开发提效 80%,资源利用率大幅提升
开源 Supabase 凭借其灵活性和与 PostgreSQL 生态的深度兼容,在 GitHub 上斩获了近 10 万 Star,深受全球开发者青睐。
而火山 Supabase 在保留开源优势的基础上,注入了字节跳动大规模业务场景锤炼出的企业级服务能力,为开发者带来了更极致的性价比与稳定性。
- 全链路 Serverless 架构,实现弹性与成本双赢。传统 Serverless 架构通常仅覆盖计算层,数据库仍需固定配置,成本控制依然是核心挑战。火山 Supabase 创新性地将 Serverless 理念贯穿至数据库层,实现了 BaaS 服务层到数据库层的全链路弹性。业务低谷时,资源可自动休眠,费用趋近于零;流量波峰时,系统则能秒级自动扩容,无需人工干预。经实际生产业务验证,与自建开源 Supabase 相比,火山 Supabase 最高可节省 23 倍的成本。
- 企业级数据安全体系,筑牢业务资产防线。依托字节跳动海量业务验证的“数据保险箱”方案,火山 Supabase 提供了核心的 Data as Git 能力,让数据管理如代码版本控制般便捷。企业可创建独立的数据分支,用于新功能测试、AI 模型训练,全程不影响生产环境。当遇到误操作导致的数据损坏时,通过时间点回溯功能,可瞬间恢复到任意时间点的数据状态。结合金融级高可用底座与存算分离架构,即便面对电商大促、金融交易等业务规模的激增,也能确保数据不丢失、服务不中断。
- AI 原生极简交互,开发效率提升 80%+。火山 Supabase 重构了开发者的交互流程。首先,开发者可以通过自然语言下达指令,例如“创建一个用于测试环境的 Supabase 实例”,系统便会自动完成所有配置,传统开发模式下需要十余个步骤的繁琐操作,如今仅需 2-3 步即可完成。其次,基于 火山Supabase 的 RLS 和 标准化 REST API,开发者无需再开发后端服务,仅需开发前端代码即可完成 AI Agent 等应用的制作,大幅降低了开发、调试、部署的成本。
以扣子编程为例,在每个 Vibe Coding 生成物(网页应用、移动应用、小程序、智能体、技能等)背后,都会同步创建和使用一个Supabase 实例运行这些产物,并且使用火山 Supabase 的多分支能力(Branching)进行环境隔离。
在使用火山 Supabase 后,扣子编程整体的交付效率、质量、成本,都得到极大的改善。以交付效率为例,基于火山 Supabase,扣子编程在 Vibe Coding 场景,提供了以下功能:
- 开箱即用的云端环境:打开网页即可开始,每个项目自动分配云端运行环境和对应资源,无需安装任何工具。遇到问题也能一键重启、自动恢复。
- 一键部署和项目构建服务:一键完成云端打包、构建与服务部署,支持自定义域名。版本可回退,部署记录完善、可追踪。
这极大降低了 Agent 开发的门槛,让开发者一站式完成从构建到落地的完整生产级闭环,让整个开发过程更聚焦于创意和价值创造。
站在 PostgreSQL 肩膀上的 Agent 全栈开发平台
火山 Supabase 的强大之处,在于它巧妙地将一系列成熟的开源组件,围绕 PostgreSQL 这颗强大的“心脏”进行整合与封装,为开发者提供了一套连贯、高效的工具集。下面,我们深入其核心组件,探究其技术原理。
核心架构:以 PostgreSQL 为中心的全栈协同
火山 Supabase 的架构并非重新发明轮子,而是“站在巨人的肩膀上”。它以功能强大且极度可靠的 PostgreSQL 数据库为中心,集成了一系列专注于特定领域的服务,每个服务都力求做到小而精,并通过良好定义的接口协同工作。
- PostgreSQL:不止开源 PostgreSQL,火山团队为更好服务 Agent 场景,全新打造 Serverless PostgreSQL,提供了一系列前所未有的体验——秒级弹性、资源自动休眠、秒级 Branch 管理、Timetravel 灵活查询历史数据等。
- PostgREST:一个神奇的工具,它能将你的 PostgreSQL 数据库瞬间转换成一个 RESTful API。你无需编写一行后端代码,数据库中的表、视图、函数,都会自动拥有对应的 API 端点。
- GoTrue: 一个基于 JWT (JSON Web Tokens) 的身份验证服务,负责用户注册、登录和管理。它与 PostgreSQL 的行级安全(Row Level Security, RLS)机制深度集成,为数据访问提供了精细的权限控制。
- Realtime:一个基于 Elixir 构建的高性能 WebSocket 服务。它通过监听 PostgreSQL 的预写日志(Write-Ahead Log, WAL),能够实时地将数据库的变更推送给客户端,是构建实时协作应用的关键。
- Storage: 提供对象存储服务,用于管理图片、视频等大文件。其元数据存储在 Postgres 中,权限管理同样与 GoTrue 和 RLS 集成打通。
- Edge Functions:分布式 Serverless 函数。开发者可以编写 TypeScript、Python 函数,按需执行,可用于处理 Webhooks、安全地调用第三方 API 或执行自定义的后端逻辑。
数据流视角下的协同工作
- 用户请求:一个前端应用通过 supabase-js 客户端库发起请求。
- API 网关 (Kong):所有请求首先经过 API 网关,它负责路由、认证和负载均衡。
- 身份验证 (GoTrue):如果是需要认证的请求,网关会携带 JWT 令牌与 GoTrue 通信,验证用户身份。
- API 服务 (PostgREST):验证通过后,请求被转发到 PostgREST。PostgREST 将 HTTP 请求(如 GET /tasks)解析成 SQL 查询。
- 数据库权限 (PostgreSQL RLS):PostgreSQL 在执行 SQL 前,会检查为当前用户角色(从 JWT 中解析)设定的 RLS 策略。例如,一个 RLS 策略可以规定“用户只能访问 tasks 表中 user_id 等于自己 ID 的行”。
- 数据响应: 数据库返回符合权限的数据,经由 PostgREST 和 API 网关,最终到达客户端。
- 实时更新 (Realtime):如果某个操作(如 INSERT 或 UPDATE)修改了数据库,Realtime 服务会监听到 WAL 的变化,并将变更通过 WebSocket 推送给所有订阅了该数据的客户端,实现界面自动更新。
- 服务端逻辑 (Edge Functions):如果需要执行复杂或敏感的操作(如调用外部支付接口),客户端会调用一个 Edge Function。该函数在沙箱环境中运行,可以使用 service_role_key 安全地与数据库或其他服务交互,并将结果返回给客户端。
火山 Supabase一站式AI基建能力供给
技术实操:将火山 Supabase 集成到 Agent 开发环境中,开启 Vibe Coding
将火山 Supabase 集成到开发者的 Agent 开发环境中,可以极大地加速 Agent 和全栈应用的后端构建。下面我们将通过两个具体的 Agent 开发场景——“任务管理与记忆”、“RAG功能”,展示如何实现集成。
基于火山的Supabase的Agent的数据链路示意图如下:
1. 环境配置:连接你的 Supabase 项目
在项目环境中,第一步是安全地配置 Supabase 的连接凭证。我们推荐使用环境变量来管理这些敏感信息。
在你的项目设置或 .env文件中,添加以下两个变量:
SUPABASE_URL="YOUR_SUPABASE_PROJECT_URL"#例如br123123123.supabase.aidap-global.cn-beijing.volces.com:443SUPABASE_ANON_KEY="YOUR_SUPABASE_ANON_KEY"
- SUPABASE_URL 和 SUPABASE_ANON_KEY 可以在火山 Supabase 控制台的“连接”页面中获取到。ANON_KEY 是公开的匿名密钥,它受到 RLS 策略的保护,可以安全地在前端环境使用它。
2. 初始化 supabase-js 客户端
在项目中(无论是 Node.js 后端还是前端代码),首先需要安装 supabase-js客户端库:
npm install @supabase/supabase-js
然后,创建一个客户端实例。通常,我们会将这个实例放在一个单独的文件中(例如 lib/supabaseClient.js),以便在整个项目中复用。
// lib/supabaseClient.jsimport { createClient } from'@supabase/supabase-js'
const supabaseUrl = process.env.SUPABASE_URLconst supabaseAnonKey = process.env.SUPABASE_ANON_KEY
exportconst supabase = createClient(supabaseUrl, supabaseAnonKey)
3. 示例1:为 Agent 实现用户任务管理与记忆
假设我们正在构建一个 Agent,它需要记录用户的任务,并能根据历史任务提供建议。
(1) 创建相关表结构 及 RLS 策略
首先,在火山 Supabase 的 Dashboard 中 SQL Editor 里创建 tasks 表,并为 Agent 的“记忆”创建一个 memories 表,后者将包含向量数据。
上下滑动查看完整内容
-- 启用 pgvector 扩展CREATE EXTENSION IF NOT EXISTS vector;
-- 创建任务表CREATE TABLE public.tasks ( id uuid primary key default gen_random_uuid(), user_id uuid references auth.users not null, title text not null, is_complete boolean defaultfalse, created_at timestamptz default now());
-- 为任务表启用行级安全 (RLS)ALTER TABLE public.tasks ENABLE ROW LEVEL SECURITY;
-- 策略:用户只能看到和操作自己的任务CREATE POLICY "Users can manage their own tasks."ON public.tasksFOR ALLUSING(auth.uid() = user_id)WITH CHECK(auth.uid() = user_id);
-- 创建记忆表,用于存储向量化后的任务信息CREATE TABLE public.memories ( id uuid primary key default gen_random_uuid(), task_id uuid references public.tasks on delete cascade, user_id uuid references auth.users not null, content text not null, -- 任务标题或描述 embedding vector(384), -- 假设使用 384 维的 embedding 模型 created_at timestamptz default now());
-- 为记忆表启用 RLSALTER TABLE public.memories ENABLE ROW LEVEL SECURITY;
-- 策略:用户只能访问自己的记忆CREATE POLICY "Users can access their own memories."ON public.memoriesFOR ALLUSING(auth.uid() = user_id)WITH CHECK(auth.uid() = user_id);
(2) 创建向量检索Function
创建一个 PG Function 来进行向量相似度检索。
-- 创建一个函数来匹配相似的记忆CREATE OR REPLACE FUNCTION match_memories( query_embedding vector(384), match_threshold float, match_count int)RETURNS TABLE (id uuid, content text, similarity float)LANGUAGE sql STABLE AS $$ SELECT memories.id, memories.content, 1 - (memories.embedding <=> query_embedding) as similarity FROM memories WHERE auth.uid() = memories.user_id -- 确保只在当前用户记忆中搜索 AND 1 - (memories.embedding <=> query_embedding) > match_threshold ORDER BY similarity DESC LIMIT match_count;$$;
(3) 实现基本的 CRUD 操作
现在,在代码中,我们可以使用 supabase-js 与这些表进行交互。
上下滑动查看完整内容
import { supabase } from './lib/supabaseClient.js';
// 获取当前用户的任务列表async function getTasks(){ const { data: tasks, error } = await supabase .from('tasks') .select('*') .order('created_at', { ascending: false });
if (error) { console.error('Error fetching tasks:', error); return; } console.log('Tasks:', tasks);}
// 创建一个新任务async function createTask(title){ const { data: { user } } = await supabase.auth.getUser(); // 获取当前登录用户 if (!user) { console.error('User not logged in'); return; }
const { data: newTask, error } = await supabase .from('tasks') .insert({ title: title, user_id: user.id }) .select() .single();
if (error) { console.error('Error creating task:', error); } else { console.log('New task created:', newTask); // 异步生成并存储记忆向量 (具体实现在 Edge Function 的 generate-memory 函数中,见下节) await supabase.functions.invoke('generate-memory', { body: { task_id: newTask.id, content: newTask.title }, }); }}
(4) 使用 Edge Function 实现记忆信息的Embedding并入库
使用 Edge Function 进行记忆信息的Embedding并入库,即上节提及的“generate-memory”的具体实现。
相比于直接在客户端执行Embedding并入库,在 Edge Function 中会更安全,能避免暴露实现细节。
上下滑动查看完整内容
// supabase/functions/generate-memory/index.tsimport { serve } from 'https://deno.land/[email protected]/http/server.ts';import { pipeline } from 'https://cdn.jsdelivr.net/npm/@xenova/[email protected]';import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
serve(async (req) => { const { task_id, content } = await req.json();
// 使用 service_role key 安全地初始化 Admin 客户端 const supabaseAdmin = createClient( Deno.env.get('SUPABASE_URL') , Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ); // 1. 生成 Embedding const generateEmbedding = await pipeline('feature-extraction', 'Supabase/gte-small'); const output = await generateEmbedding(content, { pooling: 'mean', normalize: true }); const embedding = Array.from(output.data);
// 2. 获取任务信息,以拿到 user_id const { data: task, error: taskError } = await supabaseAdmin .from('tasks') .select('user_id') .eq('id', task_id) .single();
if (taskError) { returnnew Response(JSON.stringify({ error: taskError.message }), { status: 500 }); }
// 3. 将向量存入 memories 表 const { error: insertError } = await supabaseAdmin.from('memories').insert({ task_id, user_id: task.user_id, content, embedding, });
if (insertError) { returnnew Response(JSON.stringify({ error: insertError.message }), { status: 500 }); }
returnnew Response(JSON.stringify({ message: 'Memory created' }), { status: 200 });});
(5) 在 APP前端 或 Edge Function 中检索记忆信息
在 APP前端 或 Edge Function 中,调用以下函数来检索进行记忆信息。
asyncfunctionfindSimilarMemories(text) { // 1. 将当前文本生成 embedding (此处省略) const queryEmbedding = await generateEmbeddingFor(text);
// 2. 调用 RPC 函数进行搜索 const { data: memories, error } = await supabase.rpc('match_memories', { query_embedding: queryEmbedding, match_threshold: 0.7, // 相似度阈值 match_count: 5, // 返回最多 5 个结果 });
if (error) { console.error('Error searching memories:', error); return []; } console.log('Found similar memories:', memories); return memories;}
(6) 使用 Edge Function 中访问 大模型 (或MCP、外部工具等)
Edge Functions 可以用于承载 AI Agent 的核心逻辑,如调用 LLM、MCP Tools、执行工具)的执行。
上下滑动查看完整内容
// supabase/functions/agent-core/index.tsimport { serve } from "https://deno.land/[email protected]/http/server.ts";import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
serve(async (req) => { const supabase = createClient( Deno.env.get("SUPABASE_URL")!, Deno.env.get("SUPABASE_ANON_KEY")! );
// 1. 解析用户请求(用户输入、Agent ID) const { user_id, query, agent_id } = await req.json();
// 2. 检索长期记忆(结构化+非结构化) const user_prefs = await supabase .from("user_profiles") .select("*") .eq("user_id", user_id) .single();
// 3. 调用 LLM(比如 OpenAI)生成 Agent 响应 const llmResponse = await fetch("https://api.openai.com/v1/chat/completions", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${Deno.env.get("OPENAI_API_KEY")}` }, body: JSON.stringify({ model: "gpt-3.5-turbo", messages: [ { role: "system", content: `你是一个基于 Supabase 的 AI Agent,用户偏好:${JSON.stringify(user_prefs.data)}` }, { role: "user", content: query } ] }) });
const llmData = await llmResponse.json(); const agent_answer = llmData.choices[0].message.content;
// 4. 保存本次交互到长期记忆 await supabase.table("agent_sessions").upsert({ user_id, agent_id, query: query, response: agent_answer, updated_at: new Date() });
// 5. 返回 Agent 响应 returnnew Response(JSON.stringify({ answer: agent_answer }), { headers: { "Content-Type": "application/json" } });});
部署该函数后,客户端调用 supabase.functions.invoke(‘generate-memory’, …)即可触发服务端的向量生成与存储,整个过程对前端透明且安全。
4. 示例2:为 Agent 实现RAG功能
(1) 创建相关表结构 及 RLS 策略
创建两个表:一个存储原始文档分块,一个存储向量(也可合并,分开更易管理):
上下滑动查看完整内容
-- 启用 pgvector 扩展CREATE EXTENSION IF NOT EXISTS vector;
-- 文档元数据表:存储原始文档信息CREATE TABLE IF NOT EXISTS rag_documents( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), document_name TEXT NOT NULL, -- 文档名称 document_type TEXT, -- 文档类型(pdf/txt/md 等) user_id UUID, -- 所属用户(关联 auth.users) created_at TIMESTAMP DEFAULT NOW());
-- 文档分块&向量表:存储分块文本和对应的 Embedding 向量CREATE TABLE IF NOT EXISTS rag_document_chunks( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), document_id UUID REFERENCES rag_documents(id) ON DELETE CASCADE, -- 关联文档 chunk_text TEXT NOT NULL, -- 文档分块文本 chunk_index INT, -- 分块序号(保持上下文顺序) embedding vector(1536), -- OpenAI Embedding 向量(维度 1536,可根据模型调整) created_at TIMESTAMP DEFAULT NOW());
-- 创建向量索引:加速相似度检索(核心!否则大数据量检索慢)CREATE INDEX IF NOT EXISTS idx_rag_embeddings ON rag_document_chunks USING ivfflat(embedding vector_cosine_ops) -- 余弦相似度WITH(lists = 100); -- lists 数值:数据量小设 10-100,大数据量设 1000+
-- (可选)启用 RLS 规则,确保用户只能访问自己的文档ALTER TABLE rag_documents ENABLE ROW LEVEL SECURITY;ALTER TABLE rag_document_chunks ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can only access their own documents"ON rag_documents FOR ALL USING(auth.uid() = user_id);
CREATE POLICY "Users can only access their own chunks"ON rag_document_chunks FOR ALL USING( EXISTS ( SELECT 1 FROM rag_documents WHERE rag_documents.id = rag_document_chunks.document_id AND rag_documents.user_id = auth.uid() ));
(2) 预处理文档:Embedding并入库
上下滑动查看完整内容
import osimport uuidfrom dotenv import load_dotenvfrom supabase import create_client, Clientfrom openai import OpenAIfrom PyPDF2 import PdfReader
# 加载环境变量load_dotenv()SUPABASE_URL = os.getenv("SUPABASE_URL")SUPABASE_KEY = os.getenv("SUPABASE_ANON_KEY")OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
# 初始化客户端supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY)openai_client = OpenAI(api_key=OPENAI_API_KEY)
# 1. 文档分块工具(通用:支持文本/PDF)def split_document(file_path, chunk_size=500, chunk_overlap=50): """ 拆分文档为小分块,避免向量长度超限,同时保留上下文重叠 """ chunks = [] # 处理 PDF if file_path.endswith(".pdf"): reader = PdfReader(file_path) text = "" for page in reader.pages: text += page.extract_text() or"" # 处理纯文本 else: with open(file_path, "r", encoding="utf-8") as f: text = f.read() # 分块逻辑 start = 0 while start < len(text): end = start + chunk_size chunk = text[start:end].strip() if chunk: chunks.append(chunk) start = end - chunk_overlap # 重叠部分,保持上下文连贯 return chunks
# 2. 生成 Embedding 向量def get_embedding(text): """调用 OpenAI Embedding 模型生成向量""" response = openai_client.embeddings.create( input=text, model="text-embedding-3-small" # 轻量、低成本,维度 1536 ) return response.data[0].embedding
# 3. 文档入库主函数def ingest_document(file_path, user_id): # 步骤 1:拆分文档 chunks = split_document(file_path) ifnot chunks: raise ValueError("文档内容为空") # 步骤 2:创建文档元数据 document_name = os.path.basename(file_path) document_type = file_path.split(".")[-1] doc_response = supabase.table("rag_documents").insert({ "document_name": document_name, "document_type": document_type, "user_id": user_id }).execute() document_id = doc_response.data[0]["id"] # 步骤 3:生成向量并入库 chunk_records = [] for idx, chunk in enumerate(chunks): embedding = get_embedding(chunk) chunk_records.append({ "document_id": document_id, "chunk_text": chunk, "chunk_index": idx, "embedding": embedding }) # 批量插入(提升效率) supabase.table("rag_document_chunks").insert(chunk_records).execute() print(f"文档 {document_name} 入库完成,共拆分 {len(chunks)} 个分块") return document_id
# 测试:上传一个 PDF 文档if __name__ == "__main__": # 替换为你的文件路径和用户 ID(Supabase Auth 的 user_id) ingest_document("test_document.pdf", "your-user-uuid-here")
(3) 使用 Edge Function 实现RAG功能
上下滑动查看完整内容
// supabase/functions/rag-retrieve/index.tsimport { serve } from "https://deno.land/[email protected]/http/server.ts";import { createClient } from "https://esm.sh/@supabase/supabase-js@2";import OpenAI from "https://esm.sh/openai@4";
serve(async (req) => { // 解析请求参数 const { query, user_id } = await req.json(); if (!query || !user_id) { returnnew Response(JSON.stringify({ error: "缺少参数" }), { status: 400 }); }
// 初始化客户端 const supabase = createClient( Deno.env.get("SUPABASE_URL")!, Deno.env.get("SUPABASE_ANON_KEY")! ); const openai = new OpenAI({ apiKey: Deno.env.get("OPENAI_API_KEY")! });
// 1. 生成问题向量 const embeddingResponse = await openai.embeddings.create({ input: query, model: "text-embedding-3-small", }); const queryEmbedding = embeddingResponse.data[0].embedding;
// 2. 向量检索 const { data: chunks } = await supabase.raw(` SELECT rc.chunk_text, 1 - (rc.embedding <=> $1) as similarity FROM rag_document_chunks rc JOIN rag_documents rd ON rc.document_id = rd.id WHERE rd.user_id = $2 ORDER BY similarity DESC LIMIT 5; `, [queryEmbedding, user_id]);
// 3. 生成回答 const context = chunks.map((c: any) => c.chunk_text).join("\n\n"); const llmResponse = await openai.chat.completions.create({ model: "gpt-3.5-turbo", messages: [ { role: "system", content: "基于上下文回答问题,不要编造内容" }, { role: "user", content: `上下文:${context}\n问题:${query}` } ] });
returnnew Response(JSON.stringify({ answer: llmResponse.choices[0].message.content, context: context }), { headers: { "Content-Type": "application/json" } });});
5. 示例:利用 Realtime 实现实时状态同步
Agent 需要实时交互(比如多用户协作 Agent、实时任务进度更新),Realtime 可以实现实时主动地推送实时消息。
在APP前端代码(例如 React 组件)中,可以这样订阅 tasks 表的变更:
上下滑动查看完整内容
import { useEffect, useState } from 'react';import { supabase } from './lib/supabaseClient';
function RealtimeTasks(){ const [tasks, setTasks] = useState([]);
useEffect(() => { // 初始加载任务 const fetchInitialTasks = async () => { const { data } = await supabase.from('tasks').select('*'); setTasks(data || []); }; fetchInitialTasks();
// 订阅变更 const channel = supabase .channel('public:tasks') .on( 'postgres_changes', { event: '*', schema: 'public', table: 'tasks' }, (payload) => { console.log('Change received!', payload); // 简单地重新拉取数据以更新 UI // 更优化的方式是根据 payload.eventType 来增量更新 state fetchInitialTasks(); } ) .subscribe();
// 清理订阅 return () => { supabase.removeChannel(channel); }; }, []);
return ( - {task.title} );}
这样,任何用户创建、更新或删除任务,所有打开该页面的客户端都会几乎瞬间收到通知并更新 UI,无需手动刷新。
6. 高级用法示例:Branch多分支/多环境管理
在前文我们提到火山 Supabase 的 Data as Git 能力。站在工程视角,Branch 就是一条独立的数据时间线:你可以为每个环境(Dev / Staging / Prod),甚至为重要客户或一次数据库大改,创建各自的分支,在分支上做结构调整、压测与演练,不会污染生产主线。火山 Supabase 为整套 BaaS 服务,包括 Database、Auth、Storage、Edge Functions 都提供了分支能力,并且创建分支时可以选择 “最新数据”或者“空” 等不同策略。
在项目中,其开发和生产环境使用同一个 Supabase Workspace,但 Branch 完全独立。整套机制原理如下:
- 开发分支开发:在 Dev Branch 上调整 Schema、调试 RLS、验证 Agent 逻辑,并用 Realtime、pgvector 等能力跑通端到端链路。
- 预发分支验证:将 Dev 上稳定的 Schema 迁移到 Staging Branch,使用部分真实数据或脱敏数据进行灰度验证。
- 生产分支发布:仅将 Schema 变更从 Staging 合入 Prod Branch,不带任何测试数据,把风险锁在前两级环境。
- 开发环境PITR恢复:当某次尝试在开发环境“玩砸”时,可以利用火山 Supabase 的PITR恢复能力,将开发分支回滚到指定时间。
在 Branch 机制之上,前文提到的 全链路 Serverless 弹性、数据库即 API(PostgREST)、RLS 多租户隔离、Realtime 实时推送 与 pgvector 向量检索 会以“整套能力”挂载在每一个分支之上。
这意味着:你可以在 Dev / Staging 分支上放心压测 Realtime 推送、调参数、改 Schema,再把稳定的变更以“仅同步 Schema”的方式迁移到 Prod分支,为 Agent、全栈应用和多人协作场景提供一个安全可控的迭代闭环。
给 Agent 开发者的快速起步清单
通过这些步骤,我们为 Agent 构建了一个功能完备、安全且实时的后端,而这一切几乎没有编写传统的后端服务代码。那么,准备好在你的下一个 Agent 或全栈项目中使用火山 Supabase 了吗?
这里有一份快速上手清单:
- 访问火山引擎官网:搜索“火山 Supabase”并创建一个新项目。
- 获取 API 凭证:在控制台的“连接”页面中,找到你的 Project URL 和 anon_key。
- 安装 supabase-js:在你的前端或 Node.js 项目中运行 npm install @supabase/supabase-js。
- 初始化客户端:使用获取的凭证创建 Supabase 客户端实例。
- 设计数据表:使用仪表盘的 Table Editor 或 SQL Editor 创建你的表结构。
- 开启 RLS:为你需要保护的每一张表启用行级安全,并至少为授权用户添加一条 SELECT 策略,否则 API 将无法读取任何数据。
- 开始编码:利用 select, insert, rpc 等方法,尽情享受无需后端编码的全栈开发体验吧!
结语:火山 Supabase,释放 Vibe Coding 的高效创造力
技术的终极价值在于降低创新的门槛,火山引擎 Supabase 融合了开源的灵活性与字节跳动的企业级技术可靠性,将复杂的后端能力转化为普惠的工具,助力开发者在诸如扣子、豆包、TRAE 这样高效的 Vibe Coding 中,跳出基建内耗的循环。无论是初创团队快速验证 MVP,还是大型企业构建稳定业务,都能以更低的成本、更高的效率和更强的安全保障,让每一个好想法,一键变为现实。
已关注
关注
重播 分享 赞
关闭
观看更多
更多
退出全屏
切换到竖屏全屏退出全屏
字节跳动技术团队已关注
分享视频
,时长01:40
0/0
00:00/01:40
切换到横屏模式
继续播放
[ ]
进度条,百分之0
播放
00:00
/
01:40
01:40
倍速
全屏
倍速播放中
0.5倍 0.75倍 1.0倍 1.5倍 2.0倍
超清 流畅
继续观看
Vibe Coding 一键部署——火山引擎推出 Supabase, 驱动Agent 应用快速上线
观看更多
转载
,
Vibe Coding 一键部署——火山引擎推出 Supabase, 驱动Agent 应用快速上线
字节跳动技术团队已关注
分享点赞在看
已同步到看一看写下你的评论
视频详情
目前,火山 Supabase 已正式上线火山引擎官网。欢迎试用产品或查阅技术文档,开启你的高效Vibe Coding之旅。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:字节跳动技术团队 火山引擎数据库 火山引擎数据库《Vibe Coding 一键部署——火山引擎推出 Supabase, 驱动Agent 应用快速上线》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论