DeepAgents 部署内容创作 Agent:基于 Supabase 自定义认证实现按用户隔离的记忆系统
【免费下载链接】deepagentsThe batteries-included agent harness.项目地址: https://gitcode.com/GitHub_Trending/de/deepagents
导读
deepagents deploy是 DeepAgents 提供的将 Agent 打包部署到 LangSmith 云平台的官方流程。本文以仓库中的 deploy-content-writer 示例 为骨架,完整讲解如何部署一个能写博客、LinkedIn 帖子和推文的 AI 内容创作 Agent,并重点剖析它的两个核心特性:按用户身份隔离的持久化记忆(per-user memory)与零自定义代码的 Supabase 认证集成。读完本文,你将掌握从环境配置、deepagents deploy部署到通过 LangGraph SDK 携带 JWT 调用的完整链路,并理解记忆文件如何在多用户场景下做到零串号。
示例整体架构
deploy-content-writer是一个"开箱即用"的内容创作 Agent 部署示例,其目录结构如下:
examples/deploy-content-writer/ ├── AGENTS.md # Agent 指令与记忆工作流定义 ├── agent.json # Agent 名称与运行时模型配置 ├── deepagents.toml # 部署配置(模型、认证)——README 所述,随部署生成 ├── skills/ │ ├── blog-post/ # 长文博客写作技能 │ └── social-media/ # LinkedIn 与推文写作技能 ├── user/ │ └── AGENTS.md # 用户偏好模板(preferences.md 的初始内容) └── test_user_memory.py # 跨会话记忆持久化的端到端验证脚本各文件的职责在 README 的 Structure 一节中有明确对应:
- AGENTS.md 定义了 Agent 的"人格"与工作流:品牌语调(专业但平易近人)、写作标准(主动语态、以价值开头、每段一个观点、以行动结尾)、内容支柱(AI Agent 与自动化、开发者工具、软件架构、新兴技术),以及最重要的用户记忆使用规则。
- agent.json 声明了 Agent 的运行时元数据:名称为
deepagents-deploy-content-writer,模型为openai:gpt-4.1。 deepagents.toml是部署时的核心配置,本文主角之一,其中[auth]段决定是否启用 Supabase 认证。skills/下的两个技能文件是可被 Agent 按需调用的"能力单元",详见后文。
前置条件与环境变量
部署前需要准备以下环境变量:
| 变量 | 用途 |
|---|---|
OPENAI_API_KEY | GPT-4.1 模型访问凭证 |
LANGSMITH_API_KEY | 部署到 LangSmith 平台的必需凭证 |
SUPABASE_URL | Supabase 项目 URL(仅认证场景需要) |
SUPABASE_ANON_KEY | Supabase anon/public 密钥(仅认证场景需要) |
配置步骤:将.env.example复制为.env并填入对应密钥。README 特别强调:
Supabase 密钥只有在
deepagents.toml中保留[auth]段时才需要;删除该段即可部署为无认证模式。
也就是说,认证是可插拔的——这正体现了 DeepAgents 部署链路中配置即声明(declarative configuration)的设计思路。
部署:一行命令完成认证接线
在项目根目录执行:
deepagents deployREADME 明确描述了部署时的自动行为:
部署时,
deepagents.toml中的[auth]段会自动生成一个 Supabase token validator,并将其接入部署,无需任何自定义中间件。
这背后的含义是:[auth]配置声明了"本部署使用 Supabase 身份体系",deepagents deploy在打包阶段据此自动完成 JWT 校验器的生成与装配。开发者无需编写一行认证代码,也无需手动注册中间件,从而把"多租户认证"这种常见但繁琐的工作从业务代码中剥离。
对部署链路感兴趣的读者,可以对比同一仓库中另一个部署示例 deploy-coding-agent,后者同样是deepagents deploy一行部署,展示了该流程在不同 Agent 类型(编码 Agent vs 内容创作 Agent)间的通用性。
按用户隔离的记忆系统(Per-User Memory)
记忆文件的组织方式
每个通过认证的用户都会获得自己独立的记忆文件,统一存放在/memories/user/下:
| 文件 | 读写权限 | 用途 |
|---|---|---|
preferences.md | 读/写 | Agent 读取并更新,用于记录用户的语调、主题与排版偏好 |
context.md | 只读 | 关于用户公司与产品的静态上下文 |
由于认证将这两类文件按用户身份(user identity)进行作用域隔离,一份部署可以同时服务多个用户,且账户之间零数据串扰。
Agent 侧的记忆读写规则
AGENTS.md 的User Memory一节给出了 Agent 使用记忆的明确协议:
- 会话开始时用
ls /memories/user/发现可用文件; - 每次对话开始前必须读取记忆文件,以便个性化输出;
- 当用户分享偏好时,用
edit_file更新/memories/user/preferences.md; context.md为只读,仅在创作内容时引用。
这一"先读记忆、再产出内容、持续回写偏好"的闭环,使得 Agent 能够跨会话记住"用户喜欢更随意的语气"这类偏好,并在后续的博客、LinkedIn、推文创作中持续生效。
user/AGENTS.md则提供了preferences.md的初始模板("尚未设置偏好,Agent 将在学习用户偏好的过程中更新本文件"),部署时作为每个新用户记忆文件的起点。
记忆持久化的端到端验证
仓库中的 test_user_memory.py 是理解记忆隔离机制的最佳可运行证据。它通过 LangGraph SDK 依次执行四个测试场景:
- Thread 1(设置偏好):以
user_id="test-user-sydney"向 Agent 发送"我偏好简洁的要点式内容,请记住这一偏好"; - Thread 2(同用户跨会话持久化):新建线程,同一
user_id,询问"我的内容偏好是什么?读取你的记忆文件并告诉我"——验证记忆跨线程保留; - Thread 3(不同用户隔离):换用
user_id="other-user-xyz"问同样的问题——预期看不到Thread 1 设置的偏好,验证账户隔离; - Thread 4(无 user_id 容错):不传
user_id仅打招呼——预期优雅跳过用户记忆,不报错。
该脚本的关键实现细节展示了如何在 SDK 层注入用户身份:
config = {} if user_id: config = {"configurable": {"user_id": user_id}}即用户身份通过 run 的config.configurable.user_id传入;在启用 Supabase 认证的部署中,该身份由部署在服务端自动从 JWT 推断,而脚本直接传user_id的方式则适用于无认证的本地/自定义场景。脚本同时支持从环境变量或.env文件读取LANGSMITH_API_KEY,并会先调用client.assistants.search()自动发现部署后的 assistant_id。
自定义认证(Custom Auth)配置
配置声明
在deepagents.toml中加入以下配置段即可启用 Supabase 认证:
[auth] provider = "supabase"这正是 README 所强调的zero custom code:仅凭这一小节配置,部署时便会自动生成 Supabase token validator 并接入服务端,使得:
- 部署会自动校验每个请求携带的 Supabase JWT;
- 从 JWT 中推断用户身份;
- 该身份被用于
/memories/user/记忆文件的作用域隔离。
与记忆系统的联动
认证与记忆的联动是本文档最核心的架构点:没有认证,记忆文件无法安全地按用户划分;有了认证,一份部署即可安全服务多租户。若移除[auth]段(无认证部署),则所有请求共享同一套记忆空间,也就失去了账户隔离能力——这也解释了为何 README 要求只在需要认证时配置 Supabase 密钥。
通过 LangGraph SDK 查询与流式调用
携带 JWT 发起请求
部署完成后,在 LangSmith 的Deployments页面可以找到部署 URL。调用方需在 HTTP 请求的Authorization头中携带 Supabase JWT,部署端会自动校验并推断用户身份:
from langgraph_sdk import get_client client = get_client( url="https://<your-deployment-url>", headers={"Authorization": "Bearer <your-supabase-jwt>"}, ) thread = await client.threads.create() async for chunk in client.runs.stream( thread["thread_id"], "agent", input={"messages": [{"role": "user", "content": "Write a tweet about AI agents"}]}, stream_mode="messages", ): print(chunk.data, end="", flush=True)要点拆解:
get_client(url=..., headers=...):在客户端统一注入认证头,后续所有请求自动携带;threads.create():创建会话线程;runs.stream(thread_id, "agent", input=..., stream_mode="messages"):以消息流模式流式获取 Agent 输出,"agent"是默认的 assistant 名称;stream_mode="messages"逐 token 输出,适合聊天式 UI 渲染。
更多调用示例
test_user_memory.py 中的run_thread函数给出了另一种流式模式stream_mode="values"(按状态快照流式返回,可获取每轮的完整消息列表),并演示了如何从事件数据中解析最终的 AI 文本(兼容纯文本与 tool-use 块两种内容结构)。两种模式各有适用场景:messages偏实时聊天流,values偏结构化状态观测。
技能体系:博客与社媒写作能力单元
示例将写作能力拆分为两个可复用的技能(Skill),由 Agent 按任务类型按需调用:
blog-post(长文博客)
SKILL.md 定义的能力要点:
- 写作前强制研究:使用
task工具并指定subagent_type: "researcher",先委托研究子代理展开调研,再动笔; - 固定结构:Hook 开头(2-3 句的抓人问题/数据/陈述)→ 问题背景 → 主体(3-5 个 H2 小节,含代码示例与要点列表)→ 实战应用(分步说明)→ 结论与 CTA(最多 3 条要点);
- SEO 约束:主关键词进标题与首段、标题 60 字符内、meta description 150-160 字符;
- 输出路径:保存到
blogs/<slug>/post.md。
social-media(LinkedIn 与推文)
SKILL.md 覆盖三种格式:
| 格式 | 核心规范 |
|---|---|
| Twitter/X Thread | 钩子推 < 280 字符,3-7 条跟进推,末条 CTA,善用换行 |
| LinkedIn Post | 前 2 行即钩子("see more" 之前可见),3-5 短段,以提问收尾促互动,目标约 1,300 字符 |
| Short-form Update | 单段公告/洞察,可附长文链接,< 280 字符便于跨平台 |
通用准则还包括:LinkedIn 用第一人称、公司账号用第三人称;只加 2-3 个相关 hashtag;LinkedIn 偏专业、Twitter 偏口语化;每篇内容独立成立、拒绝"只吊胃口";用具体数字而非模糊宣称。输出统一保存到social/<platform>/<slug>.md。
技能与记忆的协作
结合 AGENTS.md 的四步工作流(研究 → 大纲 → 写作 → 对照质量清单复核),可以还原一次典型创作会话的完整链路:读取用户记忆 → 派 researcher 子代理调研 → 按所选技能的结构化模板创作 → 依据品牌语调与质量标准复核 → 将新学到的用户偏好回写preferences.md。技能管"怎么写",记忆管"为谁写",二者共同构成内容创作 Agent 的生产力闭环。
验证与运行前提说明
test_user_memory.py中的DEPLOY_URL指向一个具体的 LangSmith 部署实例,仅供示例参考;实际运行请替换为你在 LangSmithDeployments页面获取到的部署 URL。- 脚本要求安装
langgraph_sdk(示例的完整依赖与打包配置可参考仓库内其他示例的pyproject.toml),并具备有效的LANGSMITH_API_KEY。 - 本文涉及的命令与配置以当前仓库 examples/deploy-content-writer 的实际内容为准;
deepagents.toml与.env.example为 README 所述但未随仓库提交的部署期文件,实际部署时需按上文说明自行创建。
【免费下载链接】deepagentsThe batteries-included agent harness.项目地址: https://gitcode.com/GitHub_Trending/de/deepagents
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考