我们开源了 Djinn:一个提示词进去,NDJSON 事件流出来的 headless agent 运行时
今天我们开源了 Djinn——一个可嵌入的 headless agent 运行时:你给它一个提示词,它吐出一路逐行 NDJSON 事件流,会话随时可恢复。它不绑定任何 IDE,也不绑定任何模型厂商,底层仅依赖 Node 内置模块。一句话,它不是某个平台的插件,而是「agent 本体」。我们已经把它以 MIT 许可放出,欢迎 Star 与 Fork。
一、Djinn 是什么:agent 本体,不是插件也不是 SDK
市面上的「智能体」大多活在两种壳里:要么是一个 IDE 插件(你不去点,它不干活),要么是某家模型的 SDK(换家模型就得重写)。Djinn 想做的不是这两种,而是更底层的一层——把「会话持久化、模型池与容错、上下文压缩、工具执行」收敛成一个 headless 二进制:进程被拉起来,喂一个提示词,它跑完一轮、把每一步事件写成 NDJSON 吐到标准输出,然后退出。
这意味着它可以被任何系统用最简单的方式驱动:spawn 一个进程、读它的 stdout 就行。你既可以把它当 CLI 在终端里跑,也可以直接 require('@djinn/runtime') 嵌进你自己的 Node 进程。它不做业务编排,只负责把「agent 这一圈」跑得稳、跑得可恢复。
二、为什么是 headless + NDJSON:为「被别的系统驱动」而生
很多框架追求「我替你把整套流程都编排好」。Djinn 反向操作:它只保证一件事——stdout 永远只写逐行 NDJSON 事件(8 类:session / token / tool_call / tool_result / done / error …),日志一律走 stderr,退出码 0 成功 / 1 错误 / 130 表示 SIGINT 中断(会话已落盘)。
这套纪律看似朴素,却能换来一个关键能力:它是一个「可被编排器 spawn 驱动、流式拼接」的标准组件。上层不管是工作流引擎、聊天服务还是某个调度器,只要会拉进程、会读行,就能把 Djinn 接进去当推理执行体,而不必被锁进某套框架的抽象里。
三、最不一样的一点:会话能「复活」
生产环境里,进程被 kill -9、OOM、容器重启,都是家常便饭。多数 agent 实现一挂就丢上下文,得从头再来。Djinn 的设计前提是「进程随时会死,但会话不能死」:
- 持久化会话:以 append-only 的 jsonl 落盘,每产生一条记录就即刻写入;
- 断点恢复:进程被杀后用同一个
--session-id重跑即可续上; - dangling redo:上次死在「工具执行中途」的那一轮,会被自动重做,不会卡在半状态。
四、韧性模型池 + 双路径压缩:弱网也能跑完
推理不会永远顺滑。Djinn 在模型侧做了两层兜底:
- OpenAI 兼容模型池:主模型 + 有序 fallback 链,遇到 429 / 5xx / 网络错误 / 空响应会自动沿链切换;上下文超长时走「压缩后同模型重试」,而不是盲目换模型;每个模型可带独立的输入上限与网关地址。
- 两条上下文压缩路径:主路径调 LLM 生成摘要(2 次尝试),失败或返回空时,自动退到零成本的确定性裁剪兜底(丢弃 reasoning 等低信息量记录);触发线默认为当前模型输入上限的 70%。
工具侧同样稳健:内置 read_file / write_file / edit_file / bash / read_image / grep / glob 七件套;工具失败一律转成 isError 结果喂回模型,不中断循环。这让它即便在弱网、限流、上下文爆炸的环境里,也能把一轮跑完。
五、零运行时依赖:一个 npm 包,Node ≥ 18.17 就能跑
Djinn 的另一个执念是「没有第三方运行时依赖」——只用 Node 内置模块,CommonJS,Node ≥ 18.17 即可。这意味着它不需要和一个庞大的依赖树共存,也不会因为某个传递依赖的 breaking change 而崩。对要在生产环境长期驻留、还要做每租户隔离的推理执行体来说,「少依赖」本身就是一种可靠性。
它还随包发布了一个测试替身:一个假的 OpenAI 服务器(startFakeOpenAI),接入方无需真实模型、无需联网就能写自己的集成测试。Djinn 自身的 90+ 项测试就全部跑在它之上——覆盖 SSE 分块边界、崩溃半行、dangling 重做、SIGINT 中断恢复等真实而刁钻的场景。
六、在数员里,它是第三种推理底座
Djinn 不是孤立放出的玩具,它已经在数员的 AI 原生工作平台里承担角色——作为第三种推理引擎底座(底座 C 方案)与云端托管、本机引擎并列。在数员(harness-platform)中,一个租户只需一行
-- 租户级切换,无需改代码、无需重启 UPDATE tenants SET wbb_engine='djinn';
即可把数字员工的推理切换到 Djinn。在生产环境里,Djinn 以每租户独立系统用户降权运行,并挂入每次调用独立的 cgroup v2(内存 / 进程数硬顶),子进程环境变量为最小集——平台密钥(数据库 / 鉴权 / 其他引擎密钥)绝不注入降权进程。会话通过 --session-id 跨消息继承上下文,system prompt 经文件注入,与企业上下文、知识检索、能力指令共用同一套构建。换句话说,Djinn 先把「agent 本体」做扎实,数员再把「企业级治理」长在它外面。
七、我们的判断:把「agent 本体」交还给社区
为什么把这样一层开源出来?因为我们的判断是:「agent 运行时」正在从一个公司的内部实现,变成行业独立、可复用的一层基础设施——就像信通院在 2026 人工智能产业大会上把「智能体工程化」单列成关键词时所点明的:模型负责推理,Harness 工程负责把任务组织、约束、执行。Harness 这一层不该被锁死在某一家的私有实现里。
八、五分钟跑起来
零配置起步:装好、构建、给个 Key 就能跑。
# 安装依赖并构建 npm install npm run build npm link packages/cli # 或:node packages/cli/dist/index.js export DJINN_API_KEY=sk-... djinn -p "把当前目录的 package.json 里的版本号改成 0.2.0" # 输出(每行一个 JSON 事件) {"type":"session","sessionId":"3f6c…","resumed":false} {"type":"tool_call","name":"read_file","arguments":"{\"path\":\"package.json\"}"} {"type":"token","text":"已把版本号改为 0.2.0"} {"type":"done","sessionId":"3f6c…","turns":2,"usage":{...}} # 中断后恢复(同一个会话 id) djinn -p "继续,顺便把 README 也更新了" --session-id 3f6c…
想嵌进自己的进程?无需联网即可测试的写法同样简单:
const { startFakeOpenAI, contentChunk } = require('@djinn/runtime'); const fake = await startFakeOpenAI(() => ({ sse: [contentChunk('你好')] })); // …把 fake.baseUrl 当作 DJINN_API_BASE… await fake.stop();
事实与来源
- Djinn 开源项目(MIT 许可,可嵌入的 headless agent 运行时)——一个提示词进去、NDJSON 事件流出来,会话持久化可恢复,零运行时依赖(仅 Node 内置模块,CommonJS,Node ≥ 18.17)。为开源项目事实,详见 GitHub 仓库 github.com/gelincloud/djinn(已公开,可核验)。
- Djinn 核心特性——持久化会话(append-only jsonl + dangling redo)、OpenAI 兼容模型池与 fallback、双路径上下文压缩、7 个内置工具、headless 输出纪律(stdout NDJSON / stderr 日志 / 退出码 0·1·130)、自带测试替身(
startFakeOpenAI,90+ 项测试无需真实模型即可运行)。为项目事实,与上述 GitHub 仓库 README 及官网专页一致,可公开核验。 - 数员官网 Djinn 专页——对 Djinn 定位、特性、快速开始与「在数员里作为第三种推理底座」的说明。为产品事实,详见 miniabc.top/djinn.html(已上线,可核验)。
- 数员 AI 原生工作平台:数字员工 + 企业级治理底座——Djinn 在数员中作为可切换的推理引擎底座,生产环境以每租户独立系统用户降权 + 每次调用独立 cgroup v2 隔离运行。为产品事实,详见官网「产品版本」页(原文链接)。
编辑说明:本文由数员数字员工生产,经人类审核后发布。事实部分均附来源链接;带「解读 / 观点」标记的内容为我们的判断。文中测试项数为保守下限表述(项目 README 与官网专页对测试项数有 94 / 100+ 差异,以实际仓库为准);若具体表述有误,欢迎在仓库 Issue 指正,我们会核实并更正。