puppyone × LangChain:作为 Tool、Retriever、DocumentLoader 直接接入的真实工作空间

2026年4月23日puppyone team

TL;DR

  • LangChain 是组装 agent 的框架。 Chain、tool、retriever、memory 抽象、callback。它是抽象,不是基础设施。真正的持久状态住在哪,由你决定。
  • 默认情况下,"状态住哪"会落到三个糟糕选择之一: 一个进程退出就消失的内存 dict,一个你得自己运维的 vector DB,或者一张你自己维护的临时 Postgres 表。
  • puppyone 作为 drop-in Tool、Retriever、DocumentLoader 接入。 你的 agent 拿到 read_filewrite_filelist_directorysearch,背后是持久、版本化、按 agent 鉴权的文件工作空间。明天的运行能读到今天的运行写下的东西。其他 agent(Cursor、Claude Code、n8n、你其他 Python 服务)也都看得见。
  • 改的不是概念 —— LangChain 还是 LangChain。改的是你不再需要自己去搭那一层状态层

把 puppyone 接进 LangChain 之后变了什么

绝大多数 LangChain 项目都长一个样:

  1. 搭一个 agent。
  2. 给它几个 tool。
  3. 发现它跨运行没有真正的记忆。
  4. 加个东西 —— ConversationBufferMemory、一个 vector DB、一张自定义 Postgres 表、一文件夹 pickle。
  5. 发现这个东西现在又需要 scope、权限、版本历史、多 agent 可见性,还要让人能读。
  6. 现在你在维护基础设施,不是在做 agent。

puppyone 把第 4–6 步压缩成"注册一个 Tool / Retriever,用就行":

  • 持久文件工作空间,撑得过进程重启、部署、笔记本重启。
  • LangChain agent 能直接理解的 tool 表面read_filewrite_filelist_directorysearch。标准 BaseTool 形态。
  • RAG 用的 retriever 表面:跨工作空间的混合关键字 + 向量搜索,返回 LangChain 已经能消费的 Document
  • DocumentLoader 表面:把 Notion / Slack / Postgres / Gmail / GitHub issues 同步进 puppyone 的那些连接器,对你的 LangChain pipeline 来说就是免费的 DocumentLoader
  • per-agent Access Point。 研究链读 /research/。写作链写 /drafts/。审稿链读 /drafts//reviews/。没有任何 agent 看到超出它需要的范围。
  • 自动版本历史。 每次写都是 commit,带 author(哪条链)、时间戳、diff。Agent 跑飞了直接回滚,不影响其他东西。
  • 跨进程、跨语言可见性。 你 Python 的 LangChain agent 写一个文件;你 TypeScript 服务 / Cursor / Claude Code / n8n flow 都能读。

LangChain 继续做编排框架。puppyone 让你不用第五次重建持久化层。

完全不变的东西

  • 你已有的所有 chain、runnable、prompt、output parser。 我们不替换其中任何一个。
  • 你的模型 provider。 OpenAI、Anthropic、本地模型,LangChain 支持的都行 —— 不变。
  • 你已有的 tool。 puppyone 跟它们并列加进去,不替代。
  • LCEL。 把 puppyone 组合进 runnable,跟其他 tool / retriever 一样。
  • 你的 eval / tracing / LangSmith。 不变。puppyone 调用在 trace 里跟其他 tool call 一样出现。
  • 你已有的 vector DB(如果有的话)。puppyone 的 retriever 是补充,不是替代 —— 你的领域向量留在原地;puppyone 用来装文件形态、多源、不断变化的 context。

怎么接(短版)

  1. 起一个 puppyone 工作空间。 云端(try.puppyone.ai)或 Docker 自托管。
  2. 每条链 / 每种 agent 角色定义一个 Access Point。 读+写 /scratch/<agent>/,读 /specs,读 /integrations/,等等。
  3. 装 puppyone Python SDK(如果你跨语言再装 TypeScript SDK)。
  4. 把 puppyone Tool 注册进你的 agent
    • read_filewrite_filelist_directorysearchversion_history
    • 这些是标准 BaseTool 实例。跟其他 tool 一样加进 AgentExecutor / LCEL chain。
  5. RAG 用 puppyone Retriever:返回带 metadata 的 Document(路径、版本、来源连接器、最后由哪个 agent 改的)。
  6. 用 puppyone DocumentLoader 把已经同步进来的 SaaS 数据接进 pipeline —— NotionLoaderSlackLoaderPostgresLoader 等等,背后是 puppyone 的连接器,你不用自己写集成代码。

真正变好的工作流

1. 长跑研究 / 计划 agent

没 puppyone: 研究 agent 把发现拼成内存里的字符串。进程退出。除非你写了自定义 serializer,发现就没了。

有 puppyone: Agent 的 tool spec 里有 write_file。它把发现写到 /research/<topic>/<date>.md。明天的 agent 读这个目录,接着干。完整版本历史。其他 agent(review、summarisation)读同一份文件。

2. 多步 plan-and-execute

没 puppyone: "Plan" 链产出一个计划。"Execute" 链拿过去。你把 plan serialize 进 conversation buffer 或者你自己写的 JSON 文件。

有 puppyone: Plan 链写 /plans/<run-id>.md。Execute 链读它。Reviewer 链读 /plans/<run-id>.md/executions/<run-id>.md。每条链有自己的 Access Point。"plan 格式"就是"一个 markdown 文件" —— 人也能读、也能改。

3. 多 agent crew / 编排

没 puppyone: 你 crew 里的每个 agent 有自己的 memory。在它们之间协调 context 意味着通过 orchestrator 传消息,orchestrator 变瓶颈。

有 puppyone: Agent 共享一个工作空间。Researcher 写 /research/。Writer 读 /research//drafts/。Reviewer 读 /drafts//reviews/。Orchestrator 只负责 route;状态住在所有 agent 都能看到的文件里。

4. 多源 RAG

没 puppyone: 你起一个 vector DB,给每个源(Notion、Slack、Postgres、GitHub issues)写 loader,维护 ingestion pipeline,去重,同步。

有 puppyone: 连接器把源同步进工作空间。puppyone Retriever 跨它们做混合搜索。DocumentLoader 返回带 provenance 的 Document(哪个源、哪个路径、哪个版本)。你的 RAG 链不在乎一些来自 Notion 一些来自 Slack —— 它就是检索文件。

5. Human-in-the-loop,无需独立 UI

没 puppyone: Agent 产出一个东西,你建一个独立 UI 让人 review、edit,把改动 serialize 回 agent 的 memory。

有 puppyone: Agent 写到 /drafts/。人打开 puppyone(或者任何能跟它对话的文本编辑器)改。下一个 agent 读改过的版本。"Review UI"就是"一文件夹文件"。

6. 跨语言 agent 栈

没 puppyone: 你 Python LangChain agent 和你 TypeScript LangChain.js agent 各有自己的 memory。共享需要一个共享 DB,schema 你自己维护。

有 puppyone: 两边都连同一个工作空间。两边读写同样的文件。Schema 就是"目录树里的文件"。零协调代码。

该避免的模式

  • 别把每步 scratch 都塞 puppyone。 没人需要看到的中间 RunnableLambda 输出留在内存里就行。puppyone 用来放你以后会读、会被另一次运行、另一个 agent、或一个人读的状态。
  • 别为了高 QPS 检索而拿 puppyone 替换你领域 vector DB。 你有 1000 万文档的产品目录、需要毫秒级 p99 检索,那还是专门 vector DB 的活。puppyone 的 retriever 适合多源、不断变化、文件形态的 context —— 不是给商品搜索引擎当后端的。
  • 别让所有 agent 共用一个 Access Point。 一张过宽的 token 把 per-agent 鉴权全废了。每个分开。
  • 别让一个 agent 的写覆盖另一个 agent 的 canonical 文件。 让 agent 写到 scratch 路径;通过 review(人工或另一条链)才提升进 canonical 路径。
  • 别忘了 git 形态。 puppyone 给你 commit 和 rollback。用上 —— 尤其是偶尔会做出夸张操作的 agent。

这跟你栈里其他东西怎么配

  • LangChain 编排。Tool、chain、prompt、output parsing —— 你的活。
  • puppyone 持久化。工作空间文件、版本历史、per-agent 权限、连接器同步 —— 它的活。
  • Cursor / Claude Code 通过 MCP 看到同一个工作空间,你 LangChain agent 写的东西在编辑器里实时出现。见 puppyone for Cursorpuppyone for Claude Code
  • n8n(或任何 workflow 工具)通过 REST 读写同一个工作空间。见 puppyone for n8n
  • Postgres / Pinecone / S3 留在你栈里。你 LangChain 链该跟它们说话的地方继续说话。边界见 puppyone vs Postgrespuppyone vs Pinecone

LangChain 还是你拿来用的框架。puppyone 让你不用再重建底下那层无聊的基础设施。

FAQ

这是 LangChain 官方集成吗? 我们提供 Python 和 TypeScript SDK,里面有遵循 LangChain 标准接口的 BaseToolBaseRetrieverBaseLoader 实现。直接放进你已有的链就行。

puppyone 替代 ConversationBufferMemory / chat memory 吗? 长跑、多 session 的 agent —— 是,你会想要 puppyone 后端的 memory,让它撑过进程重启。请求结束就不用活的 5 轮 chat,内存版的够了。

puppyone 替代我的 vector DB 吗? 多源、不断变化、文件形态的 context(不然你得自己搭 loader 和 ingestion 管道)—— 是。高吞吐、单领域语义搜索索引 —— 不是,专门 vector DB 留着。

能跟 LangGraph 一起用吗? 能。图里每个节点都能通过同一个 Tool 读写 puppyone。跨 graph execution 的持久状态就成了工作空间的属性,不再是 graph runtime 的属性。

LangSmith / tracing 怎么处理? puppyone 调用在你 trace 里跟标准 tool call 一样显示 —— 文件路径、操作、延时、返回大小。无需特殊集成。

支持 LangChain.js 吗? 支持。一样的 SDK 形态、一样的 Access Point、一样的工作空间。Python agent 和 TypeScript agent 能透明共享一个工作空间。

多租户 SaaS 里每个客户有自己的 LangChain agent,权限怎么管? 每个租户拿自己的 puppyone 工作空间(或一个空间内独立 scope 的子树),每个 agent 有自己的 Access Point,存储层不会跨租户漏。你应用逻辑不用强制 tenancy —— 存储层就强制了。

只用 LCEL 不用老的 agent 抽象呢? 一样 —— 把 tool 注册成 RunnableLambda wrapper(或者用 SDK helper),组合进你的链就行。

再说一遍 TL;DR

LangChain 给你 agent。它不给你放状态的地方 —— 那是给用户做的练习题。puppyone 用 drop-in Tool、Retriever、DocumentLoader 把这个洞补上,你的 agent 不再忘事,你的团队不再维护临时凑出来的持久化层。同样的链。同样的 prompt。底下是真正的工作空间。

给你 LangChain agent 一份工作空间,而不是一个进程退出就死的 Python dict。Get started