news 2026/8/31 5:46:23

Deepseek harness 底层的Cordis就像一个公司?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Deepseek harness 底层的Cordis就像一个公司?

Corids框架基础——“一切皆插件”

理解DeepSeek harness的地基cord插框架
本章目标:

  • 什么是插件化架构
  • 为什么是Agent框架要这么设计
  • 5个核心设计思想

先问一个问题:什么是 Agent?

想象你要开一家AI 公司,这家公司的目标是:接收客户任务 → 思考 → 调用工具 → 返回结果。

客户说:“帮我查一下天气,然后写一首关于天气的诗”

Agent 要做的事:

  1. 理解任务(需要 LLM 大脑)
  2. 调用"查天气"工具
  3. 拿到天气数据
  4. 调用"写诗"能力
  5. 返回结果
    问题来了:如果每做一个新 Agent,你都要从零写"怎么调工具"、“怎么管对话”、“怎么换模型”……太累了!

Cordis 就是解决这个的——它是一套"公司管理框架",让你像搭积木一样组装 Agent。

Cordis 概念公司类比具体例子
插件 (Plugin)一个员工/部门“工具部”、“模型部”、“安全部”
上下文 (Context)公司通讯录/公告板每个员工通过通讯录找到其他部门
服务 (Service)部门提供的能力“工具部”提供ctx.tools(各种工具)
事件 (Event)公司广播/邮件“有新任务了!”、“工具调用完毕!”
依赖注入 (inject)入职前提“安全部”成立的前提是“工具部”已经存在
效果 (Effect)入职/离职手续员工离职时自动交接工作、归还工牌

核心概念:Cordis的五大思想

Cordis 是整个 dsh 框架的底层哲学。想象它是一个**“插件操作系统”**——每个功能都是一个可插拔的模块。

思想一:插件 = 员工

插件是一个实现服务的对象,在coredis中,插件有三种形态。

// 形态 1:函数插件(最常用)exportconstname='my-plugin'// 可选,用于诊断export functionapply(ctx:Context){// 在这里注册你的贡献}// 形态 2:对象插件exportconstmyPlugin={name:'my-object-plugin',apply(ctx:Context){/* ... */}}// 形态 3:类插件(Service 子类)classMyServiceextendsService{constructor(ctx:Context){super(ctx,'myService')// 注册服务名}}

一句话理解:插件就是一个"员工",入职时告诉公司"我能干什么"。

思想二:Context = 公司通讯录

Context是所有服务的容器插件,通过Context找到它需要的服务,而不是直接import具体实现。

没有Cordis的情况(混乱):"我要用搜索功能!"→ 你newSearchTool()→ 你newDeepSeekLLM()→ 你newFileSaver()每个地方都要自己找具体的人,换个人就要改代码 有Cordis的情况(有序):"我要用搜索功能!"→ ctx.tools.execute('search',...)你不管具体是谁在做,通讯录(ctx)帮你找到

一句话:Context 让你"找人办事"不用知道具体是谁,只认岗位不认人。

思想三:依赖注入 = 入职前提

插件通过inject字段声明它需要什么服务,coredis会等所有依赖就绪后才加载插件

场景:你想成立"安全审计部",但它必须等"工具部"成立后才能工作 (因为安全部要审计工具调用) 没有依赖注入: 你手动安排:先加载工具部 → 再加载安全部 万一顺序错了,安全部找不到工具部,崩溃! 有依赖注入:// 安全部的定义exportconstinject=['tools']// "我需要 tools 部先成立"Cordis自动处理:1.看到安全部需要 tools2.先加载 tools3.tools 就绪后,再加载安全部

一句话:你只声明"我需要谁",框架自动安排顺序。

思想四:事件 = 公司广播

事件是插件间松耦合通信的方式,Core Redis有5种调度模式。

emit——广播通知

// 服务方:发射事件classStatsServiceextendsService{bump(name:string){constnext=(this.counts.get(name)??0)+1this.counts.set(name,next)this.ctx.emit('stats/report',name,next)// 广播}}// 消费方:监听事件export functionapply(ctx:Context){ctx.on('stats/report',(name,count)=>{console.log(`${name}->${count}`)})}

一句话:事件 = “我做了件事,谁关心谁听着”,发布者不知道也不关心谁在听

思想五:效果 = 自动离职交接

Cordis最精妙的设计

场景:一个插件被卸载(比如配置改了、热更新) 没有效果管理: 插件卸载了,但它注册的监听器还在 → 内存泄漏 它启动的定时器还在 → 定时器报错 它注册的 service 还在 → 别人调用时崩溃 有效管理(Cordis): export functionapply(ctx){// 注册监听器 → 卸载时自动移除ctx.on('event',handler)// 启动定时器 → 卸载时自动清理ctx.effect(()=>{consttimer=setInterval(...)return()=>clearInterval(timer)// ← 这个函数在卸载时自动执行})}

Fiber状态机(插件的生命周期)
PENDING ──→ LOADING ──→ ACTIVE ──→ UNLOADING ──→ DISPOSED

└──→ FAILED

PENDING:等待依赖服务就绪
LOADING / ACTIVE:apply() 执行中 / 已完成
FAILED:加载失败
UNLOADING / DISPOSED:清理中 / 已清理


深入理解:Waterfall = 审批流程

Waterfall 是 dsh 中使用最频繁的模式,理解它就理解了 Agent 的"拦截链"
这是最难理解的,用公司审批类比:

场景:员工要调用一个危险工具(比如删除文件),需要审批 直接调用: tool.delete(file)→ 直接执行,没有拦截Waterfall(审批链): 员工发起请求 → 经过层层审批 → 最终执行或拒绝 调用 ctx.waterfall('approval/request', '删除文件')│ ▼ ┌─────────────────────────────┐ │ 第1层:日志记录员 │ │"有人要删除文件,我先记一笔"│ │ 调用next()→ 继续往下 │ └─────────────────────────────┘ │ ▼ ┌─────────────────────────────┐ │ 第2层:安全策略员 │ │"删除文件?让我看看规则..."│ │ 规则说:不能删除系统文件! │ │ 直接返回"拒绝"✂️ │ ← 不调用next(),链断了! └─────────────────────────────┘ │ ▼(返回值往上走)┌─────────────────────────────┐ │ 第1层收到"拒绝"│ │"哦被拒绝了,我也返回拒绝"│ └─────────────────────────────┘ │ ▼ 最终结果:拒绝执行

执行流程:
调用 ctx.waterfall(‘approval/request’, ‘rm -rf /’)


┌─────────────────────────┐
│ 监听器 1 (日志记录) │
│ 调用 next() ──────────┼──┐
└─────────────────────────┘ │

┌─────────────────────────┐
│ 监听器 2 (安全策略) │
│ 发现是危险工具 │
│ 直接返回 false ✂️ │ ← 短路!不调用 next()
└─────────────────────────┘

▼ (返回值上浮)
┌─────────────────────────┐
│ 监听器 1 收到 false │
│ 记录日志,返回 false │
└─────────────────────────┘


最终结果: false (拒绝执行)

总结

概念一句话解释类比
Context插件之间互相找到对方的渠道公司通讯录
Service一个插件提供的能力部门(如工具部)
Event (emit)广播通知,谁监听谁收到公司大喇叭
Waterfall层层处理,可以中途拦截审批流程
Effect注册的东西,卸载时自动清理离职交接

Cordis 的五大思想:

  1. 插件 = 员工 → 每个功能是一个独立模块

  2. Context = 通讯录 → 通过它找到其他服务

  3. 依赖注入 = 入职前提 → 声明需要什么,框架自动安排

  4. 事件 = 广播 → 松耦合通信

  5. 效果 = 自动清理 → 生命周期自动管理
    "Cordis 有五个核心机制:

  6. 插件即服务
    每个插件是一个函数或类,通过 apply(ctx) 向系统注册自己的能力。

  7. 上下文定位
    插件之间不直接 import,而是通过 ctx 找到需要的服务。比如 ctx.tools 找到工具注册器。这样消费者和提供者完全解耦——换实现不改代码。

  8. 依赖注入
    插件用 inject 声明需要什么服务,框架自动按依赖顺序加载。配置文件里的顺序无所谓。

  9. 类型化事件
    插件间通过事件通信。ctx.emit 广播通知,谁监听谁收到。发布者不知道谁在听,新增监听者不改发布者代码。

  10. 可逆效果
    所有注册都是’效果’,插件卸载时自动清理——监听器移除、定时器停止,不会内存泄漏。"

总结

一句话概括
Cordis 是 dsh 的底层框架,通过插件化 + 事件驱动 + 依赖注入实现"一切皆插件、一切可替换"。

核心知识点

  1. 五大思想
    | 思想 | 一句话 | 类比 |
    |—|—|—|
    |插件即服务|apply(ctx)注册能力 | 员工入职报到 |
    |上下文定位|ctx找服务,不直接import| 公司通讯录 |
    |依赖注入|inject声明依赖,框架负责排序 | 入职前提 |
    |类型化事件|emit广播 /waterfall审批 | 公司大喇叭 / 审批流程 |
    |可逆效果| 注册的东西,卸载时自动清理 | 离职交接 |
  2. 两种关键事件模式

emit(广播):大喇叭通知,谁监听谁收到,发布者不知道谁在听
waterfall(审批链):层层处理,next()=放行,不调用next()=拦截
3. Fiber 生命周期

PENDING → LOADING → ACTIVE → UNLOADING → DISPOSED
面试怎么答
“Cordis 的核心是插件化架构。插件通过 apply(ctx) 向系统注册能力,通过 ctx 查找其他服务(解耦),通过 inject 声明依赖(框架自动排序)。通信靠事件——emit 做广播通知,waterfall 做可拦截的审批链。所有注册都是’效果’,卸载时自动清理,支持热加载。”

一页速记

五大思想:插件即服务 / 上下文定位 / 依赖注入 / 类型化事件 / 可逆效果
事件模式:emit(广播) / waterfall(审批链, next()=放行, 不调用=拦截)
生命周期:PENDING → LOADING → ACTIVE → UNLOADING → DISPOSED
效果管理:ctx.effect(() => { … return 清理函数 })

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/31 5:46:09

基于Spring Boot的大学生心理健康咨询系统实战解析

简介:本资源是一套完整的基于Spring Boot的大学生心理健康咨询系统源码,面向计算机专业本科生开展毕业设计、期末大作业或课程综合实践使用,旨在解决高校心理服务数字化能力不足、学生求助渠道有限等现实问题。压缩包共509个文件,…

作者头像 李华
网站建设 2026/8/31 5:45:27

Simulink汽车动力性能仿真曲线分析与异常排查方法

第010讲讨论的是Simulink里汽车动力性能仿真结果曲线怎么看、怎么判、怎么排查。这个主题听起来很直观:模型跑完,双击Scope看曲线。但实际做过项目就会发现,曲线不是给眼睛看的,它要回答三个很具体的工程问题——最高车速能不能到…

作者头像 李华
网站建设 2026/8/31 5:45:19

仿美团外卖小程序前后端代码实战:从环境搭建到订单链路二次开发

简介:本资源是一套完整的仿美团外卖微信小程序开源项目,面向前端初学者、全栈入门者及小程序实战学习者,旨在帮助开发者系统掌握小程序开发全流程与典型业务场景实现。压缩包共206个文件,含38个JS逻辑文件(处理页面交互…

作者头像 李华
网站建设 2026/8/31 5:43:13

LVGL嵌入式UI实现高性能像素火焰特效:双缓冲画布与优化算法详解

最近在嵌入式UI开发中,想为设备界面添加一些动态、酷炫的视觉效果来提升用户体验,LVGL(Light and Versatile Graphics Library)无疑是首选。但实现像“像素火焰”这样复杂的动态效果,如果仅用基础控件和动画API&#x…

作者头像 李华
网站建设 2026/8/31 5:43:04

C语言——预处理器

基本介绍 预处理指令: 预处理过程中会执行预处理指令,预处理指令以 # 号开头,用于指导预处理器执行不同的任务。 预处理指令的特点: (1)预处理指令应该放在代码的开头部分。 (2)预处…

作者头像 李华
网站建设 2026/8/31 5:40:44

U3D|毕设答辩|毕设项目|毕业论文|基于Unity的白族扎染工艺交互设计与开发

文档标题:基于Unity的白族扎染工艺交互设计与开发文档介绍:第1章 绪论1.1 课题研究背景与意义白族扎染是中国云南省大理地区传统的手工印染工艺,已有上千年历史的传承。2006年被列为第一批国家级非物质文化遗产名录。它用针线作笔、布料作纸…

作者头像 李华