[{"data":1,"prerenderedAt":2314},["ShallowReactive",2],{"docs-page-cn-/cn/usecase/memmy_knowledge_base":3,"surround-cn-/cn/usecase/memmy_knowledge_base":2298},{"id":4,"title":5,"avatar":6,"banner":6,"body":7,"category":6,"desc":2291,"description":13,"extension":2292,"lead":6,"links":6,"meta":2293,"navigation":6,"path":2294,"seo":2295,"stem":2296,"__hash__":2297},"docs/cn/usecase/memmy_knowledge_base.md","在 Memmy 中集成 MemOS 知识库",null,{"type":8,"value":9,"toc":2279},"minimark",[10,14,17,20,23,27,30,65,72,74,77,80,106,109,268,271,417,420,638,645,788,790,793,796,799,1002,1005,1007,1010,1013,1324,1330,1345,1348,1350,1354,1357,1470,1473,1476,1479,1482,1491,1494,1504,1898,1901,1916,1919,1925,1927,1929,1932,1943,1949,1952,2024,2027,2029,2032,2035,2248,2264,2266,2269,2272,2275],[11,12,13],"p",{},"Memmy 是一款桌面端 Agent 应用，让用户的工作在 DeepSeek Harness、Claude Code、Codex 等 Agent 之间延续。用户希望 Agent 回答时参考自己的资料，例如产品手册、项目文档和调研报告。Memmy 知识库为此而建：用户创建知识库、上传文件，再选择哪些知识库参与对话；Agent 回答前自动检索，并在回答中标注资料来源。",[11,15,16],{},"这项能力完全基于 MemOS 知识库接口实现。与一个服务端直接调用 MemOS 不同，Memmy 运行在大量终端用户自己的电脑上，用户之间还会互相共享资料。这些前提决定了它的接入方式。",[11,18,19],{},"本文以一个产品团队的使用场景为线索，依次说明创建、上传、检索、共享、删除每一步 Memmy 怎么做、为什么这样做。文中代码是示意，用于说明应用服务端如何调用 MemOS 公开接口，不能直接运行。",[21,22],"br",{},[24,25,26],"h2",{"id":26},"使用场景",[11,28,29],{},"以产品团队为例，一次完整的使用过程如下：",[31,32,33,41,47,53,59],"ol",{},[34,35,36,40],"li",{},[37,38,39],"strong",{},"建库","：产品经理在 Memmy 中创建一个知识库，上传《MemOS产品介绍.md》和《MemOS 开源VS商业化.md》。两份文件的状态从「处理中」变为「可用」。",[34,42,43,46],{},[37,44,45],{},"共享","：产品经理在「共享管理」中输入销售同事的手机号，把这个知识库共享出去。",[34,48,49,52],{},[37,50,51],{},"提问","：销售同事在 Memmy 中问「MemOS 开源版和商业版有什么区别」。Agent 回答前自动检索，回答中引用《MemOS 开源VS商业化》并注明出处。",[34,54,55,58],{},[37,56,57],{},"更新","：产品经理又上传了一份新资料。销售同事无需任何操作，下一次提问即可检索到新内容。",[34,60,61,64],{},[37,62,63],{},"撤销","：销售同事转岗后，产品经理撤销共享。销售同事之后的提问不再检索这个知识库。",[11,66,67],{},[68,69],"img",{"alt":70,"src":71},"Memmy 知识库页面","https://cdn.memtensor.com.cn/img/1792586352599_qmi1ct_compressed.png",[21,73],{},[24,75,76],{"id":76},"整体架构",[11,78,79],{},"Memmy 由桌面端和 Memmy 云服务两部分组成。作为面向终端用户的桌面产品，它接入 MemOS 时需要满足四项约束：",[31,81,82,88,94,100],{},[34,83,84,87],{},[37,85,86],{},"API Key 不能下发","：桌面端安装在用户自己的电脑上，写进安装包或本地配置的 API Key 等同于公开。因此 API Key 只放在 Memmy 云服务，桌面端使用用户的 Memmy 登录凭据访问云服务。",[34,89,90,93],{},[37,91,92],{},"归属需要应用判断","：MemOS 知识库归属于开发者项目，并不识别 Memmy 的终端用户。Memmy 为所有用户使用同一个 MemOS 项目，哪个用户拥有、能看到哪个知识库，由云服务在每次调用 MemOS 前判断。",[34,95,96,99],{},[37,97,98],{},"设置需要跟随账号","：同一账号可能在多台电脑上登录，每个知识库的「参与召回」设置保存在云服务。",[34,101,102,105],{},[37,103,104],{},"Agent 不接触凭据","：Agent 在运行中会调用工具、读取本地文件。知识库 Hook 只使用本机服务的访问令牌，检索链路不向 Agent 传递任何云端凭据。",[11,107,108],{},"由此形成三层结构：桌面端只与 Memmy 云服务通信，由云服务代表用户调用 MemOS。",[110,111,116],"pre",{"className":112,"code":113,"language":114,"meta":115,"style":115},"language-mermaid shiki shiki-themes material-theme-lighter github-light-high-contrast github-dark-default","flowchart LR\n    subgraph Desktop[\"Memmy 桌面端\"]\n        direction TB\n        Page[\"知识库页面\"]\n        Hook[\"知识库 Hook\"]\n        Local[\"本机服务\"]\n        Page --> Local\n        Hook --> Local\n    end\n    subgraph Service[\"Memmy 云服务\"]\n        direction TB\n        Auth[\"识别登录用户\"]\n        Biz[\"归属 · 共享 · 召回设置\"]\n        Scope[\"转换知识库 ID\u003Cbr/>计算召回范围\"]\n        Auth --> Biz --> Scope\n    end\n    subgraph Cloud[\"MemOS\"]\n        direction TB\n        Store[\"知识库与文件\"]\n        Index[\"解析 · 分段 · 索引\"]\n        Search[\"知识检索\"]\n        Store --> Index --> Search\n    end\n    Desktop -->|Memmy 登录凭据| Service\n    Service -->|MemOS API Key| Cloud\n","mermaid","",[117,118,119,128,134,140,146,152,158,164,170,176,182,187,193,199,205,211,216,222,227,233,239,245,251,256,262],"code",{"__ignoreMap":115},[120,121,124],"span",{"class":122,"line":123},"line",1,[120,125,127],{"class":126},"s5ojA","flowchart LR\n",[120,129,131],{"class":122,"line":130},2,[120,132,133],{"class":126},"    subgraph Desktop[\"Memmy 桌面端\"]\n",[120,135,137],{"class":122,"line":136},3,[120,138,139],{"class":126},"        direction TB\n",[120,141,143],{"class":122,"line":142},4,[120,144,145],{"class":126},"        Page[\"知识库页面\"]\n",[120,147,149],{"class":122,"line":148},5,[120,150,151],{"class":126},"        Hook[\"知识库 Hook\"]\n",[120,153,155],{"class":122,"line":154},6,[120,156,157],{"class":126},"        Local[\"本机服务\"]\n",[120,159,161],{"class":122,"line":160},7,[120,162,163],{"class":126},"        Page --> Local\n",[120,165,167],{"class":122,"line":166},8,[120,168,169],{"class":126},"        Hook --> Local\n",[120,171,173],{"class":122,"line":172},9,[120,174,175],{"class":126},"    end\n",[120,177,179],{"class":122,"line":178},10,[120,180,181],{"class":126},"    subgraph Service[\"Memmy 云服务\"]\n",[120,183,185],{"class":122,"line":184},11,[120,186,139],{"class":126},[120,188,190],{"class":122,"line":189},12,[120,191,192],{"class":126},"        Auth[\"识别登录用户\"]\n",[120,194,196],{"class":122,"line":195},13,[120,197,198],{"class":126},"        Biz[\"归属 · 共享 · 召回设置\"]\n",[120,200,202],{"class":122,"line":201},14,[120,203,204],{"class":126},"        Scope[\"转换知识库 ID\u003Cbr/>计算召回范围\"]\n",[120,206,208],{"class":122,"line":207},15,[120,209,210],{"class":126},"        Auth --> Biz --> Scope\n",[120,212,214],{"class":122,"line":213},16,[120,215,175],{"class":126},[120,217,219],{"class":122,"line":218},17,[120,220,221],{"class":126},"    subgraph Cloud[\"MemOS\"]\n",[120,223,225],{"class":122,"line":224},18,[120,226,139],{"class":126},[120,228,230],{"class":122,"line":229},19,[120,231,232],{"class":126},"        Store[\"知识库与文件\"]\n",[120,234,236],{"class":122,"line":235},20,[120,237,238],{"class":126},"        Index[\"解析 · 分段 · 索引\"]\n",[120,240,242],{"class":122,"line":241},21,[120,243,244],{"class":126},"        Search[\"知识检索\"]\n",[120,246,248],{"class":122,"line":247},22,[120,249,250],{"class":126},"        Store --> Index --> Search\n",[120,252,254],{"class":122,"line":253},23,[120,255,175],{"class":126},[120,257,259],{"class":122,"line":258},24,[120,260,261],{"class":126},"    Desktop -->|Memmy 登录凭据| Service\n",[120,263,265],{"class":122,"line":264},25,[120,266,267],{"class":126},"    Service -->|MemOS API Key| Cloud\n",[11,269,270],{},"落到具体功能上，Memmy 云服务与 MemOS 的分工如下。没有对应接口的功能，完全由 Memmy 云服务在应用层实现：",[272,273,274,293],"table",{},[275,276,277],"thead",{},[278,279,280,284,287,290],"tr",{},[281,282,283],"th",{},"Memmy 功能",[281,285,286],{},"Memmy 云服务负责",[281,288,289],{},"MemOS 负责",[281,291,292],{},"MemOS 接口",[294,295,296,312,328,344,357,369,385,397],"tbody",{},[278,297,298,302,305,307],{},[299,300,301],"td",{},"创建知识库",[299,303,304],{},"保存 Memmy 与 MemOS 知识库 ID 的对应关系",[299,306,301],{},[299,308,309],{},[117,310,311],{},"/create/knowledgebase",[278,313,314,317,320,323],{},[299,315,316],{},"上传文件",[299,318,319],{},"确认拥有者，转换知识库 ID",[299,321,322],{},"存储文件，异步完成解析、分段与索引",[299,324,325],{},[117,326,327],{},"/add/knowledgebase-file",[278,329,330,333,336,339],{},[299,331,332],{},"文件列表与处理状态",[299,334,335],{},"按文件夹筛选",[299,337,338],{},"返回文件信息与处理状态",[299,340,341],{},[117,342,343],{},"/get/knowledgebase-file",[278,345,346,349,352,355],{},[299,347,348],{},"重命名、文件夹",[299,350,351],{},"保存名称与目录结构",[299,353,354],{},"—",[299,356,354],{},[278,358,359,362,365,367],{},[299,360,361],{},"参与召回",[299,363,364],{},"保存每位用户对每个知识库的开关",[299,366,354],{},[299,368,354],{},[278,370,371,374,377,380],{},[299,372,373],{},"Agent 回答前检索",[299,375,376],{},"计算召回范围，复核检索结果",[299,378,379],{},"在指定知识库中检索",[299,381,382],{},[117,383,384],{},"/search/memory",[278,386,387,390,393,395],{},[299,388,389],{},"共享知识库",[299,391,392],{},"维护成员关系",[299,394,354],{},[299,396,354],{},[278,398,399,402,405,408],{},[299,400,401],{},"删除知识库或文件",[299,403,404],{},"先在应用侧删除",[299,406,407],{},"后台清理知识库与文件",[299,409,410,413,414],{},[117,411,412],{},"/delete/knowledgebase","、",[117,415,416],{},"/delete/knowledgebase-file",[11,418,419],{},"云服务对 MemOS 的所有调用都经过同一个入口，API Key 只在这里出现：",[110,421,425],{"className":422,"code":423,"language":424,"meta":115,"style":115},"language-python shiki shiki-themes material-theme-lighter github-light-high-contrast github-dark-default","MEMOS_BASE_URL = \"https://memos.memtensor.cn/api/openmem/v1\"\nMEMOS_API_KEY = os.environ[\"MEMOS_API_KEY\"]  # 只配置在云服务，不下发给桌面端\n\n\ndef memos_post(path, body):\n    resp = requests.post(\n        MEMOS_BASE_URL + path,\n        headers={\"Authorization\": f\"Token {MEMOS_API_KEY}\"},\n        json=body,\n    )\n    return resp.json()[\"data\"]\n","python",[117,426,427,448,483,489,493,519,539,554,594,606,611],{"__ignoreMap":115},[120,428,429,433,437,441,445],{"class":122,"line":123},[120,430,432],{"class":431},"sZaqd","MEMOS_BASE_URL",[120,434,436],{"class":435},"saN0X"," =",[120,438,440],{"class":439},"sjUum"," \"",[120,442,444],{"class":443},"sp1uZ","https://memos.memtensor.cn/api/openmem/v1",[120,446,447],{"class":439},"\"\n",[120,449,450,453,455,458,462,466,469,472,474,476,479],{"class":122,"line":130},[120,451,452],{"class":431},"MEMOS_API_KEY",[120,454,436],{"class":435},[120,456,457],{"class":126}," os",[120,459,461],{"class":460},"suWxN",".",[120,463,465],{"class":464},"s5qkx","environ",[120,467,468],{"class":460},"[",[120,470,471],{"class":439},"\"",[120,473,452],{"class":443},[120,475,471],{"class":439},[120,477,478],{"class":460},"]",[120,480,482],{"class":481},"sfVK4","  # 只配置在云服务，不下发给桌面端\n",[120,484,485],{"class":122,"line":136},[120,486,488],{"emptyLinePlaceholder":487},true,"\n",[120,490,491],{"class":122,"line":142},[120,492,488],{"emptyLinePlaceholder":487},[120,494,495,499,503,506,510,513,516],{"class":122,"line":148},[120,496,498],{"class":497},"sZ6T4","def",[120,500,502],{"class":501},"sbcIq"," memos_post",[120,504,505],{"class":460},"(",[120,507,509],{"class":508},"sM07a","path",[120,511,512],{"class":460},",",[120,514,515],{"class":508}," body",[120,517,518],{"class":460},"):\n",[120,520,521,524,527,530,532,536],{"class":122,"line":154},[120,522,523],{"class":126},"    resp ",[120,525,526],{"class":435},"=",[120,528,529],{"class":126}," requests",[120,531,461],{"class":460},[120,533,535],{"class":534},"sa-2m","post",[120,537,538],{"class":460},"(\n",[120,540,541,545,548,551],{"class":122,"line":160},[120,542,544],{"class":543},"svxCd","        MEMOS_BASE_URL",[120,546,547],{"class":435}," +",[120,549,550],{"class":534}," path",[120,552,553],{"class":460},",\n",[120,555,556,560,562,565,567,570,572,575,578,581,584,586,589,591],{"class":122,"line":166},[120,557,559],{"class":558},"sp4zP","        headers",[120,561,526],{"class":435},[120,563,564],{"class":460},"{",[120,566,471],{"class":439},[120,568,569],{"class":443},"Authorization",[120,571,471],{"class":439},[120,573,574],{"class":460},":",[120,576,577],{"class":497}," f",[120,579,580],{"class":443},"\"Token ",[120,582,564],{"class":583},"scyET",[120,585,452],{"class":543},[120,587,588],{"class":583},"}",[120,590,471],{"class":443},[120,592,593],{"class":460},"},\n",[120,595,596,599,601,604],{"class":122,"line":172},[120,597,598],{"class":558},"        json",[120,600,526],{"class":435},[120,602,603],{"class":534},"body",[120,605,553],{"class":460},[120,607,608],{"class":122,"line":178},[120,609,610],{"class":460},"    )\n",[120,612,613,617,620,622,625,628,630,633,635],{"class":122,"line":184},[120,614,616],{"class":615},"sBMTB","    return",[120,618,619],{"class":126}," resp",[120,621,461],{"class":460},[120,623,624],{"class":534},"json",[120,626,627],{"class":460},"()[",[120,629,471],{"class":439},[120,631,632],{"class":443},"data",[120,634,471],{"class":439},[120,636,637],{"class":460},"]\n",[11,639,640,641,644],{},"后文示例都通过 ",[117,642,643],{},"memos_post"," 调用 MemOS。Memmy 云服务自己保存的数据如下，示例用字典表示，实际可换成数据库；目录结构类似，示例中省略：",[110,646,648],{"className":422,"code":647,"language":424,"meta":115,"style":115},"knowledge_bases = {}  # Memmy 知识库 ID -> {\"memos_kb_id\", \"owner_id\", \"name\"}\nmembers = {}          # Memmy 知识库 ID -> 被共享的用户 ID 集合\nrecall_selected = {}  # (用户 ID, Memmy 知识库 ID) -> 是否参与召回\n\n\ndef can_access(user_id, kb_id):\n    # 拥有者，或被共享的用户\n    owner_id = knowledge_bases[kb_id][\"owner_id\"]\n    return user_id == owner_id or user_id in members.get(kb_id, set())\n",[117,649,650,663,675,687,691,695,714,719,746],{"__ignoreMap":115},[120,651,652,655,657,660],{"class":122,"line":123},[120,653,654],{"class":126},"knowledge_bases ",[120,656,526],{"class":435},[120,658,659],{"class":460}," {}",[120,661,662],{"class":481},"  # Memmy 知识库 ID -> {\"memos_kb_id\", \"owner_id\", \"name\"}\n",[120,664,665,668,670,672],{"class":122,"line":130},[120,666,667],{"class":126},"members ",[120,669,526],{"class":435},[120,671,659],{"class":460},[120,673,674],{"class":481},"          # Memmy 知识库 ID -> 被共享的用户 ID 集合\n",[120,676,677,680,682,684],{"class":122,"line":136},[120,678,679],{"class":126},"recall_selected ",[120,681,526],{"class":435},[120,683,659],{"class":460},[120,685,686],{"class":481},"  # (用户 ID, Memmy 知识库 ID) -> 是否参与召回\n",[120,688,689],{"class":122,"line":142},[120,690,488],{"emptyLinePlaceholder":487},[120,692,693],{"class":122,"line":148},[120,694,488],{"emptyLinePlaceholder":487},[120,696,697,699,702,704,707,709,712],{"class":122,"line":154},[120,698,498],{"class":497},[120,700,701],{"class":501}," can_access",[120,703,505],{"class":460},[120,705,706],{"class":508},"user_id",[120,708,512],{"class":460},[120,710,711],{"class":508}," kb_id",[120,713,518],{"class":460},[120,715,716],{"class":122,"line":160},[120,717,718],{"class":481},"    # 拥有者，或被共享的用户\n",[120,720,721,724,726,729,731,734,737,739,742,744],{"class":122,"line":166},[120,722,723],{"class":126},"    owner_id ",[120,725,526],{"class":435},[120,727,728],{"class":126}," knowledge_bases",[120,730,468],{"class":460},[120,732,733],{"class":126},"kb_id",[120,735,736],{"class":460},"][",[120,738,471],{"class":439},[120,740,741],{"class":443},"owner_id",[120,743,471],{"class":439},[120,745,637],{"class":460},[120,747,748,750,753,756,759,762,764,767,770,772,775,777,779,781,785],{"class":122,"line":172},[120,749,616],{"class":615},[120,751,752],{"class":126}," user_id ",[120,754,755],{"class":435},"==",[120,757,758],{"class":126}," owner_id ",[120,760,761],{"class":435},"or",[120,763,752],{"class":126},[120,765,766],{"class":435},"in",[120,768,769],{"class":126}," members",[120,771,461],{"class":460},[120,773,774],{"class":534},"get",[120,776,505],{"class":460},[120,778,733],{"class":534},[120,780,512],{"class":460},[120,782,784],{"class":783},"skqQ-"," set",[120,786,787],{"class":460},"())\n",[21,789],{},[24,791,792],{"id":792},"创建与上传",[794,795,301],"h3",{"id":301},[11,797,798],{},"用户提交名称后，云服务先在 MemOS 中创建知识库，再保存两个知识库 ID 的对应关系：",[110,800,802],{"className":422,"code":801,"language":424,"meta":115,"style":115},"def create_knowledge_base(owner_id, name):\n    data = memos_post(\"/create/knowledgebase\", {\"knowledgebase_name\": name})\n\n    kb_id = str(uuid.uuid4())  # Memmy 知识库 ID，返回给桌面端\n    knowledge_bases[kb_id] = {\n        \"memos_kb_id\": data[\"id\"],  # MemOS 知识库 ID，只留在云服务\n        \"owner_id\": owner_id,\n        \"name\": name,\n    }\n    recall_selected[(owner_id, kb_id)] = True  # 新建的知识库默认参与召回\n    return kb_id\n",[117,803,804,822,858,862,888,904,934,949,964,969,995],{"__ignoreMap":115},[120,805,806,808,811,813,815,817,820],{"class":122,"line":123},[120,807,498],{"class":497},[120,809,810],{"class":501}," create_knowledge_base",[120,812,505],{"class":460},[120,814,741],{"class":508},[120,816,512],{"class":460},[120,818,819],{"class":508}," name",[120,821,518],{"class":460},[120,823,824,827,829,831,833,835,837,839,841,844,846,849,851,853,855],{"class":122,"line":130},[120,825,826],{"class":126},"    data ",[120,828,526],{"class":435},[120,830,502],{"class":534},[120,832,505],{"class":460},[120,834,471],{"class":439},[120,836,311],{"class":443},[120,838,471],{"class":439},[120,840,512],{"class":460},[120,842,843],{"class":460}," {",[120,845,471],{"class":439},[120,847,848],{"class":443},"knowledgebase_name",[120,850,471],{"class":439},[120,852,574],{"class":460},[120,854,819],{"class":534},[120,856,857],{"class":460},"})\n",[120,859,860],{"class":122,"line":136},[120,861,488],{"emptyLinePlaceholder":487},[120,863,864,867,869,872,874,877,879,882,885],{"class":122,"line":142},[120,865,866],{"class":126},"    kb_id ",[120,868,526],{"class":435},[120,870,871],{"class":783}," str",[120,873,505],{"class":460},[120,875,876],{"class":534},"uuid",[120,878,461],{"class":460},[120,880,881],{"class":534},"uuid4",[120,883,884],{"class":460},"())",[120,886,887],{"class":481},"  # Memmy 知识库 ID，返回给桌面端\n",[120,889,890,893,895,897,899,901],{"class":122,"line":148},[120,891,892],{"class":126},"    knowledge_bases",[120,894,468],{"class":460},[120,896,733],{"class":126},[120,898,478],{"class":460},[120,900,436],{"class":435},[120,902,903],{"class":460}," {\n",[120,905,906,909,912,914,916,919,921,923,926,928,931],{"class":122,"line":154},[120,907,908],{"class":439},"        \"",[120,910,911],{"class":443},"memos_kb_id",[120,913,471],{"class":439},[120,915,574],{"class":460},[120,917,918],{"class":126}," data",[120,920,468],{"class":460},[120,922,471],{"class":439},[120,924,925],{"class":443},"id",[120,927,471],{"class":439},[120,929,930],{"class":460},"],",[120,932,933],{"class":481},"  # MemOS 知识库 ID，只留在云服务\n",[120,935,936,938,940,942,944,947],{"class":122,"line":160},[120,937,908],{"class":439},[120,939,741],{"class":443},[120,941,471],{"class":439},[120,943,574],{"class":460},[120,945,946],{"class":126}," owner_id",[120,948,553],{"class":460},[120,950,951,953,956,958,960,962],{"class":122,"line":166},[120,952,908],{"class":439},[120,954,955],{"class":443},"name",[120,957,471],{"class":439},[120,959,574],{"class":460},[120,961,819],{"class":126},[120,963,553],{"class":460},[120,965,966],{"class":122,"line":172},[120,967,968],{"class":460},"    }\n",[120,970,971,974,977,979,981,983,986,988,992],{"class":122,"line":178},[120,972,973],{"class":126},"    recall_selected",[120,975,976],{"class":460},"[(",[120,978,741],{"class":126},[120,980,512],{"class":460},[120,982,711],{"class":126},[120,984,985],{"class":460},")]",[120,987,436],{"class":435},[120,989,991],{"class":990},"smHB8"," True",[120,993,994],{"class":481},"  # 新建的知识库默认参与召回\n",[120,996,997,999],{"class":122,"line":184},[120,998,616],{"class":615},[120,1000,1001],{"class":126}," kb_id\n",[11,1003,1004],{},"桌面端后续请求只携带 Memmy 知识库 ID，云服务不接受客户端传入的 MemOS 知识库 ID，MemOS 知识库 ID 因此无从被猜测或伪造。新建的知识库默认参与召回；重命名只修改 Memmy 中保存的名称，不调用 MemOS。",[21,1006],{},[794,1008,1009],{"id":1009},"上传与管理文件",[11,1011,1012],{},"上传前，桌面端与云服务按 MemOS 知识库的文档限制校验文件：格式为 PDF、DOCX、DOC、TXT、JSON、MD、XML 之一，单文件不超过 100 MB。云服务确认当前用户是拥有者后，把 Memmy 知识库 ID 转换为 MemOS 知识库 ID，再提交文件：",[110,1014,1016],{"className":422,"code":1015,"language":424,"meta":115,"style":115},"def upload_file(user_id, kb_id, filename, content):\n    kb = knowledge_bases[kb_id]\n    if kb[\"owner_id\"] != user_id:\n        raise PermissionError(\"只有拥有者可以上传文件\")\n\n    mime_type, _ = mimetypes.guess_type(filename)\n    encoded = base64.b64encode(content).decode(\"ascii\")\n    files = memos_post(\"/add/knowledgebase-file\", {\n        \"knowledgebase_id\": kb[\"memos_kb_id\"],  # 转换为 MemOS 知识库 ID\n        \"file\": [{\n            \"name\": filename,\n            \"content\": f\"data:{mime_type};base64,{encoded}\",\n        }],\n    })\n    return files[0][\"status\"]  # 通常为 running，表示 MemOS 正在处理\n",[117,1017,1018,1045,1060,1087,1107,1111,1138,1175,1196,1222,1236,1251,1287,1292,1297],{"__ignoreMap":115},[120,1019,1020,1022,1025,1027,1029,1031,1033,1035,1038,1040,1043],{"class":122,"line":123},[120,1021,498],{"class":497},[120,1023,1024],{"class":501}," upload_file",[120,1026,505],{"class":460},[120,1028,706],{"class":508},[120,1030,512],{"class":460},[120,1032,711],{"class":508},[120,1034,512],{"class":460},[120,1036,1037],{"class":508}," filename",[120,1039,512],{"class":460},[120,1041,1042],{"class":508}," content",[120,1044,518],{"class":460},[120,1046,1047,1050,1052,1054,1056,1058],{"class":122,"line":130},[120,1048,1049],{"class":126},"    kb ",[120,1051,526],{"class":435},[120,1053,728],{"class":126},[120,1055,468],{"class":460},[120,1057,733],{"class":126},[120,1059,637],{"class":460},[120,1061,1062,1065,1068,1070,1072,1074,1076,1078,1081,1084],{"class":122,"line":136},[120,1063,1064],{"class":615},"    if",[120,1066,1067],{"class":126}," kb",[120,1069,468],{"class":460},[120,1071,471],{"class":439},[120,1073,741],{"class":443},[120,1075,471],{"class":439},[120,1077,478],{"class":460},[120,1079,1080],{"class":435}," !=",[120,1082,1083],{"class":126}," user_id",[120,1085,1086],{"class":460},":\n",[120,1088,1089,1092,1095,1097,1099,1102,1104],{"class":122,"line":142},[120,1090,1091],{"class":615},"        raise",[120,1093,1094],{"class":783}," PermissionError",[120,1096,505],{"class":460},[120,1098,471],{"class":439},[120,1100,1101],{"class":443},"只有拥有者可以上传文件",[120,1103,471],{"class":439},[120,1105,1106],{"class":460},")\n",[120,1108,1109],{"class":122,"line":148},[120,1110,488],{"emptyLinePlaceholder":487},[120,1112,1113,1116,1118,1121,1123,1126,1128,1131,1133,1136],{"class":122,"line":154},[120,1114,1115],{"class":126},"    mime_type",[120,1117,512],{"class":460},[120,1119,1120],{"class":126}," _ ",[120,1122,526],{"class":435},[120,1124,1125],{"class":126}," mimetypes",[120,1127,461],{"class":460},[120,1129,1130],{"class":534},"guess_type",[120,1132,505],{"class":460},[120,1134,1135],{"class":534},"filename",[120,1137,1106],{"class":460},[120,1139,1140,1143,1145,1148,1150,1153,1155,1158,1161,1164,1166,1168,1171,1173],{"class":122,"line":160},[120,1141,1142],{"class":126},"    encoded ",[120,1144,526],{"class":435},[120,1146,1147],{"class":126}," base64",[120,1149,461],{"class":460},[120,1151,1152],{"class":534},"b64encode",[120,1154,505],{"class":460},[120,1156,1157],{"class":534},"content",[120,1159,1160],{"class":460},").",[120,1162,1163],{"class":534},"decode",[120,1165,505],{"class":460},[120,1167,471],{"class":439},[120,1169,1170],{"class":443},"ascii",[120,1172,471],{"class":439},[120,1174,1106],{"class":460},[120,1176,1177,1180,1182,1184,1186,1188,1190,1192,1194],{"class":122,"line":166},[120,1178,1179],{"class":126},"    files ",[120,1181,526],{"class":435},[120,1183,502],{"class":534},[120,1185,505],{"class":460},[120,1187,471],{"class":439},[120,1189,327],{"class":443},[120,1191,471],{"class":439},[120,1193,512],{"class":460},[120,1195,903],{"class":460},[120,1197,1198,1200,1203,1205,1207,1209,1211,1213,1215,1217,1219],{"class":122,"line":172},[120,1199,908],{"class":439},[120,1201,1202],{"class":443},"knowledgebase_id",[120,1204,471],{"class":439},[120,1206,574],{"class":460},[120,1208,1067],{"class":534},[120,1210,468],{"class":460},[120,1212,471],{"class":439},[120,1214,911],{"class":443},[120,1216,471],{"class":439},[120,1218,930],{"class":460},[120,1220,1221],{"class":481},"  # 转换为 MemOS 知识库 ID\n",[120,1223,1224,1226,1229,1231,1233],{"class":122,"line":178},[120,1225,908],{"class":439},[120,1227,1228],{"class":443},"file",[120,1230,471],{"class":439},[120,1232,574],{"class":460},[120,1234,1235],{"class":460}," [{\n",[120,1237,1238,1241,1243,1245,1247,1249],{"class":122,"line":184},[120,1239,1240],{"class":439},"            \"",[120,1242,955],{"class":443},[120,1244,471],{"class":439},[120,1246,574],{"class":460},[120,1248,1037],{"class":534},[120,1250,553],{"class":460},[120,1252,1253,1255,1257,1259,1261,1263,1266,1268,1271,1273,1276,1278,1281,1283,1285],{"class":122,"line":189},[120,1254,1240],{"class":439},[120,1256,1157],{"class":443},[120,1258,471],{"class":439},[120,1260,574],{"class":460},[120,1262,577],{"class":497},[120,1264,1265],{"class":443},"\"data:",[120,1267,564],{"class":583},[120,1269,1270],{"class":534},"mime_type",[120,1272,588],{"class":583},[120,1274,1275],{"class":443},";base64,",[120,1277,564],{"class":583},[120,1279,1280],{"class":534},"encoded",[120,1282,588],{"class":583},[120,1284,471],{"class":443},[120,1286,553],{"class":460},[120,1288,1289],{"class":122,"line":195},[120,1290,1291],{"class":460},"        }],\n",[120,1293,1294],{"class":122,"line":201},[120,1295,1296],{"class":460},"    })\n",[120,1298,1299,1301,1304,1306,1310,1312,1314,1317,1319,1321],{"class":122,"line":207},[120,1300,616],{"class":615},[120,1302,1303],{"class":126}," files",[120,1305,468],{"class":460},[120,1307,1309],{"class":1308},"sJNII","0",[120,1311,736],{"class":460},[120,1313,471],{"class":439},[120,1315,1316],{"class":443},"status",[120,1318,471],{"class":439},[120,1320,478],{"class":460},[120,1322,1323],{"class":481},"  # 通常为 running，表示 MemOS 正在处理\n",[11,1325,1326,1327,1329],{},"文件较大时，也可以先把文件放到 MemOS 能够访问的地址，再在 ",[117,1328,1157],{}," 中传入 URL。",[11,1331,1332,1333,1336,1337,1340,1341,1344],{},"MemOS 收到文件后，异步完成解析、分段与索引，文件状态从 ",[117,1334,1335],{},"running"," 变为 ",[117,1338,1339],{},"completed","，处理失败时为 ",[117,1342,1343],{},"failed","。只有处理完成的内容才会进入检索结果。Memmy 页面据此展示「处理中」「可用」「失败」，有文件处理中时定时刷新。",[11,1346,1347],{},"文件名、处理状态等文件信息不在 Memmy 中另存，每次打开知识库都从 MemOS 实时查询，文件状态因此只有一个来源。Memmy 额外保存的只有目录：MemOS 知识库中的文件是平铺的，云服务记录文件夹层级和每个文件所在的文件夹，打开文件夹时按对应关系筛选。移动文件只修改对应关系，不需要重新上传，MemOS 也不会重新解析。",[21,1349],{},[24,1351,1353],{"id":1352},"agent-回答前的检索","Agent 回答前的检索",[11,1355,1356],{},"这是整条链路的核心。用户之间的隔离，最终落在每次检索传入的知识库 ID 上：传错一个，就会把别人的资料交给 Agent。一次对话中，知识库检索的过程如下：",[110,1358,1360],{"className":112,"code":1359,"language":114,"meta":115,"style":115},"sequenceDiagram\n    participant User as 用户\n    participant Hook as 知识库 Hook\n    participant Service as Memmy 云服务\n    participant MemOS as MemOS\n    participant Agent as Agent\n\n    User->>Hook: 在对话中提问\n    Note over Hook: Agent 运行前触发\n    Hook->>Service: 本轮问题\n    Service->>Service: 计算召回范围\n    alt 召回范围为空\n        Service-->>Hook: 不调用 MemOS，直接返回\n    else 召回范围不为空\n        Service->>MemOS: /search/memory（knowledgebase_ids = 召回范围）\n        MemOS-->>Service: 知识库片段\n        Service->>Service: 复核召回范围，变化则丢弃结果\n        Service-->>Hook: 资料片段与来源\n    end\n    Hook->>Agent: 把资料追加到本轮系统提示\n    Agent-->>User: 回答并引用来源\n    Hook->>Hook: 运行结束后移除注入内容\n",[117,1361,1362,1367,1372,1377,1382,1387,1392,1396,1401,1406,1411,1416,1421,1426,1431,1436,1441,1446,1451,1455,1460,1465],{"__ignoreMap":115},[120,1363,1364],{"class":122,"line":123},[120,1365,1366],{"class":126},"sequenceDiagram\n",[120,1368,1369],{"class":122,"line":130},[120,1370,1371],{"class":126},"    participant User as 用户\n",[120,1373,1374],{"class":122,"line":136},[120,1375,1376],{"class":126},"    participant Hook as 知识库 Hook\n",[120,1378,1379],{"class":122,"line":142},[120,1380,1381],{"class":126},"    participant Service as Memmy 云服务\n",[120,1383,1384],{"class":122,"line":148},[120,1385,1386],{"class":126},"    participant MemOS as MemOS\n",[120,1388,1389],{"class":122,"line":154},[120,1390,1391],{"class":126},"    participant Agent as Agent\n",[120,1393,1394],{"class":122,"line":160},[120,1395,488],{"emptyLinePlaceholder":487},[120,1397,1398],{"class":122,"line":166},[120,1399,1400],{"class":126},"    User->>Hook: 在对话中提问\n",[120,1402,1403],{"class":122,"line":172},[120,1404,1405],{"class":126},"    Note over Hook: Agent 运行前触发\n",[120,1407,1408],{"class":122,"line":178},[120,1409,1410],{"class":126},"    Hook->>Service: 本轮问题\n",[120,1412,1413],{"class":122,"line":184},[120,1414,1415],{"class":126},"    Service->>Service: 计算召回范围\n",[120,1417,1418],{"class":122,"line":189},[120,1419,1420],{"class":126},"    alt 召回范围为空\n",[120,1422,1423],{"class":122,"line":195},[120,1424,1425],{"class":126},"        Service-->>Hook: 不调用 MemOS，直接返回\n",[120,1427,1428],{"class":122,"line":201},[120,1429,1430],{"class":126},"    else 召回范围不为空\n",[120,1432,1433],{"class":122,"line":207},[120,1434,1435],{"class":126},"        Service->>MemOS: /search/memory（knowledgebase_ids = 召回范围）\n",[120,1437,1438],{"class":122,"line":213},[120,1439,1440],{"class":126},"        MemOS-->>Service: 知识库片段\n",[120,1442,1443],{"class":122,"line":218},[120,1444,1445],{"class":126},"        Service->>Service: 复核召回范围，变化则丢弃结果\n",[120,1447,1448],{"class":122,"line":224},[120,1449,1450],{"class":126},"        Service-->>Hook: 资料片段与来源\n",[120,1452,1453],{"class":122,"line":229},[120,1454,175],{"class":126},[120,1456,1457],{"class":122,"line":235},[120,1458,1459],{"class":126},"    Hook->>Agent: 把资料追加到本轮系统提示\n",[120,1461,1462],{"class":122,"line":241},[120,1463,1464],{"class":126},"    Agent-->>User: 回答并引用来源\n",[120,1466,1467],{"class":122,"line":247},[120,1468,1469],{"class":126},"    Hook->>Hook: 运行结束后移除注入内容\n",[11,1471,1472],{},"检索由知识库 Hook 在 Agent 运行前自动发起，Agent 本身不调用任何知识库接口。这样做不依赖 Agent 判断何时该查资料：用户开启「参与召回」后，提问时无需额外提醒「查一下知识库」。代价是每轮都会检索一次，与资料无关的问题也不例外。",[11,1474,1475],{},"Hook 拿到资料后追加到本轮系统提示；运行结束后移除这些内容，下一轮按新问题重新检索，资料不会在多轮对话中累积。",[11,1477,1478],{},"云服务在调用 MemOS 前后各检查一次召回范围：调用前计算范围，决定检索哪些知识库；调用后复核范围，确认检索期间范围没有变化。下面分别说明。",[11,1480,1481],{},"召回范围是以下两个集合的交集。交集为空时，云服务跳过检索，不调用 MemOS。",[1483,1484,1485,1488],"ul",{},[34,1486,1487],{},"用户开启了「参与召回」的知识库。",[34,1489,1490],{},"用户当前有权访问的知识库，包括自己拥有的和被共享的。",[11,1492,1493],{},"以场景中的销售同事为例：销售同事自己有一个知识库，又收到了产品经理共享的知识库，两个都开启了「参与召回」，召回范围就是这两个知识库的 MemOS ID。关掉自己知识库的「参与召回」后，召回范围只剩共享来的那一个。",[11,1495,1496,1499,1500,1503],{},[117,1497,1498],{},"knowledgebase_ids"," 是这条链路中唯一的权限出口。MemOS 默认不检索任何知识库，只有显式传入的 ID 才进入检索范围；它也支持传入 ",[117,1501,1502],{},"all","，但这会检索项目下的所有知识库，包括其他用户的。因此，云服务每次检索前都重新计算范围，只传入明确的 ID 列表，不信任桌面端缓存的列表。",[110,1505,1507],{"className":422,"code":1506,"language":424,"meta":115,"style":115},"def recall_scope(user_id):\n    return [\n        kb[\"memos_kb_id\"]\n        for kb_id, kb in knowledge_bases.items()\n        if can_access(user_id, kb_id)                     # 自己拥有的与被共享的\n        and recall_selected.get((user_id, kb_id), False)  # 开启了「参与召回」\n    ]\n\n\ndef recall(user_id, query):\n    scope = recall_scope(user_id)\n    if not scope:\n        return []  # 不调用 MemOS\n\n    data = memos_post(\"/search/memory\", {\n        \"user_id\": f\"kb-reader-{user_id}\",  # 检索专用 ID\n        \"query\": query,\n        \"knowledgebase_ids\": scope,         # 只传明确的 ID，不传 all\n    })\n\n    if recall_scope(user_id) != scope:  # 复核：范围变化则丢弃结果\n        return []\n\n    return [\n        {\"title\": item[\"memory_key\"], \"content\": item[\"memory_value\"]}\n        for item in data[\"memory_detail_list\"]\n    ]\n",[117,1508,1509,1522,1529,1544,1568,1589,1621,1626,1630,1634,1652,1667,1679,1690,1694,1714,1742,1757,1774,1778,1782,1803,1810,1814,1820,1870,1893],{"__ignoreMap":115},[120,1510,1511,1513,1516,1518,1520],{"class":122,"line":123},[120,1512,498],{"class":497},[120,1514,1515],{"class":501}," recall_scope",[120,1517,505],{"class":460},[120,1519,706],{"class":508},[120,1521,518],{"class":460},[120,1523,1524,1526],{"class":122,"line":130},[120,1525,616],{"class":615},[120,1527,1528],{"class":460}," [\n",[120,1530,1531,1534,1536,1538,1540,1542],{"class":122,"line":136},[120,1532,1533],{"class":126},"        kb",[120,1535,468],{"class":460},[120,1537,471],{"class":439},[120,1539,911],{"class":443},[120,1541,471],{"class":439},[120,1543,637],{"class":460},[120,1545,1546,1549,1551,1553,1556,1558,1560,1562,1565],{"class":122,"line":142},[120,1547,1548],{"class":615},"        for",[120,1550,711],{"class":126},[120,1552,512],{"class":460},[120,1554,1555],{"class":126}," kb ",[120,1557,766],{"class":615},[120,1559,728],{"class":126},[120,1561,461],{"class":460},[120,1563,1564],{"class":534},"items",[120,1566,1567],{"class":460},"()\n",[120,1569,1570,1573,1575,1577,1579,1581,1583,1586],{"class":122,"line":148},[120,1571,1572],{"class":615},"        if",[120,1574,701],{"class":534},[120,1576,505],{"class":460},[120,1578,706],{"class":534},[120,1580,512],{"class":460},[120,1582,711],{"class":534},[120,1584,1585],{"class":460},")",[120,1587,1588],{"class":481},"                     # 自己拥有的与被共享的\n",[120,1590,1591,1594,1597,1599,1601,1604,1606,1608,1610,1613,1616,1618],{"class":122,"line":154},[120,1592,1593],{"class":435},"        and",[120,1595,1596],{"class":126}," recall_selected",[120,1598,461],{"class":460},[120,1600,774],{"class":534},[120,1602,1603],{"class":460},"((",[120,1605,706],{"class":534},[120,1607,512],{"class":460},[120,1609,711],{"class":534},[120,1611,1612],{"class":460},"),",[120,1614,1615],{"class":990}," False",[120,1617,1585],{"class":460},[120,1619,1620],{"class":481},"  # 开启了「参与召回」\n",[120,1622,1623],{"class":122,"line":160},[120,1624,1625],{"class":460},"    ]\n",[120,1627,1628],{"class":122,"line":166},[120,1629,488],{"emptyLinePlaceholder":487},[120,1631,1632],{"class":122,"line":172},[120,1633,488],{"emptyLinePlaceholder":487},[120,1635,1636,1638,1641,1643,1645,1647,1650],{"class":122,"line":178},[120,1637,498],{"class":497},[120,1639,1640],{"class":501}," recall",[120,1642,505],{"class":460},[120,1644,706],{"class":508},[120,1646,512],{"class":460},[120,1648,1649],{"class":508}," query",[120,1651,518],{"class":460},[120,1653,1654,1657,1659,1661,1663,1665],{"class":122,"line":184},[120,1655,1656],{"class":126},"    scope ",[120,1658,526],{"class":435},[120,1660,1515],{"class":534},[120,1662,505],{"class":460},[120,1664,706],{"class":534},[120,1666,1106],{"class":460},[120,1668,1669,1671,1674,1677],{"class":122,"line":189},[120,1670,1064],{"class":615},[120,1672,1673],{"class":435}," not",[120,1675,1676],{"class":126}," scope",[120,1678,1086],{"class":460},[120,1680,1681,1684,1687],{"class":122,"line":195},[120,1682,1683],{"class":615},"        return",[120,1685,1686],{"class":460}," []",[120,1688,1689],{"class":481},"  # 不调用 MemOS\n",[120,1691,1692],{"class":122,"line":201},[120,1693,488],{"emptyLinePlaceholder":487},[120,1695,1696,1698,1700,1702,1704,1706,1708,1710,1712],{"class":122,"line":207},[120,1697,826],{"class":126},[120,1699,526],{"class":435},[120,1701,502],{"class":534},[120,1703,505],{"class":460},[120,1705,471],{"class":439},[120,1707,384],{"class":443},[120,1709,471],{"class":439},[120,1711,512],{"class":460},[120,1713,903],{"class":460},[120,1715,1716,1718,1720,1722,1724,1726,1729,1731,1733,1735,1737,1739],{"class":122,"line":213},[120,1717,908],{"class":439},[120,1719,706],{"class":443},[120,1721,471],{"class":439},[120,1723,574],{"class":460},[120,1725,577],{"class":497},[120,1727,1728],{"class":443},"\"kb-reader-",[120,1730,564],{"class":583},[120,1732,706],{"class":534},[120,1734,588],{"class":583},[120,1736,471],{"class":443},[120,1738,512],{"class":460},[120,1740,1741],{"class":481},"  # 检索专用 ID\n",[120,1743,1744,1746,1749,1751,1753,1755],{"class":122,"line":218},[120,1745,908],{"class":439},[120,1747,1748],{"class":443},"query",[120,1750,471],{"class":439},[120,1752,574],{"class":460},[120,1754,1649],{"class":534},[120,1756,553],{"class":460},[120,1758,1759,1761,1763,1765,1767,1769,1771],{"class":122,"line":224},[120,1760,908],{"class":439},[120,1762,1498],{"class":443},[120,1764,471],{"class":439},[120,1766,574],{"class":460},[120,1768,1676],{"class":534},[120,1770,512],{"class":460},[120,1772,1773],{"class":481},"         # 只传明确的 ID，不传 all\n",[120,1775,1776],{"class":122,"line":229},[120,1777,1296],{"class":460},[120,1779,1780],{"class":122,"line":235},[120,1781,488],{"emptyLinePlaceholder":487},[120,1783,1784,1786,1788,1790,1792,1794,1796,1798,1800],{"class":122,"line":241},[120,1785,1064],{"class":615},[120,1787,1515],{"class":534},[120,1789,505],{"class":460},[120,1791,706],{"class":534},[120,1793,1585],{"class":460},[120,1795,1080],{"class":435},[120,1797,1676],{"class":126},[120,1799,574],{"class":460},[120,1801,1802],{"class":481},"  # 复核：范围变化则丢弃结果\n",[120,1804,1805,1807],{"class":122,"line":247},[120,1806,1683],{"class":615},[120,1808,1809],{"class":460}," []\n",[120,1811,1812],{"class":122,"line":253},[120,1813,488],{"emptyLinePlaceholder":487},[120,1815,1816,1818],{"class":122,"line":258},[120,1817,616],{"class":615},[120,1819,1528],{"class":460},[120,1821,1822,1825,1827,1830,1832,1834,1837,1839,1841,1844,1846,1848,1850,1852,1854,1856,1858,1860,1862,1865,1867],{"class":122,"line":264},[120,1823,1824],{"class":460},"        {",[120,1826,471],{"class":439},[120,1828,1829],{"class":443},"title",[120,1831,471],{"class":439},[120,1833,574],{"class":460},[120,1835,1836],{"class":126}," item",[120,1838,468],{"class":460},[120,1840,471],{"class":439},[120,1842,1843],{"class":443},"memory_key",[120,1845,471],{"class":439},[120,1847,930],{"class":460},[120,1849,440],{"class":439},[120,1851,1157],{"class":443},[120,1853,471],{"class":439},[120,1855,574],{"class":460},[120,1857,1836],{"class":126},[120,1859,468],{"class":460},[120,1861,471],{"class":439},[120,1863,1864],{"class":443},"memory_value",[120,1866,471],{"class":439},[120,1868,1869],{"class":460},"]}\n",[120,1871,1873,1875,1878,1880,1882,1884,1886,1889,1891],{"class":122,"line":1872},26,[120,1874,1548],{"class":615},[120,1876,1877],{"class":126}," item ",[120,1879,766],{"class":615},[120,1881,918],{"class":126},[120,1883,468],{"class":460},[120,1885,471],{"class":439},[120,1887,1888],{"class":443},"memory_detail_list",[120,1890,471],{"class":439},[120,1892,637],{"class":460},[120,1894,1896],{"class":122,"line":1895},27,[120,1897,1625],{"class":460},[11,1899,1900],{},"检索返回后的复核容易被忽略。一次检索需要一定时间，期间拥有者可能撤销共享，用户也可能关闭某个知识库的「参与召回」。例如销售同事提问时，产品经理恰好撤销了共享：调用 MemOS 前，召回范围里还有这个知识库；检索返回时，它已经不在范围内了。复核发现范围变化，云服务丢弃整次结果，下一轮再按新范围检索。",[11,1902,1903,1904,1906,1907,1909,1910,1915],{},"示例中的 ",[117,1905,706],{}," 是检索专用的，从不写入对话，因此检索结果里只有知识库片段。这是因为 Memmy 的个人记忆由独立的 Memory 模块负责，两类上下文由各自的 Hook 注入，互不依赖。如果你的应用没有自己的记忆系统，可以传入真实的 ",[117,1908,706],{},"，让 MemOS 在同一次检索中一并返回用户事实与偏好，具体用法可参考",[1911,1912,1914],"a",{"href":1913},"/cn/memos_cloud/features/knowledge_base","知识库功能说明","。",[11,1917,1918],{},"Hook 注入资料时会注明：这些内容是参考资料而不是指令，Agent 需要引用来源，并忽略资料中出现的任何指令，以防范提示词注入。",[11,1920,1921],{},[68,1922],{"alt":1923,"src":1924},"Agent 回答时标注资料来源","https://cdn.memtensor.com.cn/img/1792586375431_qwk6vy_compressed.png",[21,1926],{},[24,1928,389],{"id":389},[11,1930,1931],{},"MemOS 没有成员或共享相关的接口，Memmy 的共享完全在应用层实现。由于所有知识库都在同一个 MemOS 项目下，只要 Memmy 判定成员有权访问，就可以把拥有者知识库的 MemOS ID 加入成员的召回范围。处理过程如下：",[31,1933,1934,1937,1940],{},[34,1935,1936],{},"拥有者在「共享管理」中输入对方的 Memmy 用户 ID、手机号或邮箱。",[34,1938,1939],{},"云服务把输入解析为 Memmy 账号，确认对方存在且不是本人后，写入一条只读成员关系。这一步不调用 MemOS。",[34,1941,1942],{},"对方刷新页面后，在知识库列表的「共享」分组中看到该知识库，并显示来自哪位用户。新共享的知识库默认参与对方的召回。",[11,1944,1945],{},[68,1946],{"alt":1947,"src":1948},"共享管理","https://cdn.memtensor.com.cn/img/1792586422247_2r0azs_compressed.png",[11,1950,1951],{},"共享后，拥有者与被共享的用户权限如下：",[272,1953,1954,1967],{},[275,1955,1956],{},[278,1957,1958,1961,1964],{},[281,1959,1960],{},"操作",[281,1962,1963],{},"拥有者",[281,1965,1966],{},"被共享的用户",[294,1968,1969,1979,1989,1998,2007,2016],{},[278,1970,1971,1974,1977],{},[299,1972,1973],{},"查看文件",[299,1975,1976],{},"✓",[299,1978,1976],{},[278,1980,1981,1984,1986],{},[299,1982,1983],{},"开关「参与召回」",[299,1985,1976],{},[299,1987,1988],{},"✓，只影响自己",[278,1990,1991,1994,1996],{},[299,1992,1993],{},"上传、删除文件",[299,1995,1976],{},[299,1997,354],{},[278,1999,2000,2003,2005],{},[299,2001,2002],{},"新建、移动、删除文件夹",[299,2004,1976],{},[299,2006,354],{},[278,2008,2009,2012,2014],{},[299,2010,2011],{},"重命名、删除知识库",[299,2013,1976],{},[299,2015,354],{},[278,2017,2018,2020,2022],{},[299,2019,1947],{},[299,2021,1976],{},[299,2023,354],{},[11,2025,2026],{},"共享不复制任何内容：所有成员检索的是同一个 MemOS 知识库。场景中产品经理上传新资料后，销售同事的下一次检索即可命中新内容。拥有者撤销共享后，该成员的召回范围立即不再包含这个知识库。",[21,2028],{},[24,2030,2031],{"id":2031},"删除知识库",[11,2033,2034],{},"删除分两步：先在 Memmy 中删除，知识库立即从所有成员的列表和召回范围中消失，用户无需等待；再在后台清理 MemOS 中的知识库与文件。以删除知识库为例：",[110,2036,2038],{"className":422,"code":2037,"language":424,"meta":115,"style":115},"def delete_knowledge_base(user_id, kb_id):\n    kb = knowledge_bases[kb_id]\n    if kb[\"owner_id\"] != user_id:\n        raise PermissionError(\"只有拥有者可以删除知识库\")\n\n    # 1. 先在 Memmy 中删除\n    del knowledge_bases[kb_id]\n    members.pop(kb_id, None)\n\n    # 2. 再在后台清理 MemOS\n    threading.Thread(target=memos_post, args=(\"/delete/knowledgebase\", {\n        \"knowledgebase_id\": kb[\"memos_kb_id\"],\n        \"delete_all\": True,\n    })).start()\n",[117,2039,2040,2057,2071,2093,2110,2114,2119,2132,2153,2157,2162,2200,2223,2238],{"__ignoreMap":115},[120,2041,2042,2044,2047,2049,2051,2053,2055],{"class":122,"line":123},[120,2043,498],{"class":497},[120,2045,2046],{"class":501}," delete_knowledge_base",[120,2048,505],{"class":460},[120,2050,706],{"class":508},[120,2052,512],{"class":460},[120,2054,711],{"class":508},[120,2056,518],{"class":460},[120,2058,2059,2061,2063,2065,2067,2069],{"class":122,"line":130},[120,2060,1049],{"class":126},[120,2062,526],{"class":435},[120,2064,728],{"class":126},[120,2066,468],{"class":460},[120,2068,733],{"class":126},[120,2070,637],{"class":460},[120,2072,2073,2075,2077,2079,2081,2083,2085,2087,2089,2091],{"class":122,"line":136},[120,2074,1064],{"class":615},[120,2076,1067],{"class":126},[120,2078,468],{"class":460},[120,2080,471],{"class":439},[120,2082,741],{"class":443},[120,2084,471],{"class":439},[120,2086,478],{"class":460},[120,2088,1080],{"class":435},[120,2090,1083],{"class":126},[120,2092,1086],{"class":460},[120,2094,2095,2097,2099,2101,2103,2106,2108],{"class":122,"line":142},[120,2096,1091],{"class":615},[120,2098,1094],{"class":783},[120,2100,505],{"class":460},[120,2102,471],{"class":439},[120,2104,2105],{"class":443},"只有拥有者可以删除知识库",[120,2107,471],{"class":439},[120,2109,1106],{"class":460},[120,2111,2112],{"class":122,"line":148},[120,2113,488],{"emptyLinePlaceholder":487},[120,2115,2116],{"class":122,"line":154},[120,2117,2118],{"class":481},"    # 1. 先在 Memmy 中删除\n",[120,2120,2121,2124,2126,2128,2130],{"class":122,"line":160},[120,2122,2123],{"class":615},"    del",[120,2125,728],{"class":126},[120,2127,468],{"class":460},[120,2129,733],{"class":126},[120,2131,637],{"class":460},[120,2133,2134,2137,2139,2142,2144,2146,2148,2151],{"class":122,"line":166},[120,2135,2136],{"class":126},"    members",[120,2138,461],{"class":460},[120,2140,2141],{"class":534},"pop",[120,2143,505],{"class":460},[120,2145,733],{"class":534},[120,2147,512],{"class":460},[120,2149,2150],{"class":990}," None",[120,2152,1106],{"class":460},[120,2154,2155],{"class":122,"line":172},[120,2156,488],{"emptyLinePlaceholder":487},[120,2158,2159],{"class":122,"line":178},[120,2160,2161],{"class":481},"    # 2. 再在后台清理 MemOS\n",[120,2163,2164,2167,2169,2172,2174,2177,2179,2181,2183,2186,2188,2190,2192,2194,2196,2198],{"class":122,"line":184},[120,2165,2166],{"class":126},"    threading",[120,2168,461],{"class":460},[120,2170,2171],{"class":534},"Thread",[120,2173,505],{"class":460},[120,2175,2176],{"class":558},"target",[120,2178,526],{"class":435},[120,2180,643],{"class":534},[120,2182,512],{"class":460},[120,2184,2185],{"class":558}," args",[120,2187,526],{"class":435},[120,2189,505],{"class":460},[120,2191,471],{"class":439},[120,2193,412],{"class":443},[120,2195,471],{"class":439},[120,2197,512],{"class":460},[120,2199,903],{"class":460},[120,2201,2202,2204,2206,2208,2210,2212,2214,2216,2218,2220],{"class":122,"line":189},[120,2203,908],{"class":439},[120,2205,1202],{"class":443},[120,2207,471],{"class":439},[120,2209,574],{"class":460},[120,2211,1067],{"class":534},[120,2213,468],{"class":460},[120,2215,471],{"class":439},[120,2217,911],{"class":443},[120,2219,471],{"class":439},[120,2221,2222],{"class":460},"],\n",[120,2224,2225,2227,2230,2232,2234,2236],{"class":122,"line":195},[120,2226,908],{"class":439},[120,2228,2229],{"class":443},"delete_all",[120,2231,471],{"class":439},[120,2233,574],{"class":460},[120,2235,991],{"class":990},[120,2237,553],{"class":460},[120,2239,2240,2243,2246],{"class":122,"line":201},[120,2241,2242],{"class":460},"    })).",[120,2244,2245],{"class":534},"start",[120,2247,1567],{"class":460},[11,2249,2250,2252,2253,2256,2257,2260,2261,2263],{},[117,2251,2229],{}," 默认为 ",[117,2254,2255],{},"false","，只解除知识库与当前项目的关联，知识库与文件仍然保留；彻底删除必须显式传入 ",[117,2258,2259],{},"true","。删除文件与文件夹遵循同样的顺序，后台调用 ",[117,2262,416],{},"。后台清理可能失败，应用需要准备重试或定期对账，避免 MemOS 中残留已删除的数据。",[21,2265],{},[24,2267,2268],{"id":2268},"小结",[11,2270,2271],{},"Memmy 的接入可以归结为一句话：MemOS 负责\"资料里写了什么\"，Memmy 负责\"谁能用、用哪些\"。任何同时拥有客户端与终端用户的 AI 产品，接入 MemOS 知识库时都可以沿用这套分层。",[11,2273,2274],{},"Memmy 的权限粒度是整个知识库。需要按文件区分可见范围时，可以把可见范围不同的文件放进不同的知识库。",[2276,2277,2278],"style",{},"html pre.shiki code .s5ojA, html code.shiki .s5ojA{--shiki-light:#90A4AE;--shiki-default:#0E1116;--shiki-dark:#E6EDF3}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sZaqd, html code.shiki .sZaqd{--shiki-light:#90A4AE;--shiki-default:#023B95;--shiki-dark:#79C0FF}html pre.shiki code .saN0X, html code.shiki .saN0X{--shiki-light:#39ADB5;--shiki-default:#A0111F;--shiki-dark:#FF7B72}html pre.shiki code .sjUum, html code.shiki .sjUum{--shiki-light:#39ADB5;--shiki-default:#032563;--shiki-dark:#A5D6FF}html pre.shiki code .sp1uZ, html code.shiki .sp1uZ{--shiki-light:#91B859;--shiki-default:#032563;--shiki-dark:#A5D6FF}html pre.shiki code .suWxN, html code.shiki .suWxN{--shiki-light:#39ADB5;--shiki-default:#0E1116;--shiki-dark:#E6EDF3}html pre.shiki code .s5qkx, html code.shiki .s5qkx{--shiki-light:#E53935;--shiki-default:#0E1116;--shiki-dark:#E6EDF3}html pre.shiki code .sfVK4, html code.shiki .sfVK4{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#66707B;--shiki-default-font-style:inherit;--shiki-dark:#8B949E;--shiki-dark-font-style:inherit}html pre.shiki code .sZ6T4, html code.shiki .sZ6T4{--shiki-light:#9C3EDA;--shiki-default:#A0111F;--shiki-dark:#FF7B72}html pre.shiki code .sbcIq, html code.shiki .sbcIq{--shiki-light:#6182B8;--shiki-default:#622CBC;--shiki-dark:#D2A8FF}html pre.shiki code .sM07a, html code.shiki .sM07a{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#0E1116;--shiki-default-font-style:inherit;--shiki-dark:#E6EDF3;--shiki-dark-font-style:inherit}html pre.shiki code .sa-2m, html code.shiki .sa-2m{--shiki-light:#6182B8;--shiki-default:#0E1116;--shiki-dark:#E6EDF3}html pre.shiki code .svxCd, html code.shiki .svxCd{--shiki-light:#6182B8;--shiki-default:#023B95;--shiki-dark:#79C0FF}html pre.shiki code .sp4zP, html code.shiki .sp4zP{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#702C00;--shiki-default-font-style:inherit;--shiki-dark:#FFA657;--shiki-dark-font-style:inherit}html pre.shiki code .scyET, html code.shiki .scyET{--shiki-light:#F76D47;--shiki-default:#A0111F;--shiki-dark:#FF7B72}html pre.shiki code .sBMTB, html code.shiki .sBMTB{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#A0111F;--shiki-default-font-style:inherit;--shiki-dark:#FF7B72;--shiki-dark-font-style:inherit}html pre.shiki code .skqQ-, html code.shiki .skqQ-{--shiki-light:#E2931D;--shiki-default:#023B95;--shiki-dark:#79C0FF}html pre.shiki code .smHB8, html code.shiki .smHB8{--shiki-light:#39ADB5;--shiki-default:#023B95;--shiki-dark:#79C0FF}html pre.shiki code .sJNII, html code.shiki .sJNII{--shiki-light:#F76D47;--shiki-default:#023B95;--shiki-dark:#79C0FF}",{"title":115,"searchDepth":130,"depth":130,"links":2280},[2281,2282,2283,2287,2288,2289,2290],{"id":26,"depth":130,"text":26},{"id":76,"depth":130,"text":76},{"id":792,"depth":130,"text":792,"children":2284},[2285,2286],{"id":301,"depth":136,"text":301},{"id":1009,"depth":136,"text":1009},{"id":1352,"depth":130,"text":1353},{"id":389,"depth":130,"text":389},{"id":2031,"depth":130,"text":2031},{"id":2268,"depth":130,"text":2268},"Memmy 桌面端知识库的接入方式：API Key 只留在服务端，知识库归属、共享与召回范围由应用计算，文档解析与检索交给 MemOS。","md",{},"/cn/usecase/memmy_knowledge_base",{"title":5,"description":13},"cn/usecase/memmy_knowledge_base","bM5hbLRr8SGmKBzrhOj95D-AdXLoVRbZg6S7E4bj-EA",[2299,2307],{"title":2300,"path":2301,"stem":2302,"icon":2303,"framework":6,"module":6,"class":2304,"target":-1,"active":2305,"defaultOpen":2305,"children":-1,"description":2306},"用 MemOS 为 AI 应用构建共享知识库","/cn/usecase/shared_knowledge_base","usecase/shared_knowledge_base","i-ri-book-2-line",[],false,"应用负责归属与共享，MemOS 负责文档解析与检索，让有权限的用户围绕同一份知识库提问。",{"title":2308,"path":2309,"stem":2310,"icon":2311,"framework":6,"module":6,"class":2312,"target":-1,"active":2305,"defaultOpen":2305,"children":-1,"description":2313},"让知识库成为懂你的专属顾问","/cn/usecase/knowledge_qa_assistant","usecase/knowledge_qa_assistant","i-ri-customer-service-2-line",[],"融合长期记忆与知识库，告别 “千人一面” 的检索结果，基于用户背景与偏好提供个性化、精准化解答，让知识库成为懂你的专属顾问。",1793163786309]