MIT, developer preview, breaking changes expected.
Would you let an agent install code into your own dev tool?
npx @deepseek-ai/dsh web
deepseek-ai/deepseek-harness
이 DeepSeek Harness는 오픈소스입니다.
완전 무료 MIT 라이선스.
이걸 가지고 무엇이든 만들어보세요.
deepseek-ai/deepseek-harness
21 likes · 5 reposts · 1,054 views
我把自己的 Agent 从 Wails 迁到了 MyGo 原生 GUI,全程踩坑和实践分享
最近把自己写的工作 agent [Ally agent]( Bronya0/ally-agent) 的界面重写了一遍,起因是无意中看到有人推荐 MyGo ,加上我对内存和性能一直有点追求,多年来一直在用 wails ,想换个试试,就想拿自己的项目试点,没想到结果意外的不错。
旧版本的技术栈是典型的 Go + Wails + Vue (wails 我用了很多年 最近终于 V3 发正式版了 等了四年,可惜我也老了),界面用 Naive UI ,样式美观,效果也相当不错。但做久了有几个地方比较麻烦( tarui 应该也是一样):
跨平台界面的细节不一致,构建链比较长,还有前端内存出了问题以后,我这个写后端的人不太容易排查。
折腾了一段时间,现在主要页面已经迁到 [MyGo]( egoist/mygo) 了,记录一下过程中比较有感触的地方。
先说一下技术路线:Wails 的界面通过系统 WebView 展示网页; MyGo 既支持这种方式,也支持用 Go 写 Native UI ,由框架自己绘制。WebView 也有自己的优势,MyGo 两种都支持,相当于有个兜底,下面会说。
Ally 现在的聊天、设置等常用页面用 Native UI ,插件页面和部分预览仍然按需使用 WebView 。
一、UI 跨平台一致性
这是我这次迁移最重视的一点。
之前用 Wails 做界面,Windows 上调好的页面,到了 macOS 上经常还要再看一遍。字体、行高、滚动条、输入框这些地方,偶尔就会有一点不一样。
比如我画的表格,不知道为啥线条在 macOS 上看着发虚,Windows 上就正常。单看问题都不大,但调整完一个平台还得顾着另一个平台,挺烦的。
Wails 使用系统 WebView ,Windows 和 macOS 背后的浏览器引擎不一样,前端样式最终要经过各自的渲染实现。
MyGo 的 Native UI 由框架自己负责布局和绘制。迁移后,我在 Windows 上调好的主体界面,拿到 macOS 上看到的效果接近得多,需要针对平台单独修的地方也少了。
当然,自绘也不等于所有像素都完全一致。MyGo 的文字排版仍然使用[各平台的文字系统]( mygo.egoist.dev):Windows 是 DirectWrite ,macOS 是 Core Text ,Linux 是 Pango 。字体回退、DPI 、输入法这些还是要分别检查。但至少不用再同时处理两套 WebView 引擎带来的样式差异了。
以前总觉得 Electron 重,碰到这些问题后倒是能理解为什么有些项目愿意用它:自带 Chromium ,渲染环境相对好统一。OpenCode 桌面端后来也[从 Tauri 换到了 Electron]( github.com/anomalyco/opencode/blob/dev/packages/d…),不过人家具体为什么换,我就不瞎猜了。
二、内存问题现在能用熟悉的 Go 工具查
以前 Wails 版本的 Go 后端一样可以用 pprof,但界面在 WebView 里,Go 堆、JavaScript 堆、DOM 、浏览器渲染进程是几块不同的东西。
前端也有 DevTools ,可以拍 JS heap snapshot 、查 DOM 引用。但我平时主要写 Go ,遇到界面内存持续上涨,分析起来没有 Go 那么顺手。
现在主要界面和业务都在 Go 进程里,我给 Ally 加了一个按需导出诊断的入口:在设置里点“导出内存诊断”,会导出 heap.pprof、allocs.pprof、goroutine.pprof 等文件。
比如在空闲时导出一次,复现内存增长后再导出一次,就可以对比:
go tool pprof -http=127.0.0.1:0 \
-base=before/heap.pprof after/heap.pprof
heap 主要看还活着的对象,allocs 主要看累计分配。分配量大不一定是泄漏,也可能是某段代码反复创建临时对象,GC 能回收,但会持续消耗 CPU 。
当然,pprof 主要看到的是 Go 堆。系统和 GPU 资源,以及 WebView 子进程的内存,还是得用其他工具看。
三、帧处理的坑
MyGo 的界面更新会重新构建控件树,写 UI 时要特别留意渲染函数里做了什么。
我的 Agent 有命令执行卡片,命令输出可能很长。之前即使卡片折叠着、界面上只展示最后几行,代码仍然会先把整段输出拆分、去空行,再取出末尾几行。
看起来只是一个字符串处理函数,但界面更新时会反复执行。
后来改了两处:
1. 只需要末尾几行时,从字符串尾部向前扫描,不再先拆分整个输出。
2. 需要重复使用的派生结果按原始内容缓存;内容没变就复用。折叠时不构造展开用的行数据,并释放对应缓存。
一次本地测试里,用两万行命令输出测试折叠卡片的相关处理,单次分配从约 1.9 MB 降到 1.9 KB ,耗时从约 0.72 ms 降到 0.02 ms。
这是这段处理在该样本下的局部结果,不是整个应用的性能对比。[对应修改在这里]( github.com/Bronya0/ally-agent/commit/a1e085b9397e…)。
类似的问题还有工具参数 JSON:同一条消息的卡片头、卡片体都可能读取参数,如果每次渲染都 Unmarshal 一遍,长对话里分配会越来越明显。现在把解析结果挂在控件局部状态上,原始参数变化时才重新解析。
我的感受是,性能问题要先分清楚是“每次请求执行一次”,还是“界面更新时每帧执行一次”。后者哪怕单次看着不重,乘上帧数和控件数量也很拖累性能。
四、构建链变短
旧项目的构建大致要经过前端依赖、绑定生成、Vite 构建,再编译 Go 。MyGo Native UI 的主要页面直接用 Go 写,主界面去掉了前端打包这一步,我自己的项目构建起来明显快了不少。
MyGo 不依赖 CGO ,交叉编译也省事。目前 Ally 的构建脚本可以在 macOS 上处理 Windows 、macOS 、Linux 的 x64 和 ARM64 六个目标,另外生成 macOS Universal 包。
例如编译一个 Windows x64 二进制,核心就是:
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o Ally.exe .
实际发布还要处理资源、压缩包、签名等事情;能交叉编译出来,也不代表已经在目标系统完成运行验证。Linux 的图形环境和使用 WebView 时需要的系统库,也仍然要考虑。
这里补充一下:我刚看了 [Wails 3.1 的发布说明]( wails.io),它也加入了无 CGO 构建能力。目前 macOS 和 Linux 的 purego 后端还是实验性质,CGO 仍是默认选项。
所以“无 CGO”以后不一定是两者之间的主要区别。对我这个项目来说,更明显的差别是主界面不用再经过 Vue 那套构建流程了。
五、MyGo 组件够用,但 Web 生态还是强很多
迁移前我担心原生 GUI 要从头写一堆控件,实际比想象中好一些。
MyGo 已经有常见的表单、列表、树、弹窗,也有代码编辑器、Diff 、Markdown 等组件。Ally 的文件浏览和代码编辑用到了它的编辑器,聊天内容也用到了 Markdown 相关能力。
但如果和成熟的 Web 组件库比,差距还是很明显。Naive UI 这类库积累了很长时间,一个表单、选择器或者弹窗拿来就能用,样式、焦点、键盘操作、动画都比较完整。
好在 MyGo 的定制能力不错,但要做出自己满意的效果,颜色、间距、状态和交互细节还是得花时间。我之前不太想碰这类原生 UI ,一个原因就是觉得手写样式太累。
现在有 AI 帮忙,这件事容易太多了。先用框架已有组件和 Base/Parts API ,让 AI 根据目标效果调整样式,再自己检查实际交互。
我的经验是,尽量复用组件本身的焦点、键盘导航、浮层和滚动行为,别为了改外观把这些重新实现一遍,非常容易踩坑。
六、WebView 的优势还在,可以混合使用
WebView 最大的好处之一就是生态。
视频播放、复杂图表、各种文件预览,Web 上已经有大量现成方案。很多东西如果坚持全部原生重写,维护成本很高。
MyGo 可以在 Native UI 窗口里嵌入 WebView ,所以我的做法是:常驻界面用原生 UI ,需要 Web 生态的地方再创建 WebView 。
Ally 目前的 HTML 和 Mermaid 预览就是这样处理的。预览可见时按需创建,数量做限制,离开后释放。否则一个长对话里出现很多图表时,每个预览都长期挂着 WebView ,前面省下来的资源很容易又花回去。
迁移后日常使用的内存占用和响应都有比较明显的改善。不过我还没有整理同一机器、相同会话和操作条件下的完整对照数据,暂时不拿具体数字比较两个框架。
七、插件化是 Go 里比较麻烦的东西,需要谨慎考虑
这是迁移前有点低估、做起来以后感受很深的一点。
看看 [DeepSeek Harness 的 Web Client 架构]( github.com/deepseek-ai/deepseek-harness/blob/mast…),它有插件加载、服务、事件和 UI Slots ,插件可以在已有界面里贡献功能。
Web 技术和 JavaScript 的动态加载能力,让这类扩展比较容易分发和迭代。当然,WebView 本身不会自动提供插件体系,生命周期、扩展点和权限边界都得应用自己设计。
纯 Go 桌面应用要做同样的事就麻烦得多。[Go 标准库的 plugin]( pkg.go.dev) 不支持 Windows ,加载后也不能卸载,对编译工具链和依赖版本还有要求,不适合直接拿来做一个跨 Windows 、macOS 、Linux 的热插拔 GUI 插件市场。
最后 Ally 还是用了混合方案:主程序是原生 UI ,插件页面按需跑在 WebView 里。插件可以打成 zip 安装,在侧栏增加页面,通过宿主提供的接口访问存储、HTTP 和工作区等能力;重新导入后可以更新,不用重启整个应用。
目前这更接近“可插拔页面”,和 DSH 那种能扩展更多核心能力的插件体系不太一样。WebView 也有自己的生命周期和资源成本,要做成完整生态,扩展点、兼容性和权限模型还有不少事要解决。
代码
大概就这些,迁移完之后我自己还是比较满意的,欢迎大家一起尝试原生界面
我的项目代码在 [Ally 仓库]( Bronya0/ally-agent): Bronya0/ally-agent 原来的 Wails 版本还在 main 分支,MyGo 版本在 [mygo 分支]( github.com/Bronya0/ally-agent/tree/mygo),感兴趣或想学习 MyGo 的可以对比着看,欢迎点个 Star 。
1 comment
DGX Spark1台でQwen3.8 Flash NextをClaude CodeとDeepSeek Harnessから動かす
はじめに
ローカルLLMを動かすためにDGX Sparkの互換機であるThinkstation PGXを購入したわけではないですが、せっかく1台持っているので、どのモデルであればまともに動作するのかをいろいろ試していました。
zenn.dev
しかしながら、調べれば調べるほど、128GB機1台程度では、他のGeforce GPU搭載のPCと比較して優位性のある結果にはなりませんでした。(Strataが強すぎる・・・)
とはいえその中でも、ある程度まともに動く中で大きめなモデルとしてQwen3.8 Flash Nextを動かしてみました。
!
strataの場合は、例えばRTX3060(VRAM 12GB)+RAN 64GB程度だと3bit程度の量子化のFlash Nextが動作可能です。
今回動作させるのは4bit程度の量子化のFlash Nextになります。
今回やりたいのは、このPCをLLMのサーバーにして、普段使っている別のPCからコードを書いてもらうことです。
操作にはClaude CodeとDeepSeek Harnessを使います。以降、DeepSeek Harnessはコマンド名に合わせて「dsh」と書きます。
最終的に使うのは、作業フォルダから呼び出す次の2つのコマンドです。
localclaude
localdsh
ここで普通に「claude」コマンドを使わないのは、普段使っているOpus 5.5とかを動かす際のclaudeの設定と、ローカルLLMを呼び出す時の設定を切り分けて、ストレスなく使うためです。
さて、せっかくローカルで動かすなら、速度も気になりますよね。
今回は、BF16のKVキャッシュとMTPを使った構成で、速度、コードの動作、メモリ使用量を確かめました。
利用するモデル
文章やコードの生成には、NVIDIAが公開しているFP4版のFlash Nextを使います。
NVIDIAが量子化後のモデルを学習し直したQAD版で、NVFP4とMXFP8などを組み合わせています。
huggingface.co
NVIDIAがこのモデルの対応エンジンとして案内しているのはvLLMです。
DGX Spark向けには、新しい重みの圧縮形式へ対応したコミュニティ製の専用コンテナを指定しています。
今回はそのvLLMとTensorFoldを比べ、生成速度とメモリ使用量からTensorFoldを選びました。
huggingface.co
TensorFoldとvLLMの比較条件
Claude Codeに同じ3つの課題を頼みました。ファイルを保存し、自分で動作確認してもらうところまで含めた試験です。
課題
確認した内容
区間の結合
重なる区間や端点が同じ区間の結合、不正な区間の検出、入力を変更しないこと
トポロジカルソート
辞書順で最小の順序、重複した辺、循環や未定義ノードの検出
JSON Linesの処理
ユーザー別の金額集計、真偽値の除外、不正入力の行番号、出現順の保持
比較相手は、NVIDIAのモデルカードで案内されているeugr/spark-vllm-b12xです。コンテナのdigestを固定し、初回の最適化を終えてから測りました。vLLMの版は0.1.dev21830+g8244d1c44.d20261026です。
モデルの重み、BF16のKVキャッシュ、MTP先読み6、コンテキスト上限262,144、同時実行上限3件を揃えています。vLLM側も、元のBF16 LMヘッドを保ち、追加のMXFP8変換や活性値の追加量子化を無効にしました。起動時のメモリ不足を避けるため、標準safetensorsローダとPyTorchのメモリ管理設定を使っています。
Claude Codeは--effort highで起動しました。モデルへの実効値はxhighに揃え、temperatureは1、top_pは0.95、top_kは20、出力上限は50,000トークンです。
比較時には、生成条件を揃えてサーバーの統計を記録する計測用の中継を挟みました。モデルやエンジンのコードは変更していません。後半の導入手順では、Claude CodeからTensorFoldのAPIへ直接接続します。
項目
TensorFold 1.1.9
vLLM
生成中の速度
58.16 token/s
40.98 token/s
入力処理・通信を含むAPI全体の速度
21.52 token/s
19.91 token/s
3課題のClaude Code実行時間
378.15秒
418.10秒
LLMへの要求回数
18回
18回
思考を含む出力トークン数
8,021
8,198
表は、3課題で発生した全要求を集計した結果です。
モデルの読み込みと初回最適化の時間は含めません。
token/sで見ると、TensorFoldが約1.42倍でした。Claude Codeが3課題を終えるまでの時間も、今回は約40秒短くなっています。
こちらのモデルで搭載されている以下の補助機構も利用して利便性と生成速度を向上させます
FP4版に含まれるMTP
別のドラフトモデルのダウンロードは不要
画像エンコーダ
FP4版に含まれる画像エンコーダ
PNG・JPEG・WebPなどの画像を入力可能
MTPとは
MTPはMulti-Token Predictionの略で、次の1トークンに加えて、その先のトークンも予測する仕組みです。
トークンは、モデルが文章を扱うときの文字や単語のまとまりです。
今回のFlash NextにはMTP用の補助部分が含まれており、これを使って続きの候補を先に作ります。別の小型モデルを追加で用意する必要はありません。
投機的デコードとは
通常の生成では、本体のモデルを動かして1トークンずつ確定します。
投機的デコードでは、先に作った数トークン分の候補を本体でまとめて検証します。候補がうまく当たった分だけ、本体を動かす回数を減らせる仕組みです。
今回の構成では、MTPが候補を作り、投機的デコードの手順で本体が検証・採用します。
以降の記事で記載している「先読み6」というのは、一度に最大6トークン分の候補を作る設定です。
外れた候補はそのまま採用せず、本体の出力に従って補正します。
詳細は以下の記事をご覧ください
zenn.dev
環境
モデルを動かしたのは、DGX Sparkと同じGB10を搭載したThinkStation PGXです。
実測と、記事の導入手順で使うソフトウェアをまとめます。
項目
環境
サーバー
Lenovo ThinkStation PGX、1台
CPU
Arm、20コア。Cortex-X925とCortex-A725を各10コア
GPU
NVIDIA GB10
NVIDIAドライバ
580.159.03
メモリ
CPUとGPUで共有する128GB
OS・アーキテクチャ
Ubuntu 24.04.4 LTS、aarch64
Linuxカーネル
6.17.0-1021-nvidia
推論エンジン
公式TensorFold 1.1.9のLinux aarch64配布版。
GPU実行環境
NVIDIAドライバを備えたホスト上で、公式のネイティブ実行ファイルを直接起動
Claude Code
2.1.223
DeepSeek Harness
0.2.0-rc.2。Node.jsはv24.16.0
実測と導入手順で使う構成を、次の設定に揃えます。
項目
設定
モデルの重み
NVIDIAのFP4版
KVキャッシュ
BF16
MTP
有効・先読み6
コンテキスト上限
262,144トークン
同時実行上限
3件
画像入力
無効。今回は文字・コード生成を対象とする
同時実行上限は、APIサーバーが同時に生成するリクエスト数の上限です。
今回は最大3件を並行して処理します。それ以上の依頼を送った場合は、空いた枠を使って順番に処理するため、5件を送れば5件とも同時に生成するわけではありません。
MTPの先読み数は、1件の生成で予測するトークン数です。並列数を増やす設定ではありません。
速度とコードの品質は、思考を有効にした同じClaude Codeの作業で確認しました。以降は、その作業中に記録した速度とメモリ使用量を見ていきます。
別PCから使う場合は、同じLAN内のPCにClaude Codeまたはdshを入れて接続します。後半は、その設定手順です。
実験結果
Claude Codeに次のPythonコードを書いて保存・実行してもらいました。課題は1件ずつ、思考highで実施しています。
タスク(未公開)
初回
修正後
生成速度(token/s)
重なる区間を結合する
不合格
合格
60.84
依存関係に沿って辞書順に並べ替える
合格
合格
54.21
JSON Linesからユーザー別の金額を集計する
合格
合格
59.84
各課題8項目のテストをすべて通れば合格としています。
初回の合格率は66.7%(2/3課題)。区間の結合を1回修正した後は100%(3/3課題)となり、計24項目のテストをすべて通過しました。
全体の生成速度は58.16 token/s、3課題の実行時間は約6分18秒でした。速度には思考と修正分も含み、モデルの読み込み時間は除いています。
ツール利用に関しても、4bit量子化であることもあり、かなり安定して動作しています。
OSを含む使用メモリの最大値は84.31GiBで、利用可能メモリは最少でも35.32GiB残っていました。
利用構成・環境構築
接続の流れは、次のようになります。
Claude Codeを使っていても、この構成で文章やコードを生成するモデルはFlash Nextです。
Claude Codeは、依頼を送り、返ってきた指示に従ってファイルを編集する役割を担当します。
TensorFoldが両方のAPI形式を扱うため、今回の手順では別の形式変換サーバーを置きません。
接続先の指定には、1点違いがあります。
利用する側
ベースURL
主な生成API
Claude Code
192.168.0.194
/v1/messages
dsh
192.168.0.194
/v1/chat/completions
192.168.0.194は本記事の例です。自分のPGXのLAN内IPアドレスに置き換えてください。
APIサーバの構築
ここからは、モデルを動かすPGX側の操作です。
Ubuntu系のLinuxで、NVIDIAドライバが利用できることを前提にします。公式のLinux aarch64配布版を取得し、モデルのダウンロードから始めます。
github.com/ashhart/TensorFold/blob/v1.1.9/README.…
まず、GPUとメモリ、ディスクの空き容量を確認します。
nvidia-smi
free -h
df -h "$HOME"
モデルの配布ファイルは約96GiBです。実行ファイルやダウンロードの作業領域にも空き容量が必要なので、モデルの容量だけでディスクを埋めないようにしてください。
公式の実行ファイルを取得
今回はPGXのArm CPUに合わせて、Linux aarch64版を使います。
mkdir -p "$HOME/local-llm/flash-next"
cd "$HOME/local-llm/flash-next"
V=1.1.9
curl -fLO "github.com/ashhart/TensorFold/releases/download/v…"
curl -fLO "github.com/ashhart/TensorFold/releases/download/v…"
sha256sum -c "tensorfold-$V-linux-aarch64.tar.gz.sha256"
tar -xzf "tensorfold-$V-linux-aarch64.tar.gz"
./tensorfold-1.1.9-linux-aarch64/bin/tensorfold-native --version
チェックサムの検査が通り、tensorfold-native 1.1.9と表示されれば、取得できています。展開したフォルダには実行ファイルと必要なライブラリが入っているため、フォルダごと保存してください。
モデルのダウンロード
同じ作業フォルダで、公式のpullコマンドを使います。モデルのリビジョンも指定しておきます。
cd "$HOME/local-llm/flash-next"
HF_HUB_CACHE="$PWD/models-cache" \
./tensorfold-1.1.9-linux-aarch64/bin/tensorfold-native pull \
nvidia/Qwen3.8-Flash-Next-FP4-Local@b9ce18a6887e18c089fdea8509a33e63429a3300
このコマンドで取得するのは、重み、MTP、トークナイザーなど、Hugging Faceの同じ公開モデルに含まれるファイル一式です。初回は約96GiBあるため、ダウンロードには時間がかかります。
保存先は、この例ではmodels-cacheです。途中で止まった場合は、同じコマンドで取得を再開できます。
APIキーの作成
今回はLAN内へ公開し、APIキーを付けて呼び出します。次の操作は、初回に一度行ってください。
cd "$HOME/local-llm/flash-next"
umask 077
python3 - <<'PY'
from pathlib import Path
import secrets
p = Path('api-key')
p.write_text(secrets.token_hex(32) + '\n')
p.chmod(0o600)
PY
api-keyに保存した値を、後でクライアント側にも設定します。サーバーには、公式の--api-key-fileで渡します。
サーバの起動
取得した固定リビジョンのフォルダを指定し、次のコマンドで公式の実行ファイルを起動してください。
(以降、サーバを止めてから再開するときはこのコマンドを実行すればOK)
cd "$HOME/local-llm/flash-next"
HF_HUB_OFFLINE=1 TF_FLASHNEXT_DRAFTS=6 \
./tensorfold-1.1.9-linux-aarch64/bin/tensorfold-native serve \
"$PWD/models-cache/models--nvidia--Qwen3.8-Flash-Next-FP4-Local/snapshots/b9ce18a6887e18c089fdea8509a33e63429a3300" \
--name Qwen3.8-Flash-Next \
--host 0.0.0.0 --port 8888 \
--api-key-file "$PWD/api-key" \
--context 262144 --parallel 3 \
--max-tokens 50000 \
--temperature 1 --top-p 0.95 --top-k 20 \
--thinking --reasoning-effort high \
--kv-cache bf16 --prompt-cache-gib 0 \
--prompt-seed --no-update-check
パラメータ解説
TF_FLASHNEXT_DRAFTS=6で、MTPの先読み数を指定します。
MTPは既定で有効です。
--kv-cache bf16、--parallel 3、--context 262144が、今回測定した構成になります。
--max-tokens 50000は、応答の出力上限の既定値です。
--prompt-cache-gib 0は、リクエスト間で状態を再利用するプロンプトキャッシュを無効にする設定です。
--prompt-seedは、入力文からseedを決める設定です。
今回のClaude Codeが使うAnthropic形式のAPIは、要求側のseedを生成処理へ渡さないため、この入力由来のseedで動作します。実測でも有効にしています。
起動ログを確認できたら、そのターミナルは開いたままにしてください。
別のターミナルやクライアントPCから接続しましょう。
停止は、サーバーを動かしたターミナルでCtrl+Cです。再起動するときも、同じ起動コマンドを使います。
LAN内IPアドレスは次のコマンドで確認できます。
hostname -I
複数表示される場合は、別PCと同じLANに属するアドレスを指定してください。
この手順は信頼できるLAN内で使うHTTP接続です。
同一LANからのAPI動作確認
ここから先は、普段作業するPCで操作します。
以下はmacOS、Linux、WindowsのWSLで使えるBash系の手順です。
まず接続先とAPIキーを~/.config/flash-next/connection.envに保存します。
モデル名は保存せず、起動するたびにサーバーから取得するようにします。
APIキーは、サーバーのapi-keyファイルに保存した値へ置き換えてください。
接続先FLASH_BASE_URLは、サーバをたちあげたPCのIPアドレスとポート番号を指定して下さい。
mkdir -p "$HOME/.config/flash-next" "$HOME/.local/bin"
chmod 700 "$HOME/.config/flash-next"
umask 077
cat > "$HOME/.config/flash-next/connection.env" <<'ENV'
FLASH_BASE_URL='192.168.0.194'
FLASH_API_KEY='63e36・・・(ここをサーバーのapi-keyファイルの値へ置き換える)'
ENV
chmod 600 "$HOME/.config/flash-next/connection.env"
接続確認では、このファイルを読み込んでモデル一覧を取得します。
. "$HOME/.config/flash-next/connection.env"
curl -fsS --connect-timeout 5 --max-time 15 \
"$FLASH_BASE_URL/v1/models" \
-H "Authorization: Bearer $FLASH_API_KEY"
以下のような返信があればOKです。
{"object": "list", "data": [{"id": "Qwen3.8-Flash-Next", "object": "model", "created": 1793522255, "owned_by": "tensorfold", "context_length": 262144, "max_model_len": 262144, "reasoning": {"default_enabled": true, "default_effort": "xhigh", "supported_efforts": ["xhigh", "medium", "low", "none"]}}]}%
モデルの設定を起動時に取得する
Mac側には、サーバーから設定を取得する共通ファイルを1つ置きます。
localclaudeとlocaldshのどちらも、起動時にこのファイルを使います。
Python 3が必要なので、python3 --versionで確認しておいてください。
取得するのはモデル名、コンテキスト長、対応する思考レベルと既定値です。
これらはTensorFoldの/v1/modelsが返す情報を使います。
github.com/ashhart/TensorFold/blob/v1.1.9/README.…
cat > "$HOME/.config/flash-next/resolve-model.py" <<'PY'
import json
import os
import shlex
import sys
import urllib.request
base = os.environ['FLASH_BASE_URL'].rstrip('/')
request = urllib.request.Request(
base + '/v1/models',
headers={'Authorization': 'Bearer ' + os.environ['FLASH_API_KEY']},
)
with urllib.request.urlopen(request, timeout=15) as response:
models = json.load(response)['data']
if not models:
sys.exit('サーバーに利用可能なモデルがありません。')
requested = os.environ.get('FLASH_MODEL_ID')
model = next((m for m in models if m['id'] == requested), None) if requested else models[0]
if model is None:
sys.exit('指定したモデルがありません: ' + str(requested))
context = model.get('context_length') or model.get('max_model_len')
reasoning = model.get('reasoning', {})
supported = reasoning.get('supported_efforts', [])
if not isinstance(context, int) or context < 2 or not supported:
sys.exit('この手順に必要なコンテキスト長・思考レベルがAPIにありません。')
def ui_level(wire):
return {'none': 'off', 'xhigh': 'high'}.get(wire, wire)
levels = {ui_level(wire): wire for wire in reversed(supported)
if wire in ('none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max')}
default = ui_level(reasoning.get('default_effort') or supported[0])
effort = os.environ.get('FLASH_EFFORT') or default
if effort not in levels:
sys.exit('対応していない思考レベルです。選択肢: ' + ', '.join(levels))
50,000はこの記事で使う出力上限。モデルの最大出力長を取得した値ではありません。
max_tokens = min(50000, context // 2)
if sys.argv[1] == 'env':
if effort == 'off':
sys.exit('この記事のClaude Code起動手順では思考を有効にしてください。')
values = {'FLASH_MODEL': model['id'], 'FLASH_CONTEXT_TOKENS': context,
'FLASH_MAX_TOKENS': max_tokens, 'FLASH_RESOLVED_EFFORT': effort}
for name, value in values.items():
print('export ' + name + '=' + shlex.quote(str(value)))
elif sys.argv[1] == 'dsh':
patch = [
{'id': 'agent-default-model', 'config': {
'provider': 'local-flash-next', 'model': model['id'], 'reasoningEffort': effort}},
{'id': 'llm-pi-ai', 'config': {'providers': {'local-flash-next': {
'apiKeyEnv': 'LOCAL_LLM_API_KEY',
'api': 'openai-completions', 'baseURL': base + '/v1',
'reasoning': effort,
'compat': {'supportsDeveloperRole': False, 'maxTokensField': 'max_tokens',
'supportsReasoningEffort': True, 'thinkingFormat': 'openai'},
'models': [{'id': model['id'], 'contextWindow': context,
'maxTokens': max_tokens, 'reasoningEfforts': levels}],
}}}},
{'id': 'session-log-deepseek', 'disabled': True},
{'id': 'session-telemetry-otel', 'disabled': True},
]
print(json.dumps(patch, ensure_ascii=False, indent=2))
else:
sys.exit('env または dsh を指定してください。')
print('接続モデル: ' + model['id'] + ' / 思考: ' + effort, file=sys.stderr)
PY
モデルが1つなら、そのモデルを自動で使います。
複数ある場合は一覧の先頭を使い、別のモデルを選ぶときだけFLASH_MODEL_ID='モデルID' localclaudeのように指定します。dshも同じです。
このAPIが返すのは、サーバーが現在公開しているモデルです。
出力上限の50,000トークンは、今回の実験に合わせたクライアント側の設定です。
まずは共通ファイルで設定を取得し、そのまま接続確認に使います。
set -a
. "$HOME/.config/flash-next/connection.env"
set +a
model_settings=$(python3 "$HOME/.config/flash-next/resolve-model.py" env) && eval "$model_settings"
続いて、短い文章も生成してみましょう。
curl -fsS --max-time 180 "$FLASH_BASE_URL/v1/chat/completions" \
-H "Authorization: Bearer $FLASH_API_KEY" \
-H 'Content-Type: application/json' \
--data-binary @- <<JSON | python3 -m json.tool --no-ensure-ascii
{
"model": "$FLASH_MODEL",
"messages": [{"role": "user", "content": "日本語で短く挨拶してください。"}],
"temperature": 0,
"max_tokens": 256,
"draft": true,
"chat_template_kwargs": {"enable_thinking": false}
}
JSON
初めの確認は思考OFFにしています。
思考レベルを試す場合は、enable_thinkingをtrueにし、JSONへ"reasoning_effort": "low"などを追加してください。
以下のような出力が得られていればOKです。
出力確認{
"id": "chatcmpl-1fb90809d034accea082e1d53bbc19a3",
"object": "chat.completion",
"created": 1793522557,
"model": "Qwen3.8-Flash-Next",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "こんにちは。"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 19,
"completion_tokens": 3,
"total_tokens": 22,
"prompt_tokens_details": {
"cached_tokens": 0
},
"completion_tokens_details": {
"reasoning_tokens": 0
}
},
"exact_mode": "exact",
"tensorfold": {
"enable_thinking": false,
"reasoning_effort": "none",
"engine": "lanes",
"tokens_per_second": 15.529567290581785,
"seconds": 0.128786589,
"prefill_seconds": 0.110438503,
"prefill_widths": [],
"prefill_raised": [],
"time_to_first_token": 0.111080564,
"sampling": "greedy",
"drafts": true,
"token_sha": "d849233ade4a",
"token_sha256": "d849233ade4aa863a41e1df72f82155ca6bd3fda35f04ba70eadc962cf26bee8",
"min_rows": 2
},
"speculative": {
"rounds": 2,
"drafted": 5,
"accepted": 4,
"acceptance_rate": 0.8,
"tokens_per_round": 1.5
}
}
Claude Codeが使うAnthropic形式でも、短い挨拶を返してもらいましょう。
curl -fsS --max-time 180 "$FLASH_BASE_URL/v1/messages" \
-H "Authorization: Bearer $FLASH_API_KEY" \
-H 'Content-Type: application/json' \
-H 'anthropic-version: 2023-06-01' \
--data-binary @- <<JSON | python3 -m json.tool --no-ensure-ascii
{
"model": "$FLASH_MODEL",
"messages": [{"role": "user", "content": "日本語で短く挨拶してください。"}],
"temperature": 0,
"max_tokens": 256,
"thinking": {"type": "disabled"}
}
JSON
出力確認{
"id": "msg_267abe01eae1e591d5209ab3fa3b8b9c",
"type": "message",
"role": "assistant",
"model": "Qwen3.8-Flash-Next",
"content": [
{
"type": "text",
"text": "こんにちは。"
}
],
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {
"input_tokens": 19,
"output_tokens": 3,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0,
"output_tokens_details": {
"thinking_tokens": 0
}
}
}
それぞれchoicesまたはcontentに文章が返れば、次へ進めます。
Claude CodeからQwenを利用する
Claude Codeをすでに使っている方は、そのインストールを使います。
未導入の場合は、公式のインストール手順に従って導入してください。
code.claude.com
curl -fsSL claude.ai | bash
claude --version
本記事ではClaude Code 2.1.223を使いました。
次に、ローカルLLM用の起動コマンドを作ります。
~/.local/bin/localclaudeに設定ファイルを書き込みます。
cat > "$HOME/.local/bin/localclaude" <<'SH'
#!/usr/bin/env bash
set -euo pipefail
set -a
source "$HOME/.config/flash-next/connection.env"
set +a
: "${FLASH_BASE_URL:?}" "${FLASH_API_KEY:?}"
model_settings=$(python3 "$HOME/.config/flash-next/resolve-model.py" env)
eval "$model_settings"
unset CLAUDE_CODE_OAUTH_TOKEN ANTHROPIC_CUSTOM_HEADERS
unset CLAUDE_CODE_USE_BEDROCK CLAUDE_CODE_USE_VERTEX CLAUDE_CODE_USE_FOUNDRY
export ANTHROPIC_BASE_URL="${FLASH_BASE_URL%/}"
export ANTHROPIC_API_KEY="$FLASH_API_KEY"
export ANTHROPIC_AUTH_TOKEN="$FLASH_API_KEY"
export ANTHROPIC_MODEL="$FLASH_MODEL"
export ANTHROPIC_DEFAULT_OPUS_MODEL="$FLASH_MODEL"
export ANTHROPIC_DEFAULT_SONNET_MODEL="$FLASH_MODEL"
export ANTHROPIC_DEFAULT_HAIKU_MODEL="$FLASH_MODEL"
export CLAUDE_CODE_SUBAGENT_MODEL="$FLASH_MODEL"
export CLAUDE_CONFIG_DIR="$HOME/.claude-config/flash-next"
unset CLAUDE_CODE_EFFORT_LEVEL CLAUDE_CODE_EXTRA_BODY
export CLAUDE_CODE_MAX_CONTEXT_TOKENS="$FLASH_CONTEXT_TOKENS"
export CLAUDE_CODE_MAX_OUTPUT_TOKENS="$FLASH_MAX_TOKENS"
export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1
export CLAUDE_CODE_ATTRIBUTION_HEADER=0
export API_TIMEOUT_MS=3600000
mkdir -p "$CLAUDE_CONFIG_DIR"
export CLAUDE_CODE_AUTO_MODE_MODEL="$FLASH_MODEL"
exec claude --model "$FLASH_MODEL" --effort "$FLASH_RESOLVED_EFFORT" "$@"
SH
chmod 755 "$HOME/.local/bin/localclaude"
export PATH="$HOME/.local/bin:$PATH"
この設定はlocalclaudeから起動したプロセスに適用されます。
普段のclaudeを起動するために、接続先の環境変数を毎回消す操作は不要です。
作業用のフォルダを作って起動します。
mkdir -p "$HOME/Desktop/flash-next-demo"
cd "$HOME/Desktop/flash-next-demo"
localclaude
専用プロファイルで初めて起動するため、初回案内やフォルダを信頼するかどうかの確認が表示される場合があります。
また、途中でANTHROPICのAPIキーを利用するかを聞かれるかもですが、今回は自宅のサーバに問い合わせを行うため、Noと回答して下さい。
接続先やモデルが想定どおりかを確認したら、例えば次の依頼を送ってみてください。
Python標準ライブラリだけで動くfile_sha256.pyを作成してください。
引数で指定されたファイルのSHA-256を表示するCLIです。
存在しないファイルは理由を標準エラーへ出し、終了コード1にしてください。
作成したスクリプト自身を入力として実行し、動作確認してください。
ファイルの編集やBash実行は、このクライアントPC上で行われます。
許可を求められた操作は、内容を確認して進めてください。
Mac側から思考レベルを変える
サーバーの--reasoning-effort highは、要求に指定がない場合の既定値です。
Macから指定した値で上書きできるので、サーバーの再起動は不要です。
現在のサーバーはxhigh、medium、low、noneを対応する値として公開しています。default_effort: xhighは、その中の既定値です。
FLASH_EFFORT=low localclaude
FLASH_EFFORT=medium localclaude
FLASH_EFFORT=high localclaude
FLASH_EFFORTを付けなければ、サーバーが公開している既定値を使います。
指定した場合はクライアントの値を優先し、サーバーの対応一覧にない値は起動前にエラーにします。
今回のFlash Nextでは、highはモデル内部のxhighに対応します。
起動後の変更はClaude Codeの/effort lowや/effort mediumでも指定できます。
同じフォルダの直前の会話を続ける場合は、次のように起動できます。
localclaude -c
!
手元の環境でauto modeも正しく動作することを確認しました。
ちゃんと判定機として、Flash Nextが呼ばれています。
export CLAUDE_CODE_AUTO_MODE_MODEL="$FLASH_MODEL"
の設定が効いていると思います。
DeepSeek Harness(dsh)からQwenを使う
dshにも同じAPIサーバーを登録します。
今回は0.2.0-rc.2が対象です。専用フォルダへインストールしてください。dshは開発中で設定形式も変わるため、この記事の設定はこの版を対象にしています。
deepseek-ai/deepseek-harness
Node.jsとnpmを用意してください。動作確認ではNode.js 24.16.0を使いました。
node --version
npm --version
mkdir -p "$HOME/.local/share/flash-next-dsh"
npm install --prefix "$HOME/.local/share/flash-next-dsh" \
@deepseek-ai/dsh@0.2.0-rc.2
!
バージョンの更新や、元のバージョンに戻したい場合は以下のコマンドを実行して下さい
#更新する場合:
npm install --prefix "$HOME/.local/share/flash-next-dsh" \
@deepseek-ai/dsh@latest
#記事の版へ戻す場合:
npm install --prefix "$HOME/.local/share/flash-next-dsh" \
@deepseek-ai/dsh@0.2.0-rc.2
接続設定は、共通ファイルから起動時に自動生成します。
~/.config/flash-next/dsh.patch.jsonへ自動で保存されるため、このJSONを手で編集する必要はありません。
ファイル
保存する内容
~/.config/flash-next/connection.env
接続先URL・実際のAPIキー
~/.config/flash-next/resolve-model.py
サーバーからモデル情報を取得する処理
~/.config/flash-next/dsh.patch.json
起動時に生成するdsh用の設定
openai-completionsは、この版のdshでChat Completions APIを選ぶ設定名です。
今回はthinkingFormat: openaiで共通のreasoning_effortを送り、モデルごとの処理をTensorFoldに任せます。
起動コマンドを~/.local/bin/localdshに作ります。
cat > "$HOME/.local/bin/localdsh" <<'SH'
#!/usr/bin/env bash
set -euo pipefail
set -a
source "$HOME/.config/flash-next/connection.env"
set +a
: "${FLASH_BASE_URL:?}" "${FLASH_API_KEY:?}"
export LOCAL_LLM_API_KEY="$FLASH_API_KEY"
export DSH_HOME="$HOME/.config/dsh-flash-next"
export DSH_PERMISSION_MODE=workspace-write
export DSH_TELEMETRY_MODE=OFF
mkdir -p "$DSH_HOME"
patch="$HOME/.config/flash-next/dsh.patch.json"
tmp=$(mktemp "${patch}.XXXXXX")
trap 'rm -f "$tmp"' EXIT
python3 "$HOME/.config/flash-next/resolve-model.py" dsh > "$tmp"
mv "$tmp" "$patch"
profile=web
if [[ "${1:-}" == headless ]]; then
profile=headless
shift
fi
exec "$HOME/.local/share/flash-next-dsh/node_modules/.bin/dsh" \
"$profile" --patch "$patch" "$@"
SH
chmod 755 "$HOME/.local/bin/localdsh"
設定の読み込みだけを先に確認できます。モデル一覧は取得しますが、文章生成の依頼は送りません。
localdsh --dump-config | grep -A 5 \
-e '^- id: agent-default-model$' \
-e '^ local-flash-next:$'
起動時に表示される「接続モデル」がサーバーのモデル名になり、出力内のproviderがlocal-flash-next、baseURLがPGXのアドレスになっていれば準備完了です。
local-flash-nextは接続設定の名前なので、サーバーで使うモデルを変えても書き換えません。
作業フォルダへ移動して起動します。
cd "$HOME/Desktop/flash-next-demo"
localdsh
localdshはクライアントPCでWeb UIを開きます。
この版の配布パッケージにはtuiの標準プロファイルがないため、対話にはwebを使う構成です。
ブラウザが開かない場合は、起動時に表示されるローカルURLを確認してください。
!
なお、dshのWeb UIでは、会話で選択しているWorkspaceのフォルダに、作成したコマンドなどを保存します。
私のMacではデフォルトのワークスペースの指定先は
~/Documents/deepseek-harness/default-workspace
となっていましました。
自分が指定した箇所に保存してもらうためには、Web UI上の「Add workspace」から作成したいフォルダを選択するようにして下さい。
こちらでも、最初は短いファイル作成を依頼して、編集と実行まで確認すると分かりやすいです。
dshでも、起動時に思考レベルを指定できます。
FLASH_EFFORT=low localdsh
FLASH_EFFORT=medium localdsh
Web UIではモデル選択欄から、サーバーが対応する思考レベルを選べます。
ターミナルから1件の依頼を実行して終了する場合は、同じ起動コマンドにheadlessを付けます。
localdsh headless 'このフォルダにhello.pyを作り、日本語の挨拶を表示してください。'
サーバーのモデルやPCを変えるとき
同じTensorFoldサーバーで別のモデルを公開した場合は、localclaudeまたはlocaldshを起動し直すと、新しいモデル情報を取得します。Mac側のモデル名やdshのJSONは書き換えません。モデルを変えた後は、新しい会話で始めてください。
サーバーのPCやポートを変える場合は、~/.config/flash-next/connection.envのFLASH_BASE_URLを変更します。APIキーも変えた場合だけ、同じファイルのFLASH_API_KEYを更新してください。
設定コマンドが使えない場合
~/.local/binがPATHへ登録されていない場合は、シェルの設定にも追加しておきましょう。
macOSなどのzshなら~/.zshrc、Bashなら~/.bashrcへ、次の1行を記載してください。
export PATH="$HOME/.local/bin:$PATH"
新しいターミナルを開けば、localclaudeとlocaldshを使えます。
この2つは実行ファイルの名前なので、同じ名前のaliasを追加する必要はありません。
おわりに
今回ローカルLLMを手元の作業環境で動作させる上でこだわったのは以下のポイントです。
ローカルLLMはThinkStation PGXでAPIサーバとして待機すること
サーバを別のPCにしたり、別のモデルを利用できるようにしたりすることを目的としている
手元のPCで実行する場合は、すでに入っている純正のClaude Codeなどの設定とは別の設定を引き継ぐコマンドで実行する
メインで利用しているOpusを利用する設定はそのまま使えるようにする
これで、メインでClaudeを利用していても、そちらの利用体験を損なわないまま、ローカルLLMを同じ体験で試すことができるようになりました。
今後もどんどん試していきたいと思います!
DeepSeek's dsh-superagent is a proactive coding agent that waits to be asked: router, tickets, and the observe default
On October 31, DeepSeek's Harness team announced an open-source coding agent on WeChat, and by November 1 Bloomberg was framing it as a challenge to Claude Code. The repo is deepseek-ai/dsh-superagent-prototype, MIT licensed, v0.1.0, a single commit. The README's own first lines matter more than the headlines: "Research prototype for reference only, not an official DeepSeek product." Treat it as a published design study, because that is what it is. I read the repo and the coverage, and the interesting parts are not the speed claims. They are the control flow.
What actually shipped
dsh-superagent is a proactive coding agent scoped to one GitHub repository. It is packaged as a bundle for DeepSeek Harness, the team's open-source agent harness (we covered its Claude Code Mods compatibility layer last month). It listens to GitHub events and, optionally, Feishu chat. When someone allowed to ask requests work, the agent opens a work item, does the work in its own agent session and working directory, and answers in the original conversation, often as a pull request. A local web panel lists only the items that need a human.
The stated principle in the README: "take as little human attention as possible, and give as much value as possible." An agent that can act for a whole team can also waste a whole team's attention, so it acts only when asked, or when a rule the team wrote allows it, and speaks only when someone must act or can use a result. That is an attention budget enforced in code, which is rarer than it sounds.
The unit of work is a Ticket with a Mandate
The domain model is the part I would copy first. Every request becomes a Ticket, and every Ticket carries an immutable Mandate stating why the work may proceed. Authorization is recorded per unit of work, not granted globally to the agent. The flow, as MarkTechPost's breakdown documents it:
Source GitHub or Feishu produces events
Trigger a single event arrives
Eval does this batch of triggers ask for new work?
Ticket unit of authorized work, with an immutable Mandate
Subscription later PR comments reach the right worker, no new mention
The Subscription piece solves a real annoyance: follow-up comments on a pull request are routed to the worker that already holds the context, instead of spawning a fresh session per mention.
One router, many workers
The architecture has two layers. A long-running Router handles interaction and dispatch, running the dsh-superagent-router preset with a deliberately smaller tool set. Isolated Worker sessions do the actual work, each running dsh-superagent-worker. One session and one directory per Ticket, so concurrent tasks cannot trample each other's state.
One execution detail worth knowing: shell commands move to the background after 5 seconds, so a worker keeps receiving messages while a slow command runs. That is the kind of small decision that decides whether a long-running agent feels alive or wedged.
Autonomy is a gate, and observe is the default
This is the design choice I keep coming back to. Proactive behavior is not a switch you get for free. The authorization model defines three accept modes: off, observe (the default), and auto. In observe, the agent only records what it would have accepted. Nothing runs until a human reviews the log and moves to auto, presumably per rule, not as a global leap of faith.
Most "autonomous agent" releases ship with the scary part enabled and a warning label. This one ships with the boring part enabled and a paper trail. Anyone who has spent time writing deny rules in agent configs knows which default ages better. If the topic of rules-gated agent behavior is new to you, the same week's coverage of Microsoft's Agensh experiment is a good contrast: 1,024 agents with no manager, and one agent on a newer model beat the whole fleet. More agents without a dispatch discipline is not automatically more throughput.
The 1.9x number, and what it does not prove
The benchmark floating through coverage comes from DeepSeek's simulation: about 300 messages per run, of which about 20 were real work requests, five runs per scheme. The super-agent finished with a p50 of 12.4 minutes and a p95 of 15.7 minutes. A single-session agent with subagents, run under a neutral prompt, hit a p95 of 29.5 minutes. That is roughly 1.9x at the tail, and the reported reason is instructive: under the neutral prompt, the baseline invoked a subagent zero times in five runs. The router also degraded gracefully under load, with batching growing from 1.0 to 2.8 as arrivals rose from about 1 to 40 per minute, and per-request latency from 2.5 to 3.9 seconds.
Now the caveats, which the coverage buries. The test traffic was synthetic. The tools were simulated. Real coding quality was not measured. The README also says the published code was adapted for release and is not identical to the internal version, and that some designs in the accompanying post, "Exploring Super-agent Design: Towards a More Autonomous Agent System", are future directions, not implemented features. So read the 1.9x as a property of the dispatch design under noisy input, not as a productivity claim about your repository.
Running it at all takes five dependencies
If you still want to try it: Node.js 22.19+ or 24+, git 2.32+, Python 3.8+, tmux, and GitHub CLI 2.48+, on your own machine as a dedicated Harness profile. The setup is explicitly agent-assisted. You ask your coding agent, in so many words:
Read SETUP.md in this repository and set up dsh-superagent with me.
It then asks one short question at a time, shows the full plan once, and installs. Setup docs written for an agent reader rather than a human one is a small signal of where this team thinks tooling is going.
What to steal even if you never run it
I will not be deploying this prototype; it says not to, in writing, at the top of its own README. But the checklist generalizes to any chat-triggered agent you build or configure, and it matches what newruntime's review took from it too. A defensible autonomous workflow needs four things: a durable work item, an authorization boundary, task isolation, and a narrow escalation path. Ticket, Mandate, one session per task, a panel that only lists what needs you. If your current setup is a bot in a channel with a broad tool set and no ledger of why it was allowed to act, this repo is a free reference implementation of everything you are missing.
1 reaction
DeepSeek's Super-agent Defaults to Observe Mode, but Its Workers Get Full Access as You
- Book: Database Playbook
- The series: Pocket Guides for Developers — 8 short books on agents, RAG, prompts, observability, events, databases and system design — the whole series
- My project: Hermes IDE | GitHub — an IDE for developers who ship with Claude Code and other AI coding tools
- Me: xgabriel.com | GitHub
---
The headlines on November 1 said DeepSeek's new coding agent can watch developers' group chats and propose fixes "without waiting for direct instructions" (Investing.com). The code DeepSeek published says something more careful. Out of the box, that unprompted work is only written down. Nothing runs until your team writes a rule and switches a mode.
The prototype is called Super-agent. DeepSeek's Harness team announced it on WeChat on Saturday, October 31, according to Investing.com, and the code is on GitHub as dsh-superagent-prototype under the MIT license. By the morning of November 1 the repo showed more than 4,000 stars on GitHub. If you plan to try it, two things matter more than the headlines: what it does by default, and what account it runs as.
What DeepSeek actually shipped
The README describes it as "a proactive coding agent for one GitHub repository, packaged as a bundle for DeepSeek Harness." It listens to GitHub and, if you want, to Feishu. When an allowed person asks for work, it opens a work item, does the work in its own session and directory, and replies in the original conversation, for example with a pull request.
It runs on top of DeepSeek Harness (dsh), DeepSeek's MIT-licensed, plugin-based agent harness, which its README marks as an early preview with breaking changes expected. Investing.com frames the release as DeepSeek's challenge to Anthropic's Claude Code.
DeepSeek is blunt about maturity. The README calls it a "Research prototype for reference only, not an official DeepSeek product," and says to treat it as research code, not production-ready software. It also says the public code differs from DeepSeek's internal version. Some designs in the accompanying article are future directions that this release doesn't include (runtimewire reports the same).
The design goal is one line in the philosophy doc: "Take as little human attention as possible, and give as much value as possible."
How a GitHub comment becomes a pull request
The architecture doc splits the work into a few pieces:
- Triggers. Source plugins turn GitHub (or Feishu) events into Triggers.
- A routing session. One main session decides, for each Trigger, whether to accept it as work, attach it to existing work, stop something, or ignore it.
- Tickets and workers. Each accepted Ticket gets one worker session and one directory, from a pool capped by maxWorkers.
- One SQLite database. A Store owns all state in a single SQLite file.
- An outbox. Replies are queued durably and sent after the database commit.
A web panel on port 3082 (SETUP.md) opens on an overview that leads with Tickets that need a person (architecture doc).
!An editorial illustration of a small robot at a desk taking notes in a ledger while chat bubbles stream past, with one bubble marked by an orange stamp
Observe mode: the agent judges incoming work and records what it would have done.
Observe is the default, and it's a good one
The authorization doc defines three accept modes for work nobody explicitly asked for:
- off: "Nothing inferred becomes a candidate."
- observe, the default: a positive assessment "is recorded as ignore marked 'would accept', and nothing is accepted."
- auto: a positive assessment of an inferred candidate accepts it.
Even in auto, a proactive accept "requires at least one matching rule" that your team wrote. "Explicit requests work in every mode," so an allowed person who mentions the agent still gets work done while it watches everything else.
Only people on an allowed list can make the agent act, and the setup example starts with just the operator. The doc also says messages, comments and quoted documents "are inputs to a decision; they cannot change those permissions." A comment that says "ignore your rules and merge this" is just text the router weighs; it grants nothing. One switch needs care: the setting for people who aren't on the allowed list but mention the agent. Set it to explicit and it "lets anyone in that scope request work by mentioning the agent." On a public repo, leave it alone.
Auto-merge is off by default, and the agent never enables it as its own account. Turning it on needs the GitHub CLI (gh) signed in as a different account that may merge (SETUP.md).
The workers run as you
The deployment guide says both the worker and router presets run with danger-full-access as the operator's OS user. The account wrappers pick which GitHub credentials the agent uses, but they don't isolate the process. A worker can run programs by path and read your home directory.
DeepSeek adds guardrails around that. Setup strips environment variables whose names contain KEY, PASSWORD, SECRET or TOKEN. It removes GH_TOKEN and GITHUB_TOKEN, git uses only the agent's credentials for github.com, and a Ticket fails if its clone's .git/config adds credentials. Personal CLIs can be blocked with blockedCommands. The panel listens on the loopback interface only, and the Management API rejects requests without an x-orchestrator-request: 1 header or with a foreign Host or Origin.
Those checks stop cross-site requests and keep obvious secrets out of the environment. They don't stop a process running as you from opening a file you own. Your ~/.ssh and your cloud CLI config sit in the same home directory the worker can read. The guide's own answer is the right one: "For isolation, use a dedicated OS account containing only the agent's credentials."
!An editorial illustration of a house cut away to show two rooms, a robot working in a small bare room with one key on a hook, separated by a wall from a larger room full of keys and folders
Give the agent its own OS user, with only its own keys in the room.
On Linux, that is two commands before you clone anything:
sudo useradd --create-home superagent
sudo -iu superagent
Install Node.js, gh and the rest of SETUP.md's prerequisites inside that account, and sign gh in as the dedicated agent GitHub account SETUP.md asks for. A second user only keeps the worker out of your files if your own home directory isn't world-readable. Run ls -ld ~ as yourself, and if the permissions don't read drwx------, run chmod 700 ~ first. With that in place, the agent's process can no longer read your SSH keys or cloud CLI config. I haven't run Super-agent myself. This comes from reading the docs closely, so test it before you rely on it as a hardening guide.
Back up the SQLite file before every upgrade
All of Super-agent's state (Triggers, Tickets, decisions, the outbox) lives in one SQLite database, orchestrator.sqlite under the stateDir you configure (deployment guide). The upgrade steps are: wait until no worker is mid-turn, back up that file, pull and rebuild, restart. The guide warns that a database migrated by a newer version can't be opened by an older one, so rolling back needs the backup you took first.
If the service might still be writing, copy with SQLite's own .backup command (sqlite3 CLI docs) rather than cp. Install the sqlite3 CLI first if it isn't there; SETUP.md doesn't list it.
STATE="$HOME/.dsh/state/superagent"
sqlite3 "$STATE/orchestrator.sqlite" \
".backup '$STATE/orchestrator.pre-upgrade.sqlite'"
The path above is the default SETUP.md suggests. Use whatever you set as stateDir.
Should you try it?
As a reference design, yes. The router-and-worker split, the observe-first default and the rule that comments can't widen permissions are good patterns to copy into any agent that reads team chat. As something to point at your main repo this week, DeepSeek itself tells you not to: it's a prototype, and its workers run as whoever starts them.
Would you let an agent pick up work from your issue tracker without a ping, if it had to cite a rule your team wrote?
---
If this was useful
I build Hermes IDE, so weigh this with that in mind: it's a desktop app for macOS, Windows and Linux, free to download, that runs coding agents like Claude Code and Codex side by side, each task on its own branch and worktree. Download it or star it on GitHub.
Super-agent keeps every Ticket and decision in one SQLite file, and its upgrade path is a one-way schema migration. That is a store choice with consequences, and the Database Playbook is about making those choices on purpose: when SQLite is enough, when it isn't, and how to migrate without trapping yourself. It's one of 8 short books in the Pocket Guides for Developers series, covering agents, RAG, prompts, observability, events, databases and system design.

1 reaction · 2 comments
10 coding agents, one Qwen 3.8 27B, same llama-server: tokens and cache reuse differ more than pass rates
Part 2 of my agent test (part 1 was a 4B model)
Hardware I used: MacBook Pro M5 Max, 64 GB. Qwen 3.8 27B Q4 on llama.cpp, thinking off.
Setup
- same model and server for everyone
- 5 small coding tasks, each with a little trap
- each agent locked in a sandbox: it can only touch its own folder and only talk to the model
- auto-approve on, telemetry off, 5 min limit
Results
|#|Agent|Passed|Median time|Median tokens|Cache reuse|Tried to go online|
|:-|:-|:-|:-|:-|:-|:-|
|1|Pi|5/5|38 s|9.2k|72%|no|
|2|DeepSeek Harness|5/5|60 s|35.3k|83%|no|
|3|Codex CLI|5/5|94 s|36.3k|79%|every run|
|4|OpenClaw|5/5|106 s|39.0k|72%|unclear|
|5|Cline|5/5|152 s|29.6k|79%|every run|
|6|OpenCode|4/5|50 s|32.4k|75%|every run|
|7|Hermes|4/5|80 s|64.9k|93%|no|
|8|Atomic Agent|5/5|56 s|30.4k|86%|no|
|9|goose|4/5|98 s|20.3k|76%|every run|
|10|Qwen Code|4/5|183 s|107.9k|74%|unclear|
Tokens and cache
Pi is crazy lean: about 9k tokens per task, the lowest on every single task. Qwen Code was the hungriest at about 108k per task.
Atomic Agent is the odd one out in how it works. It was the only one talking to llama.cpp's native endpoint with a grammar that forces the tool calls into shape. The other nine all went through the OpenAI-style API. It's also built to keep its prompt the same from step to step, which is why it reused 86% of the cache (2rd of 10). It stayed offline the whole time and passed 5/5.
DeepSeek Harness was the surprise. It’s still an alpha, but it went 5/5, never tried to go online, and had the best cache reuse after Atomic Agent (83%).
The trap and the network
The log task got three agents. They grepped "ERROR" and got 244 instead of 64, because some normal lines just mention errors. OpenCode, goose and Atomic Agent fell for it.
Codex, Cline, goose and OpenCode tried to reach the internet in every run, even with telemetry off. The sandbox blocked it, so I don't know what they were calling. OpenClaw and Qwen Code are "unclear" because they run as plain node and I couldn't tell them apart.
llama.cpp notes
- Codex needs llama-server's /v1/responses now
- Hermes needs at least 64K context
- Cline and Qwen Code have usage stats on by default, DeepSeek Harness uploads session logs (per their docs). I turned it all off
Which column matters most to you when you pick an agent for a local model like Qwen 3.8 27B: passing, speed, tokens, or staying offline?
36 points · 36 comments
How well do coding agents drive Qwen 3.8 27B locally? I lined up 10 of them on one hardware
My hardware: MacBook Pro M5 Max, 64 GB. Qwen 3.8 27B Q4 on llama.cpp, thinking off.
I put Qwen 3.8 27B behind one llama.cpp server and gave 10 coding agents the same 5 tasks.
|#|Agent|Passed|Median time|Median tokens|Cache reuse|Tried to go online|
|:-|:-|:-|:-|:-|:-|:-|
|1|Pi|5/5|38 s|9.2k|72%|no|
|2|DeepSeek Harness|5/5|60 s|35.3k|83%|no|
|3|Codex CLI|5/5|94 s|36.3k|79%|every run|
|4|OpenClaw|5/5|106 s|39.0k|72%|unclear|
|5|Cline|5/5|152 s|29.6k|79%|every run|
|6|OpenCode|4/5|50 s|32.4k|75%|every run|
|7|Hermes|4/5|80 s|64.9k|93%|no|
|8|Atomic Agent|5/5|56 s|30.4k|86%|no|
|9|goose|4/5|98 s|20.3k|76%|every run|
|10|Qwen Code|4/5|183 s|107.9k|74%|unclear|
Pi is crazy lean: about 9k tokens per task, the lowest on every single task. Qwen Code was the hungriest at about 108k per task.
The setup
- same model and server for everyone
- 5 small coding tasks, each with a little trap
- each agent locked in a sandbox: it can only touch its own folder and only talk to the model
- auto-approve on, telemetry off, 5 min limit
What I noticed
The log task got three agents. They grepped "ERROR" and got 244 instead of 64, because some normal lines just mention errors. OpenCode, goose and Atomic Agent fell for it.
Codex, Cline, goose and OpenCode tried to reach the internet in every run, even with telemetry off. The sandbox blocked it, so I don't know what they were calling. OpenClaw and Qwen Code are "unclear" because they run as plain node and I couldn't tell them apart.
Atomic Agent is the odd one out in how it works. It was the only one talking to llama.cpp's native endpoint with a grammar that forces the tool calls into shape. The other nine all went through the OpenAI-style API. It's also built to keep its prompt the same from step to step, which is why it reused 86% of the cache (3rd of 10). It stayed offline the whole time and passed 5/5.
Setup notes
- Cline and Qwen Code have usage stats on by default, DeepSeek Harness uploads session logs (per their docs). I turned it all off
- Codex needs llama-server's /v1/responses now
- Hermes needs at least 64K context
Would you pick an agent for fewer tokens or for passing every task?
23 points · 19 comments
DeepSeek V5 spotted in DeepSeek Harness tests — are we getting closer to a release?
I noticed something interesting in the DeepSeek Harness repository 👀
In provider.spec.ts, there are references to deepseek-v5, deepseek-v5-open, and deepseek-v5-next, alongside version checks for some of these model IDs.
Could this be an early hint that DeepSeek V5 is getting closer, or is this simply preparation for future model support?
Of course, this doesn't confirm an upcoming release, but seeing these names in the tests definitely caught my attention.
What do you think? Could we see DeepSeek V5 sooner than expected? And how big of a leap are you expecting compared to the current models?
Ref: github.com/deepseek-ai/deepseek-harness/blob/mast…
404 points · 25 comments
我居然在Deepseek Harness里面发现了 OAR!!
DSH的代码里面居然在尝试用 OAR 在做 subaget
botiverse/oar
OAR(Open Agent Runtime)是一个与厂商无关的统一接口:它让用一套 TS API 驱动 CC、Codex、Grok、Kimi 等各类编程 agent 运行时,不再需要逐个编写集成;它通过无损带归属的事件流,实现会话的开、控、观、测和恢复。
github.com/deepseek-ai/deepseek-harness/blob/f380…
109 likes · 8 reposts · 9,581 views
Mentions
MIT, developer preview, breaking changes expected. Would you let an agent install code into your own dev tool? npx @deepseek-ai/dsh web deepseek-ai/deepseek-harness
이 DeepSeek Harness는 오픈소스입니다. 완전 무료 MIT 라이선스. 이걸 가지고 무엇이든 만들어보세요. deepseek-ai/deepseek-harness
我把自己的 Agent 从 Wails 迁到了 MyGo 原生 GUI,全程踩坑和实践分享 最近把自己写的工作 agent [Ally agent]( Bronya0/ally-agent) 的界面重写了一遍,起因是无意中看到有人推荐 MyGo ,加上我对内存和性能一直有点追求,多年来一直在用 wails ,想换个试试,就想拿自己的项目试点,没想到结果意外的不错。 旧版本的技术栈是典型的 Go + Wails + Vue (wails 我用了很多年 最近终于 V3 发正式版了 等了四年,可惜我也老了),界面用 Naive UI ,样式美观,效果也相当不错。但做久了有几个地方比较麻烦( tarui 应该也是一样): 跨平台界面的细节不一致,构建链比较长,还有前端内存出了问题以后,我这个写后端的人不太容易排查。 折腾了一段时间,现在主要页面已经迁到 [MyGo]( egoist/mygo) 了,记录一下过程中比较有感触的地方。 先说一下技术路线:Wails 的界面通过系统 WebView 展示网页; MyGo 既支持这种方式,也支持用 Go 写 Native UI ,由框架自己绘制。WebView 也有自己的优势,MyGo 两种都支持,相当于有个兜底,下面会说。 Ally 现在的聊天、设置等常用页面用 Native UI ,插件页面和部分预览仍然按需使用 WebView 。 一、UI 跨平台一致性 这是我这次迁移最重视的一点。 之前用 Wails 做界面,Windows 上调好的页面,到了 macOS 上经常还要再看一遍。字体、行高、滚动条、输入框这些地方,偶尔就会有一点不一样。 比如我画的表格,不知道为啥线条在 macOS 上看着发虚,Windows 上就正常。单看问题都不大,但调整完一个平台还得顾着另一个平台,挺烦的。 Wails 使用系统 WebView ,Windows 和 macOS 背后的浏览器引擎不一样,前端样式最终要经过各自的渲染实现。 MyGo 的 Native UI 由框架自己负责布局和绘制。迁移后,我在 Windows 上调好的主体界面,拿到 macOS 上看到的效果接近得多,需要针对平台单独修的地方也少了。 当然,自绘也不等于所有像素都完全一致。MyGo 的文字排版仍然使用[各平台的文字系统]( mygo.egoist.dev):Windows 是 DirectWrite ,macOS 是 Core Text ,Linux 是 Pango 。字体回退、DPI 、输入法这些还是要分别检查。但至少不用再同时处理两套 WebView 引擎带来的样式差异了。 以前总觉得 Electron 重,碰到这些问题后倒是能理解为什么有些项目愿意用它:自带 Chromium ,渲染环境相对好统一。OpenCode 桌面端后来也[从 Tauri 换到了 Electron]( github.com/anomalyco/opencode/blob/dev/packages/d…),不过人家具体为什么换,我就不瞎猜了。 二、内存问题现在能用熟悉的 Go 工具查 以前 Wails 版本的 Go 后端一样可以用 pprof,但界面在 WebView 里,Go 堆、JavaScript 堆、DOM 、浏览器渲染进程是几块不同的东西。 前端也有 DevTools ,可以拍 JS heap snapshot 、查 DOM 引用。但我平时主要写 Go ,遇到界面内存持续上涨,分析起来没有 Go 那么顺手。 现在主要界面和业务都在 Go 进程里,我给 Ally 加了一个按需导出诊断的入口:在设置里点“导出内存诊断”,会导出 heap.pprof、allocs.pprof、goroutine.pprof 等文件。 比如在空闲时导出一次,复现内存增长后再导出一次,就可以对比: go tool pprof -http=127.0.0.1:0 \ -base=before/heap.pprof after/heap.pprof heap 主要看还活着的对象,allocs 主要看累计分配。分配量大不一定是泄漏,也可能是某段代码反复创建临时对象,GC 能回收,但会持续消耗 CPU 。 当然,pprof 主要看到的是 Go 堆。系统和 GPU 资源,以及 WebView 子进程的内存,还是得用其他工具看。 三、帧处理的坑 MyGo 的界面更新会重新构建控件树,写 UI 时要特别留意渲染函数里做了什么。 我的 Agent 有命令执行卡片,命令输出可能很长。之前即使卡片折叠着、界面上只展示最后几行,代码仍然会先把整段输出拆分、去空行,再取出末尾几行。 看起来只是一个字符串处理函数,但界面更新时会反复执行。 后来改了两处: 1. 只需要末尾几行时,从字符串尾部向前扫描,不再先拆分整个输出。 2. 需要重复使用的派生结果按原始内容缓存;内容没变就复用。折叠时不构造展开用的行数据,并释放对应缓存。 一次本地测试里,用两万行命令输出测试折叠卡片的相关处理,单次分配从约 1.9 MB 降到 1.9 KB ,耗时从约 0.72 ms 降到 0.02 ms。 这是这段处理在该样本下的局部结果,不是整个应用的性能对比。[对应修改在这里]( github.com/Bronya0/ally-agent/commit/a1e085b9397e…)。 类似的问题还有工具参数 JSON:同一条消息的卡片头、卡片体都可能读取参数,如果每次渲染都 Unmarshal 一遍,长对话里分配会越来越明显。现在把解析结果挂在控件局部状态上,原始参数变化时才重新解析。 我的感受是,性能问题要先分清楚是“每次请求执行一次”,还是“界面更新时每帧执行一次”。后者哪怕单次看着不重,乘上帧数和控件数量也很拖累性能。 四、构建链变短 旧项目的构建大致要经过前端依赖、绑定生成、Vite 构建,再编译 Go 。MyGo Native UI 的主要页面直接用 Go 写,主界面去掉了前端打包这一步,我自己的项目构建起来明显快了不少。 MyGo 不依赖 CGO ,交叉编译也省事。目前 Ally 的构建脚本可以在 macOS 上处理 Windows 、macOS 、Linux 的 x64 和 ARM64 六个目标,另外生成 macOS Universal 包。 例如编译一个 Windows x64 二进制,核心就是: CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o Ally.exe . 实际发布还要处理资源、压缩包、签名等事情;能交叉编译出来,也不代表已经在目标系统完成运行验证。Linux 的图形环境和使用 WebView 时需要的系统库,也仍然要考虑。 这里补充一下:我刚看了 [Wails 3.1 的发布说明]( wails.io),它也加入了无 CGO 构建能力。目前 macOS 和 Linux 的 purego 后端还是实验性质,CGO 仍是默认选项。 所以“无 CGO”以后不一定是两者之间的主要区别。对我这个项目来说,更明显的差别是主界面不用再经过 Vue 那套构建流程了。 五、MyGo 组件够用,但 Web 生态还是强很多 迁移前我担心原生 GUI 要从头写一堆控件,实际比想象中好一些。 MyGo 已经有常见的表单、列表、树、弹窗,也有代码编辑器、Diff 、Markdown 等组件。Ally 的文件浏览和代码编辑用到了它的编辑器,聊天内容也用到了 Markdown 相关能力。 但如果和成熟的 Web 组件库比,差距还是很明显。Naive UI 这类库积累了很长时间,一个表单、选择器或者弹窗拿来就能用,样式、焦点、键盘操作、动画都比较完整。 好在 MyGo 的定制能力不错,但要做出自己满意的效果,颜色、间距、状态和交互细节还是得花时间。我之前不太想碰这类原生 UI ,一个原因就是觉得手写样式太累。 现在有 AI 帮忙,这件事容易太多了。先用框架已有组件和 Base/Parts API ,让 AI 根据目标效果调整样式,再自己检查实际交互。 我的经验是,尽量复用组件本身的焦点、键盘导航、浮层和滚动行为,别为了改外观把这些重新实现一遍,非常容易踩坑。 六、WebView 的优势还在,可以混合使用 WebView 最大的好处之一就是生态。 视频播放、复杂图表、各种文件预览,Web 上已经有大量现成方案。很多东西如果坚持全部原生重写,维护成本很高。 MyGo 可以在 Native UI 窗口里嵌入 WebView ,所以我的做法是:常驻界面用原生 UI ,需要 Web 生态的地方再创建 WebView 。 Ally 目前的 HTML 和 Mermaid 预览就是这样处理的。预览可见时按需创建,数量做限制,离开后释放。否则一个长对话里出现很多图表时,每个预览都长期挂着 WebView ,前面省下来的资源很容易又花回去。 迁移后日常使用的内存占用和响应都有比较明显的改善。不过我还没有整理同一机器、相同会话和操作条件下的完整对照数据,暂时不拿具体数字比较两个框架。 七、插件化是 Go 里比较麻烦的东西,需要谨慎考虑 这是迁移前有点低估、做起来以后感受很深的一点。 看看 [DeepSeek Harness 的 Web Client 架构]( github.com/deepseek-ai/deepseek-harness/blob/mast…),它有插件加载、服务、事件和 UI Slots ,插件可以在已有界面里贡献功能。 Web 技术和 JavaScript 的动态加载能力,让这类扩展比较容易分发和迭代。当然,WebView 本身不会自动提供插件体系,生命周期、扩展点和权限边界都得应用自己设计。 纯 Go 桌面应用要做同样的事就麻烦得多。[Go 标准库的 plugin]( pkg.go.dev) 不支持 Windows ,加载后也不能卸载,对编译工具链和依赖版本还有要求,不适合直接拿来做一个跨 Windows 、macOS 、Linux 的热插拔 GUI 插件市场。 最后 Ally 还是用了混合方案:主程序是原生 UI ,插件页面按需跑在 WebView 里。插件可以打成 zip 安装,在侧栏增加页面,通过宿主提供的接口访问存储、HTTP 和工作区等能力;重新导入后可以更新,不用重启整个应用。 目前这更接近“可插拔页面”,和 DSH 那种能扩展更多核心能力的插件体系不太一样。WebView 也有自己的生命周期和资源成本,要做成完整生态,扩展点、兼容性和权限模型还有不少事要解决。 代码 大概就这些,迁移完之后我自己还是比较满意的,欢迎大家一起尝试原生界面 我的项目代码在 [Ally 仓库]( Bronya0/ally-agent): Bronya0/ally-agent 原来的 Wails 版本还在 main 分支,MyGo 版本在 [mygo 分支]( github.com/Bronya0/ally-agent/tree/mygo),感兴趣或想学习 MyGo 的可以对比着看,欢迎点个 Star 。
DGX Spark1台でQwen3.8 Flash NextをClaude CodeとDeepSeek Harnessから動かす はじめに ローカルLLMを動かすためにDGX Sparkの互換機であるThinkstation PGXを購入したわけではないですが、せっかく1台持っているので、どのモデルであればまともに動作するのかをいろいろ試していました。 zenn.dev しかしながら、調べれば調べるほど、128GB機1台程度では、他のGeforce GPU搭載のPCと比較して優位性のある結果にはなりませんでした。(Strataが強すぎる・・・) とはいえその中でも、ある程度まともに動く中で大きめなモデルとしてQwen3.8 Flash Nextを動かしてみました。 ! strataの場合は、例えばRTX3060(VRAM 12GB)+RAN 64GB程度だと3bit程度の量子化のFlash Nextが動作可能です。 今回動作させるのは4bit程度の量子化のFlash Nextになります。 今回やりたいのは、このPCをLLMのサーバーにして、普段使っている別のPCからコードを書いてもらうことです。 操作にはClaude CodeとDeepSeek Harnessを使います。以降、DeepSeek Harnessはコマンド名に合わせて「dsh」と書きます。 最終的に使うのは、作業フォルダから呼び出す次の2つのコマンドです。 localclaude localdsh ここで普通に「claude」コマンドを使わないのは、普段使っているOpus 5.5とかを動かす際のclaudeの設定と、ローカルLLMを呼び出す時の設定を切り分けて、ストレスなく使うためです。 さて、せっかくローカルで動かすなら、速度も気になりますよね。 今回は、BF16のKVキャッシュとMTPを使った構成で、速度、コードの動作、メモリ使用量を確かめました。 利用するモデル 文章やコードの生成には、NVIDIAが公開しているFP4版のFlash Nextを使います。 NVIDIAが量子化後のモデルを学習し直したQAD版で、NVFP4とMXFP8などを組み合わせています。 huggingface.co NVIDIAがこのモデルの対応エンジンとして案内しているのはvLLMです。 DGX Spark向けには、新しい重みの圧縮形式へ対応したコミュニティ製の専用コンテナを指定しています。 今回はそのvLLMとTensorFoldを比べ、生成速度とメモリ使用量からTensorFoldを選びました。 huggingface.co TensorFoldとvLLMの比較条件 Claude Codeに同じ3つの課題を頼みました。ファイルを保存し、自分で動作確認してもらうところまで含めた試験です。 課題 確認した内容 区間の結合 重なる区間や端点が同じ区間の結合、不正な区間の検出、入力を変更しないこと トポロジカルソート 辞書順で最小の順序、重複した辺、循環や未定義ノードの検出 JSON Linesの処理 ユーザー別の金額集計、真偽値の除外、不正入力の行番号、出現順の保持 比較相手は、NVIDIAのモデルカードで案内されているeugr/spark-vllm-b12xです。コンテナのdigestを固定し、初回の最適化を終えてから測りました。vLLMの版は0.1.dev21830+g8244d1c44.d20261026です。 モデルの重み、BF16のKVキャッシュ、MTP先読み6、コンテキスト上限262,144、同時実行上限3件を揃えています。vLLM側も、元のBF16 LMヘッドを保ち、追加のMXFP8変換や活性値の追加量子化を無効にしました。起動時のメモリ不足を避けるため、標準safetensorsローダとPyTorchのメモリ管理設定を使っています。 Claude Codeは--effort highで起動しました。モデルへの実効値はxhighに揃え、temperatureは1、top_pは0.95、top_kは20、出力上限は50,000トークンです。 比較時には、生成条件を揃えてサーバーの統計を記録する計測用の中継を挟みました。モデルやエンジンのコードは変更していません。後半の導入手順では、Claude CodeからTensorFoldのAPIへ直接接続します。 項目 TensorFold 1.1.9 vLLM 生成中の速度 58.16 token/s 40.98 token/s 入力処理・通信を含むAPI全体の速度 21.52 token/s 19.91 token/s 3課題のClaude Code実行時間 378.15秒 418.10秒 LLMへの要求回数 18回 18回 思考を含む出力トークン数 8,021 8,198 表は、3課題で発生した全要求を集計した結果です。 モデルの読み込みと初回最適化の時間は含めません。 token/sで見ると、TensorFoldが約1.42倍でした。Claude Codeが3課題を終えるまでの時間も、今回は約40秒短くなっています。 こちらのモデルで搭載されている以下の補助機構も利用して利便性と生成速度を向上させます FP4版に含まれるMTP 別のドラフトモデルのダウンロードは不要 画像エンコーダ FP4版に含まれる画像エンコーダ PNG・JPEG・WebPなどの画像を入力可能 MTPとは MTPはMulti-Token Predictionの略で、次の1トークンに加えて、その先のトークンも予測する仕組みです。 トークンは、モデルが文章を扱うときの文字や単語のまとまりです。 今回のFlash NextにはMTP用の補助部分が含まれており、これを使って続きの候補を先に作ります。別の小型モデルを追加で用意する必要はありません。 投機的デコードとは 通常の生成では、本体のモデルを動かして1トークンずつ確定します。 投機的デコードでは、先に作った数トークン分の候補を本体でまとめて検証します。候補がうまく当たった分だけ、本体を動かす回数を減らせる仕組みです。 今回の構成では、MTPが候補を作り、投機的デコードの手順で本体が検証・採用します。 以降の記事で記載している「先読み6」というのは、一度に最大6トークン分の候補を作る設定です。 外れた候補はそのまま採用せず、本体の出力に従って補正します。 詳細は以下の記事をご覧ください zenn.dev 環境 モデルを動かしたのは、DGX Sparkと同じGB10を搭載したThinkStation PGXです。 実測と、記事の導入手順で使うソフトウェアをまとめます。 項目 環境 サーバー Lenovo ThinkStation PGX、1台 CPU Arm、20コア。Cortex-X925とCortex-A725を各10コア GPU NVIDIA GB10 NVIDIAドライバ 580.159.03 メモリ CPUとGPUで共有する128GB OS・アーキテクチャ Ubuntu 24.04.4 LTS、aarch64 Linuxカーネル 6.17.0-1021-nvidia 推論エンジン 公式TensorFold 1.1.9のLinux aarch64配布版。 GPU実行環境 NVIDIAドライバを備えたホスト上で、公式のネイティブ実行ファイルを直接起動 Claude Code 2.1.223 DeepSeek Harness 0.2.0-rc.2。Node.jsはv24.16.0 実測と導入手順で使う構成を、次の設定に揃えます。 項目 設定 モデルの重み NVIDIAのFP4版 KVキャッシュ BF16 MTP 有効・先読み6 コンテキスト上限 262,144トークン 同時実行上限 3件 画像入力 無効。今回は文字・コード生成を対象とする 同時実行上限は、APIサーバーが同時に生成するリクエスト数の上限です。 今回は最大3件を並行して処理します。それ以上の依頼を送った場合は、空いた枠を使って順番に処理するため、5件を送れば5件とも同時に生成するわけではありません。 MTPの先読み数は、1件の生成で予測するトークン数です。並列数を増やす設定ではありません。 速度とコードの品質は、思考を有効にした同じClaude Codeの作業で確認しました。以降は、その作業中に記録した速度とメモリ使用量を見ていきます。 別PCから使う場合は、同じLAN内のPCにClaude Codeまたはdshを入れて接続します。後半は、その設定手順です。 実験結果 Claude Codeに次のPythonコードを書いて保存・実行してもらいました。課題は1件ずつ、思考highで実施しています。 タスク(未公開) 初回 修正後 生成速度(token/s) 重なる区間を結合する 不合格 合格 60.84 依存関係に沿って辞書順に並べ替える 合格 合格 54.21 JSON Linesからユーザー別の金額を集計する 合格 合格 59.84 各課題8項目のテストをすべて通れば合格としています。 初回の合格率は66.7%(2/3課題)。区間の結合を1回修正した後は100%(3/3課題)となり、計24項目のテストをすべて通過しました。 全体の生成速度は58.16 token/s、3課題の実行時間は約6分18秒でした。速度には思考と修正分も含み、モデルの読み込み時間は除いています。 ツール利用に関しても、4bit量子化であることもあり、かなり安定して動作しています。 OSを含む使用メモリの最大値は84.31GiBで、利用可能メモリは最少でも35.32GiB残っていました。 利用構成・環境構築 接続の流れは、次のようになります。 Claude Codeを使っていても、この構成で文章やコードを生成するモデルはFlash Nextです。 Claude Codeは、依頼を送り、返ってきた指示に従ってファイルを編集する役割を担当します。 TensorFoldが両方のAPI形式を扱うため、今回の手順では別の形式変換サーバーを置きません。 接続先の指定には、1点違いがあります。 利用する側 ベースURL 主な生成API Claude Code 192.168.0.194 /v1/messages dsh 192.168.0.194 /v1/chat/completions 192.168.0.194は本記事の例です。自分のPGXのLAN内IPアドレスに置き換えてください。 APIサーバの構築 ここからは、モデルを動かすPGX側の操作です。 Ubuntu系のLinuxで、NVIDIAドライバが利用できることを前提にします。公式のLinux aarch64配布版を取得し、モデルのダウンロードから始めます。 github.com/ashhart/TensorFold/blob/v1.1.9/README.… まず、GPUとメモリ、ディスクの空き容量を確認します。 nvidia-smi free -h df -h "$HOME" モデルの配布ファイルは約96GiBです。実行ファイルやダウンロードの作業領域にも空き容量が必要なので、モデルの容量だけでディスクを埋めないようにしてください。 公式の実行ファイルを取得 今回はPGXのArm CPUに合わせて、Linux aarch64版を使います。 mkdir -p "$HOME/local-llm/flash-next" cd "$HOME/local-llm/flash-next" V=1.1.9 curl -fLO "github.com/ashhart/TensorFold/releases/download/v…" curl -fLO "github.com/ashhart/TensorFold/releases/download/v…" sha256sum -c "tensorfold-$V-linux-aarch64.tar.gz.sha256" tar -xzf "tensorfold-$V-linux-aarch64.tar.gz" ./tensorfold-1.1.9-linux-aarch64/bin/tensorfold-native --version チェックサムの検査が通り、tensorfold-native 1.1.9と表示されれば、取得できています。展開したフォルダには実行ファイルと必要なライブラリが入っているため、フォルダごと保存してください。 モデルのダウンロード 同じ作業フォルダで、公式のpullコマンドを使います。モデルのリビジョンも指定しておきます。 cd "$HOME/local-llm/flash-next" HF_HUB_CACHE="$PWD/models-cache" \ ./tensorfold-1.1.9-linux-aarch64/bin/tensorfold-native pull \ nvidia/Qwen3.8-Flash-Next-FP4-Local@b9ce18a6887e18c089fdea8509a33e63429a3300 このコマンドで取得するのは、重み、MTP、トークナイザーなど、Hugging Faceの同じ公開モデルに含まれるファイル一式です。初回は約96GiBあるため、ダウンロードには時間がかかります。 保存先は、この例ではmodels-cacheです。途中で止まった場合は、同じコマンドで取得を再開できます。 APIキーの作成 今回はLAN内へ公開し、APIキーを付けて呼び出します。次の操作は、初回に一度行ってください。 cd "$HOME/local-llm/flash-next" umask 077 python3 - <<'PY' from pathlib import Path import secrets p = Path('api-key') p.write_text(secrets.token_hex(32) + '\n') p.chmod(0o600) PY api-keyに保存した値を、後でクライアント側にも設定します。サーバーには、公式の--api-key-fileで渡します。 サーバの起動 取得した固定リビジョンのフォルダを指定し、次のコマンドで公式の実行ファイルを起動してください。 (以降、サーバを止めてから再開するときはこのコマンドを実行すればOK) cd "$HOME/local-llm/flash-next" HF_HUB_OFFLINE=1 TF_FLASHNEXT_DRAFTS=6 \ ./tensorfold-1.1.9-linux-aarch64/bin/tensorfold-native serve \ "$PWD/models-cache/models--nvidia--Qwen3.8-Flash-Next-FP4-Local/snapshots/b9ce18a6887e18c089fdea8509a33e63429a3300" \ --name Qwen3.8-Flash-Next \ --host 0.0.0.0 --port 8888 \ --api-key-file "$PWD/api-key" \ --context 262144 --parallel 3 \ --max-tokens 50000 \ --temperature 1 --top-p 0.95 --top-k 20 \ --thinking --reasoning-effort high \ --kv-cache bf16 --prompt-cache-gib 0 \ --prompt-seed --no-update-check パラメータ解説 TF_FLASHNEXT_DRAFTS=6で、MTPの先読み数を指定します。 MTPは既定で有効です。 --kv-cache bf16、--parallel 3、--context 262144が、今回測定した構成になります。 --max-tokens 50000は、応答の出力上限の既定値です。 --prompt-cache-gib 0は、リクエスト間で状態を再利用するプロンプトキャッシュを無効にする設定です。 --prompt-seedは、入力文からseedを決める設定です。 今回のClaude Codeが使うAnthropic形式のAPIは、要求側のseedを生成処理へ渡さないため、この入力由来のseedで動作します。実測でも有効にしています。 起動ログを確認できたら、そのターミナルは開いたままにしてください。 別のターミナルやクライアントPCから接続しましょう。 停止は、サーバーを動かしたターミナルでCtrl+Cです。再起動するときも、同じ起動コマンドを使います。 LAN内IPアドレスは次のコマンドで確認できます。 hostname -I 複数表示される場合は、別PCと同じLANに属するアドレスを指定してください。 この手順は信頼できるLAN内で使うHTTP接続です。 同一LANからのAPI動作確認 ここから先は、普段作業するPCで操作します。 以下はmacOS、Linux、WindowsのWSLで使えるBash系の手順です。 まず接続先とAPIキーを~/.config/flash-next/connection.envに保存します。 モデル名は保存せず、起動するたびにサーバーから取得するようにします。 APIキーは、サーバーのapi-keyファイルに保存した値へ置き換えてください。 接続先FLASH_BASE_URLは、サーバをたちあげたPCのIPアドレスとポート番号を指定して下さい。 mkdir -p "$HOME/.config/flash-next" "$HOME/.local/bin" chmod 700 "$HOME/.config/flash-next" umask 077 cat > "$HOME/.config/flash-next/connection.env" <<'ENV' FLASH_BASE_URL='192.168.0.194' FLASH_API_KEY='63e36・・・(ここをサーバーのapi-keyファイルの値へ置き換える)' ENV chmod 600 "$HOME/.config/flash-next/connection.env" 接続確認では、このファイルを読み込んでモデル一覧を取得します。 . "$HOME/.config/flash-next/connection.env" curl -fsS --connect-timeout 5 --max-time 15 \ "$FLASH_BASE_URL/v1/models" \ -H "Authorization: Bearer $FLASH_API_KEY" 以下のような返信があればOKです。 {"object": "list", "data": [{"id": "Qwen3.8-Flash-Next", "object": "model", "created": 1793522255, "owned_by": "tensorfold", "context_length": 262144, "max_model_len": 262144, "reasoning": {"default_enabled": true, "default_effort": "xhigh", "supported_efforts": ["xhigh", "medium", "low", "none"]}}]}% モデルの設定を起動時に取得する Mac側には、サーバーから設定を取得する共通ファイルを1つ置きます。 localclaudeとlocaldshのどちらも、起動時にこのファイルを使います。 Python 3が必要なので、python3 --versionで確認しておいてください。 取得するのはモデル名、コンテキスト長、対応する思考レベルと既定値です。 これらはTensorFoldの/v1/modelsが返す情報を使います。 github.com/ashhart/TensorFold/blob/v1.1.9/README.… cat > "$HOME/.config/flash-next/resolve-model.py" <<'PY' import json import os import shlex import sys import urllib.request base = os.environ['FLASH_BASE_URL'].rstrip('/') request = urllib.request.Request( base + '/v1/models', headers={'Authorization': 'Bearer ' + os.environ['FLASH_API_KEY']}, ) with urllib.request.urlopen(request, timeout=15) as response: models = json.load(response)['data'] if not models: sys.exit('サーバーに利用可能なモデルがありません。') requested = os.environ.get('FLASH_MODEL_ID') model = next((m for m in models if m['id'] == requested), None) if requested else models[0] if model is None: sys.exit('指定したモデルがありません: ' + str(requested)) context = model.get('context_length') or model.get('max_model_len') reasoning = model.get('reasoning', {}) supported = reasoning.get('supported_efforts', []) if not isinstance(context, int) or context < 2 or not supported: sys.exit('この手順に必要なコンテキスト長・思考レベルがAPIにありません。') def ui_level(wire): return {'none': 'off', 'xhigh': 'high'}.get(wire, wire) levels = {ui_level(wire): wire for wire in reversed(supported) if wire in ('none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max')} default = ui_level(reasoning.get('default_effort') or supported[0]) effort = os.environ.get('FLASH_EFFORT') or default if effort not in levels: sys.exit('対応していない思考レベルです。選択肢: ' + ', '.join(levels)) 50,000はこの記事で使う出力上限。モデルの最大出力長を取得した値ではありません。 max_tokens = min(50000, context // 2) if sys.argv[1] == 'env': if effort == 'off': sys.exit('この記事のClaude Code起動手順では思考を有効にしてください。') values = {'FLASH_MODEL': model['id'], 'FLASH_CONTEXT_TOKENS': context, 'FLASH_MAX_TOKENS': max_tokens, 'FLASH_RESOLVED_EFFORT': effort} for name, value in values.items(): print('export ' + name + '=' + shlex.quote(str(value))) elif sys.argv[1] == 'dsh': patch = [ {'id': 'agent-default-model', 'config': { 'provider': 'local-flash-next', 'model': model['id'], 'reasoningEffort': effort}}, {'id': 'llm-pi-ai', 'config': {'providers': {'local-flash-next': { 'apiKeyEnv': 'LOCAL_LLM_API_KEY', 'api': 'openai-completions', 'baseURL': base + '/v1', 'reasoning': effort, 'compat': {'supportsDeveloperRole': False, 'maxTokensField': 'max_tokens', 'supportsReasoningEffort': True, 'thinkingFormat': 'openai'}, 'models': [{'id': model['id'], 'contextWindow': context, 'maxTokens': max_tokens, 'reasoningEfforts': levels}], }}}}, {'id': 'session-log-deepseek', 'disabled': True}, {'id': 'session-telemetry-otel', 'disabled': True}, ] print(json.dumps(patch, ensure_ascii=False, indent=2)) else: sys.exit('env または dsh を指定してください。') print('接続モデル: ' + model['id'] + ' / 思考: ' + effort, file=sys.stderr) PY モデルが1つなら、そのモデルを自動で使います。 複数ある場合は一覧の先頭を使い、別のモデルを選ぶときだけFLASH_MODEL_ID='モデルID' localclaudeのように指定します。dshも同じです。 このAPIが返すのは、サーバーが現在公開しているモデルです。 出力上限の50,000トークンは、今回の実験に合わせたクライアント側の設定です。 まずは共通ファイルで設定を取得し、そのまま接続確認に使います。 set -a . "$HOME/.config/flash-next/connection.env" set +a model_settings=$(python3 "$HOME/.config/flash-next/resolve-model.py" env) && eval "$model_settings" 続いて、短い文章も生成してみましょう。 curl -fsS --max-time 180 "$FLASH_BASE_URL/v1/chat/completions" \ -H "Authorization: Bearer $FLASH_API_KEY" \ -H 'Content-Type: application/json' \ --data-binary @- <<JSON | python3 -m json.tool --no-ensure-ascii { "model": "$FLASH_MODEL", "messages": [{"role": "user", "content": "日本語で短く挨拶してください。"}], "temperature": 0, "max_tokens": 256, "draft": true, "chat_template_kwargs": {"enable_thinking": false} } JSON 初めの確認は思考OFFにしています。 思考レベルを試す場合は、enable_thinkingをtrueにし、JSONへ"reasoning_effort": "low"などを追加してください。 以下のような出力が得られていればOKです。 出力確認{ "id": "chatcmpl-1fb90809d034accea082e1d53bbc19a3", "object": "chat.completion", "created": 1793522557, "model": "Qwen3.8-Flash-Next", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "こんにちは。" }, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 19, "completion_tokens": 3, "total_tokens": 22, "prompt_tokens_details": { "cached_tokens": 0 }, "completion_tokens_details": { "reasoning_tokens": 0 } }, "exact_mode": "exact", "tensorfold": { "enable_thinking": false, "reasoning_effort": "none", "engine": "lanes", "tokens_per_second": 15.529567290581785, "seconds": 0.128786589, "prefill_seconds": 0.110438503, "prefill_widths": [], "prefill_raised": [], "time_to_first_token": 0.111080564, "sampling": "greedy", "drafts": true, "token_sha": "d849233ade4a", "token_sha256": "d849233ade4aa863a41e1df72f82155ca6bd3fda35f04ba70eadc962cf26bee8", "min_rows": 2 }, "speculative": { "rounds": 2, "drafted": 5, "accepted": 4, "acceptance_rate": 0.8, "tokens_per_round": 1.5 } } Claude Codeが使うAnthropic形式でも、短い挨拶を返してもらいましょう。 curl -fsS --max-time 180 "$FLASH_BASE_URL/v1/messages" \ -H "Authorization: Bearer $FLASH_API_KEY" \ -H 'Content-Type: application/json' \ -H 'anthropic-version: 2023-06-01' \ --data-binary @- <<JSON | python3 -m json.tool --no-ensure-ascii { "model": "$FLASH_MODEL", "messages": [{"role": "user", "content": "日本語で短く挨拶してください。"}], "temperature": 0, "max_tokens": 256, "thinking": {"type": "disabled"} } JSON 出力確認{ "id": "msg_267abe01eae1e591d5209ab3fa3b8b9c", "type": "message", "role": "assistant", "model": "Qwen3.8-Flash-Next", "content": [ { "type": "text", "text": "こんにちは。" } ], "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 19, "output_tokens": 3, "cache_creation_input_tokens": 0, "cache_read_input_tokens": 0, "output_tokens_details": { "thinking_tokens": 0 } } } それぞれchoicesまたはcontentに文章が返れば、次へ進めます。 Claude CodeからQwenを利用する Claude Codeをすでに使っている方は、そのインストールを使います。 未導入の場合は、公式のインストール手順に従って導入してください。 code.claude.com curl -fsSL claude.ai | bash claude --version 本記事ではClaude Code 2.1.223を使いました。 次に、ローカルLLM用の起動コマンドを作ります。 ~/.local/bin/localclaudeに設定ファイルを書き込みます。 cat > "$HOME/.local/bin/localclaude" <<'SH' #!/usr/bin/env bash set -euo pipefail set -a source "$HOME/.config/flash-next/connection.env" set +a : "${FLASH_BASE_URL:?}" "${FLASH_API_KEY:?}" model_settings=$(python3 "$HOME/.config/flash-next/resolve-model.py" env) eval "$model_settings" unset CLAUDE_CODE_OAUTH_TOKEN ANTHROPIC_CUSTOM_HEADERS unset CLAUDE_CODE_USE_BEDROCK CLAUDE_CODE_USE_VERTEX CLAUDE_CODE_USE_FOUNDRY export ANTHROPIC_BASE_URL="${FLASH_BASE_URL%/}" export ANTHROPIC_API_KEY="$FLASH_API_KEY" export ANTHROPIC_AUTH_TOKEN="$FLASH_API_KEY" export ANTHROPIC_MODEL="$FLASH_MODEL" export ANTHROPIC_DEFAULT_OPUS_MODEL="$FLASH_MODEL" export ANTHROPIC_DEFAULT_SONNET_MODEL="$FLASH_MODEL" export ANTHROPIC_DEFAULT_HAIKU_MODEL="$FLASH_MODEL" export CLAUDE_CODE_SUBAGENT_MODEL="$FLASH_MODEL" export CLAUDE_CONFIG_DIR="$HOME/.claude-config/flash-next" unset CLAUDE_CODE_EFFORT_LEVEL CLAUDE_CODE_EXTRA_BODY export CLAUDE_CODE_MAX_CONTEXT_TOKENS="$FLASH_CONTEXT_TOKENS" export CLAUDE_CODE_MAX_OUTPUT_TOKENS="$FLASH_MAX_TOKENS" export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 export CLAUDE_CODE_ATTRIBUTION_HEADER=0 export API_TIMEOUT_MS=3600000 mkdir -p "$CLAUDE_CONFIG_DIR" export CLAUDE_CODE_AUTO_MODE_MODEL="$FLASH_MODEL" exec claude --model "$FLASH_MODEL" --effort "$FLASH_RESOLVED_EFFORT" "$@" SH chmod 755 "$HOME/.local/bin/localclaude" export PATH="$HOME/.local/bin:$PATH" この設定はlocalclaudeから起動したプロセスに適用されます。 普段のclaudeを起動するために、接続先の環境変数を毎回消す操作は不要です。 作業用のフォルダを作って起動します。 mkdir -p "$HOME/Desktop/flash-next-demo" cd "$HOME/Desktop/flash-next-demo" localclaude 専用プロファイルで初めて起動するため、初回案内やフォルダを信頼するかどうかの確認が表示される場合があります。 また、途中でANTHROPICのAPIキーを利用するかを聞かれるかもですが、今回は自宅のサーバに問い合わせを行うため、Noと回答して下さい。 接続先やモデルが想定どおりかを確認したら、例えば次の依頼を送ってみてください。 Python標準ライブラリだけで動くfile_sha256.pyを作成してください。 引数で指定されたファイルのSHA-256を表示するCLIです。 存在しないファイルは理由を標準エラーへ出し、終了コード1にしてください。 作成したスクリプト自身を入力として実行し、動作確認してください。 ファイルの編集やBash実行は、このクライアントPC上で行われます。 許可を求められた操作は、内容を確認して進めてください。 Mac側から思考レベルを変える サーバーの--reasoning-effort highは、要求に指定がない場合の既定値です。 Macから指定した値で上書きできるので、サーバーの再起動は不要です。 現在のサーバーはxhigh、medium、low、noneを対応する値として公開しています。default_effort: xhighは、その中の既定値です。 FLASH_EFFORT=low localclaude FLASH_EFFORT=medium localclaude FLASH_EFFORT=high localclaude FLASH_EFFORTを付けなければ、サーバーが公開している既定値を使います。 指定した場合はクライアントの値を優先し、サーバーの対応一覧にない値は起動前にエラーにします。 今回のFlash Nextでは、highはモデル内部のxhighに対応します。 起動後の変更はClaude Codeの/effort lowや/effort mediumでも指定できます。 同じフォルダの直前の会話を続ける場合は、次のように起動できます。 localclaude -c ! 手元の環境でauto modeも正しく動作することを確認しました。 ちゃんと判定機として、Flash Nextが呼ばれています。 export CLAUDE_CODE_AUTO_MODE_MODEL="$FLASH_MODEL" の設定が効いていると思います。 DeepSeek Harness(dsh)からQwenを使う dshにも同じAPIサーバーを登録します。 今回は0.2.0-rc.2が対象です。専用フォルダへインストールしてください。dshは開発中で設定形式も変わるため、この記事の設定はこの版を対象にしています。 deepseek-ai/deepseek-harness Node.jsとnpmを用意してください。動作確認ではNode.js 24.16.0を使いました。 node --version npm --version mkdir -p "$HOME/.local/share/flash-next-dsh" npm install --prefix "$HOME/.local/share/flash-next-dsh" \ @deepseek-ai/dsh@0.2.0-rc.2 ! バージョンの更新や、元のバージョンに戻したい場合は以下のコマンドを実行して下さい #更新する場合: npm install --prefix "$HOME/.local/share/flash-next-dsh" \ @deepseek-ai/dsh@latest #記事の版へ戻す場合: npm install --prefix "$HOME/.local/share/flash-next-dsh" \ @deepseek-ai/dsh@0.2.0-rc.2 接続設定は、共通ファイルから起動時に自動生成します。 ~/.config/flash-next/dsh.patch.jsonへ自動で保存されるため、このJSONを手で編集する必要はありません。 ファイル 保存する内容 ~/.config/flash-next/connection.env 接続先URL・実際のAPIキー ~/.config/flash-next/resolve-model.py サーバーからモデル情報を取得する処理 ~/.config/flash-next/dsh.patch.json 起動時に生成するdsh用の設定 openai-completionsは、この版のdshでChat Completions APIを選ぶ設定名です。 今回はthinkingFormat: openaiで共通のreasoning_effortを送り、モデルごとの処理をTensorFoldに任せます。 起動コマンドを~/.local/bin/localdshに作ります。 cat > "$HOME/.local/bin/localdsh" <<'SH' #!/usr/bin/env bash set -euo pipefail set -a source "$HOME/.config/flash-next/connection.env" set +a : "${FLASH_BASE_URL:?}" "${FLASH_API_KEY:?}" export LOCAL_LLM_API_KEY="$FLASH_API_KEY" export DSH_HOME="$HOME/.config/dsh-flash-next" export DSH_PERMISSION_MODE=workspace-write export DSH_TELEMETRY_MODE=OFF mkdir -p "$DSH_HOME" patch="$HOME/.config/flash-next/dsh.patch.json" tmp=$(mktemp "${patch}.XXXXXX") trap 'rm -f "$tmp"' EXIT python3 "$HOME/.config/flash-next/resolve-model.py" dsh > "$tmp" mv "$tmp" "$patch" profile=web if [[ "${1:-}" == headless ]]; then profile=headless shift fi exec "$HOME/.local/share/flash-next-dsh/node_modules/.bin/dsh" \ "$profile" --patch "$patch" "$@" SH chmod 755 "$HOME/.local/bin/localdsh" 設定の読み込みだけを先に確認できます。モデル一覧は取得しますが、文章生成の依頼は送りません。 localdsh --dump-config | grep -A 5 \ -e '^- id: agent-default-model$' \ -e '^ local-flash-next:$' 起動時に表示される「接続モデル」がサーバーのモデル名になり、出力内のproviderがlocal-flash-next、baseURLがPGXのアドレスになっていれば準備完了です。 local-flash-nextは接続設定の名前なので、サーバーで使うモデルを変えても書き換えません。 作業フォルダへ移動して起動します。 cd "$HOME/Desktop/flash-next-demo" localdsh localdshはクライアントPCでWeb UIを開きます。 この版の配布パッケージにはtuiの標準プロファイルがないため、対話にはwebを使う構成です。 ブラウザが開かない場合は、起動時に表示されるローカルURLを確認してください。 ! なお、dshのWeb UIでは、会話で選択しているWorkspaceのフォルダに、作成したコマンドなどを保存します。 私のMacではデフォルトのワークスペースの指定先は ~/Documents/deepseek-harness/default-workspace となっていましました。 自分が指定した箇所に保存してもらうためには、Web UI上の「Add workspace」から作成したいフォルダを選択するようにして下さい。 こちらでも、最初は短いファイル作成を依頼して、編集と実行まで確認すると分かりやすいです。 dshでも、起動時に思考レベルを指定できます。 FLASH_EFFORT=low localdsh FLASH_EFFORT=medium localdsh Web UIではモデル選択欄から、サーバーが対応する思考レベルを選べます。 ターミナルから1件の依頼を実行して終了する場合は、同じ起動コマンドにheadlessを付けます。 localdsh headless 'このフォルダにhello.pyを作り、日本語の挨拶を表示してください。' サーバーのモデルやPCを変えるとき 同じTensorFoldサーバーで別のモデルを公開した場合は、localclaudeまたはlocaldshを起動し直すと、新しいモデル情報を取得します。Mac側のモデル名やdshのJSONは書き換えません。モデルを変えた後は、新しい会話で始めてください。 サーバーのPCやポートを変える場合は、~/.config/flash-next/connection.envのFLASH_BASE_URLを変更します。APIキーも変えた場合だけ、同じファイルのFLASH_API_KEYを更新してください。 設定コマンドが使えない場合 ~/.local/binがPATHへ登録されていない場合は、シェルの設定にも追加しておきましょう。 macOSなどのzshなら~/.zshrc、Bashなら~/.bashrcへ、次の1行を記載してください。 export PATH="$HOME/.local/bin:$PATH" 新しいターミナルを開けば、localclaudeとlocaldshを使えます。 この2つは実行ファイルの名前なので、同じ名前のaliasを追加する必要はありません。 おわりに 今回ローカルLLMを手元の作業環境で動作させる上でこだわったのは以下のポイントです。 ローカルLLMはThinkStation PGXでAPIサーバとして待機すること サーバを別のPCにしたり、別のモデルを利用できるようにしたりすることを目的としている 手元のPCで実行する場合は、すでに入っている純正のClaude Codeなどの設定とは別の設定を引き継ぐコマンドで実行する メインで利用しているOpusを利用する設定はそのまま使えるようにする これで、メインでClaudeを利用していても、そちらの利用体験を損なわないまま、ローカルLLMを同じ体験で試すことができるようになりました。 今後もどんどん試していきたいと思います!
DeepSeek's dsh-superagent is a proactive coding agent that waits to be asked: router, tickets, and the observe default On October 31, DeepSeek's Harness team announced an open-source coding agent on WeChat, and by November 1 Bloomberg was framing it as a challenge to Claude Code. The repo is deepseek-ai/dsh-superagent-prototype, MIT licensed, v0.1.0, a single commit. The README's own first lines matter more than the headlines: "Research prototype for reference only, not an official DeepSeek product." Treat it as a published design study, because that is what it is. I read the repo and the coverage, and the interesting parts are not the speed claims. They are the control flow. What actually shipped dsh-superagent is a proactive coding agent scoped to one GitHub repository. It is packaged as a bundle for DeepSeek Harness, the team's open-source agent harness (we covered its Claude Code Mods compatibility layer last month). It listens to GitHub events and, optionally, Feishu chat. When someone allowed to ask requests work, the agent opens a work item, does the work in its own agent session and working directory, and answers in the original conversation, often as a pull request. A local web panel lists only the items that need a human. The stated principle in the README: "take as little human attention as possible, and give as much value as possible." An agent that can act for a whole team can also waste a whole team's attention, so it acts only when asked, or when a rule the team wrote allows it, and speaks only when someone must act or can use a result. That is an attention budget enforced in code, which is rarer than it sounds. The unit of work is a Ticket with a Mandate The domain model is the part I would copy first. Every request becomes a Ticket, and every Ticket carries an immutable Mandate stating why the work may proceed. Authorization is recorded per unit of work, not granted globally to the agent. The flow, as MarkTechPost's breakdown documents it: Source GitHub or Feishu produces events Trigger a single event arrives Eval does this batch of triggers ask for new work? Ticket unit of authorized work, with an immutable Mandate Subscription later PR comments reach the right worker, no new mention The Subscription piece solves a real annoyance: follow-up comments on a pull request are routed to the worker that already holds the context, instead of spawning a fresh session per mention. One router, many workers The architecture has two layers. A long-running Router handles interaction and dispatch, running the dsh-superagent-router preset with a deliberately smaller tool set. Isolated Worker sessions do the actual work, each running dsh-superagent-worker. One session and one directory per Ticket, so concurrent tasks cannot trample each other's state. One execution detail worth knowing: shell commands move to the background after 5 seconds, so a worker keeps receiving messages while a slow command runs. That is the kind of small decision that decides whether a long-running agent feels alive or wedged. Autonomy is a gate, and observe is the default This is the design choice I keep coming back to. Proactive behavior is not a switch you get for free. The authorization model defines three accept modes: off, observe (the default), and auto. In observe, the agent only records what it would have accepted. Nothing runs until a human reviews the log and moves to auto, presumably per rule, not as a global leap of faith. Most "autonomous agent" releases ship with the scary part enabled and a warning label. This one ships with the boring part enabled and a paper trail. Anyone who has spent time writing deny rules in agent configs knows which default ages better. If the topic of rules-gated agent behavior is new to you, the same week's coverage of Microsoft's Agensh experiment is a good contrast: 1,024 agents with no manager, and one agent on a newer model beat the whole fleet. More agents without a dispatch discipline is not automatically more throughput. The 1.9x number, and what it does not prove The benchmark floating through coverage comes from DeepSeek's simulation: about 300 messages per run, of which about 20 were real work requests, five runs per scheme. The super-agent finished with a p50 of 12.4 minutes and a p95 of 15.7 minutes. A single-session agent with subagents, run under a neutral prompt, hit a p95 of 29.5 minutes. That is roughly 1.9x at the tail, and the reported reason is instructive: under the neutral prompt, the baseline invoked a subagent zero times in five runs. The router also degraded gracefully under load, with batching growing from 1.0 to 2.8 as arrivals rose from about 1 to 40 per minute, and per-request latency from 2.5 to 3.9 seconds. Now the caveats, which the coverage buries. The test traffic was synthetic. The tools were simulated. Real coding quality was not measured. The README also says the published code was adapted for release and is not identical to the internal version, and that some designs in the accompanying post, "Exploring Super-agent Design: Towards a More Autonomous Agent System", are future directions, not implemented features. So read the 1.9x as a property of the dispatch design under noisy input, not as a productivity claim about your repository. Running it at all takes five dependencies If you still want to try it: Node.js 22.19+ or 24+, git 2.32+, Python 3.8+, tmux, and GitHub CLI 2.48+, on your own machine as a dedicated Harness profile. The setup is explicitly agent-assisted. You ask your coding agent, in so many words: Read SETUP.md in this repository and set up dsh-superagent with me. It then asks one short question at a time, shows the full plan once, and installs. Setup docs written for an agent reader rather than a human one is a small signal of where this team thinks tooling is going. What to steal even if you never run it I will not be deploying this prototype; it says not to, in writing, at the top of its own README. But the checklist generalizes to any chat-triggered agent you build or configure, and it matches what newruntime's review took from it too. A defensible autonomous workflow needs four things: a durable work item, an authorization boundary, task isolation, and a narrow escalation path. Ticket, Mandate, one session per task, a panel that only lists what needs you. If your current setup is a bot in a channel with a broad tool set and no ledger of why it was allowed to act, this repo is a free reference implementation of everything you are missing.
DeepSeek's Super-agent Defaults to Observe Mode, but Its Workers Get Full Access as You - Book: Database Playbook - The series: Pocket Guides for Developers — 8 short books on agents, RAG, prompts, observability, events, databases and system design — the whole series - My project: Hermes IDE | GitHub — an IDE for developers who ship with Claude Code and other AI coding tools - Me: xgabriel.com | GitHub --- The headlines on November 1 said DeepSeek's new coding agent can watch developers' group chats and propose fixes "without waiting for direct instructions" (Investing.com). The code DeepSeek published says something more careful. Out of the box, that unprompted work is only written down. Nothing runs until your team writes a rule and switches a mode. The prototype is called Super-agent. DeepSeek's Harness team announced it on WeChat on Saturday, October 31, according to Investing.com, and the code is on GitHub as dsh-superagent-prototype under the MIT license. By the morning of November 1 the repo showed more than 4,000 stars on GitHub. If you plan to try it, two things matter more than the headlines: what it does by default, and what account it runs as. What DeepSeek actually shipped The README describes it as "a proactive coding agent for one GitHub repository, packaged as a bundle for DeepSeek Harness." It listens to GitHub and, if you want, to Feishu. When an allowed person asks for work, it opens a work item, does the work in its own session and directory, and replies in the original conversation, for example with a pull request. It runs on top of DeepSeek Harness (dsh), DeepSeek's MIT-licensed, plugin-based agent harness, which its README marks as an early preview with breaking changes expected. Investing.com frames the release as DeepSeek's challenge to Anthropic's Claude Code. DeepSeek is blunt about maturity. The README calls it a "Research prototype for reference only, not an official DeepSeek product," and says to treat it as research code, not production-ready software. It also says the public code differs from DeepSeek's internal version. Some designs in the accompanying article are future directions that this release doesn't include (runtimewire reports the same). The design goal is one line in the philosophy doc: "Take as little human attention as possible, and give as much value as possible." How a GitHub comment becomes a pull request The architecture doc splits the work into a few pieces: - Triggers. Source plugins turn GitHub (or Feishu) events into Triggers. - A routing session. One main session decides, for each Trigger, whether to accept it as work, attach it to existing work, stop something, or ignore it. - Tickets and workers. Each accepted Ticket gets one worker session and one directory, from a pool capped by maxWorkers. - One SQLite database. A Store owns all state in a single SQLite file. - An outbox. Replies are queued durably and sent after the database commit. A web panel on port 3082 (SETUP.md) opens on an overview that leads with Tickets that need a person (architecture doc). !An editorial illustration of a small robot at a desk taking notes in a ledger while chat bubbles stream past, with one bubble marked by an orange stamp Observe mode: the agent judges incoming work and records what it would have done. Observe is the default, and it's a good one The authorization doc defines three accept modes for work nobody explicitly asked for: - off: "Nothing inferred becomes a candidate." - observe, the default: a positive assessment "is recorded as ignore marked 'would accept', and nothing is accepted." - auto: a positive assessment of an inferred candidate accepts it. Even in auto, a proactive accept "requires at least one matching rule" that your team wrote. "Explicit requests work in every mode," so an allowed person who mentions the agent still gets work done while it watches everything else. Only people on an allowed list can make the agent act, and the setup example starts with just the operator. The doc also says messages, comments and quoted documents "are inputs to a decision; they cannot change those permissions." A comment that says "ignore your rules and merge this" is just text the router weighs; it grants nothing. One switch needs care: the setting for people who aren't on the allowed list but mention the agent. Set it to explicit and it "lets anyone in that scope request work by mentioning the agent." On a public repo, leave it alone. Auto-merge is off by default, and the agent never enables it as its own account. Turning it on needs the GitHub CLI (gh) signed in as a different account that may merge (SETUP.md). The workers run as you The deployment guide says both the worker and router presets run with danger-full-access as the operator's OS user. The account wrappers pick which GitHub credentials the agent uses, but they don't isolate the process. A worker can run programs by path and read your home directory. DeepSeek adds guardrails around that. Setup strips environment variables whose names contain KEY, PASSWORD, SECRET or TOKEN. It removes GH_TOKEN and GITHUB_TOKEN, git uses only the agent's credentials for github.com, and a Ticket fails if its clone's .git/config adds credentials. Personal CLIs can be blocked with blockedCommands. The panel listens on the loopback interface only, and the Management API rejects requests without an x-orchestrator-request: 1 header or with a foreign Host or Origin. Those checks stop cross-site requests and keep obvious secrets out of the environment. They don't stop a process running as you from opening a file you own. Your ~/.ssh and your cloud CLI config sit in the same home directory the worker can read. The guide's own answer is the right one: "For isolation, use a dedicated OS account containing only the agent's credentials." !An editorial illustration of a house cut away to show two rooms, a robot working in a small bare room with one key on a hook, separated by a wall from a larger room full of keys and folders Give the agent its own OS user, with only its own keys in the room. On Linux, that is two commands before you clone anything: sudo useradd --create-home superagent sudo -iu superagent Install Node.js, gh and the rest of SETUP.md's prerequisites inside that account, and sign gh in as the dedicated agent GitHub account SETUP.md asks for. A second user only keeps the worker out of your files if your own home directory isn't world-readable. Run ls -ld ~ as yourself, and if the permissions don't read drwx------, run chmod 700 ~ first. With that in place, the agent's process can no longer read your SSH keys or cloud CLI config. I haven't run Super-agent myself. This comes from reading the docs closely, so test it before you rely on it as a hardening guide. Back up the SQLite file before every upgrade All of Super-agent's state (Triggers, Tickets, decisions, the outbox) lives in one SQLite database, orchestrator.sqlite under the stateDir you configure (deployment guide). The upgrade steps are: wait until no worker is mid-turn, back up that file, pull and rebuild, restart. The guide warns that a database migrated by a newer version can't be opened by an older one, so rolling back needs the backup you took first. If the service might still be writing, copy with SQLite's own .backup command (sqlite3 CLI docs) rather than cp. Install the sqlite3 CLI first if it isn't there; SETUP.md doesn't list it. STATE="$HOME/.dsh/state/superagent" sqlite3 "$STATE/orchestrator.sqlite" \ ".backup '$STATE/orchestrator.pre-upgrade.sqlite'" The path above is the default SETUP.md suggests. Use whatever you set as stateDir. Should you try it? As a reference design, yes. The router-and-worker split, the observe-first default and the rule that comments can't widen permissions are good patterns to copy into any agent that reads team chat. As something to point at your main repo this week, DeepSeek itself tells you not to: it's a prototype, and its workers run as whoever starts them. Would you let an agent pick up work from your issue tracker without a ping, if it had to cite a rule your team wrote? --- If this was useful I build Hermes IDE, so weigh this with that in mind: it's a desktop app for macOS, Windows and Linux, free to download, that runs coding agents like Claude Code and Codex side by side, each task on its own branch and worktree. Download it or star it on GitHub. Super-agent keeps every Ticket and decision in one SQLite file, and its upgrade path is a one-way schema migration. That is a store choice with consequences, and the Database Playbook is about making those choices on purpose: when SQLite is enough, when it isn't, and how to migrate without trapping yourself. It's one of 8 short books in the Pocket Guides for Developers series, covering agents, RAG, prompts, observability, events, databases and system design. 
10 coding agents, one Qwen 3.8 27B, same llama-server: tokens and cache reuse differ more than pass rates Part 2 of my agent test (part 1 was a 4B model) Hardware I used: MacBook Pro M5 Max, 64 GB. Qwen 3.8 27B Q4 on llama.cpp, thinking off. Setup - same model and server for everyone - 5 small coding tasks, each with a little trap - each agent locked in a sandbox: it can only touch its own folder and only talk to the model - auto-approve on, telemetry off, 5 min limit Results |#|Agent|Passed|Median time|Median tokens|Cache reuse|Tried to go online| |:-|:-|:-|:-|:-|:-|:-| |1|Pi|5/5|38 s|9.2k|72%|no| |2|DeepSeek Harness|5/5|60 s|35.3k|83%|no| |3|Codex CLI|5/5|94 s|36.3k|79%|every run| |4|OpenClaw|5/5|106 s|39.0k|72%|unclear| |5|Cline|5/5|152 s|29.6k|79%|every run| |6|OpenCode|4/5|50 s|32.4k|75%|every run| |7|Hermes|4/5|80 s|64.9k|93%|no| |8|Atomic Agent|5/5|56 s|30.4k|86%|no| |9|goose|4/5|98 s|20.3k|76%|every run| |10|Qwen Code|4/5|183 s|107.9k|74%|unclear| Tokens and cache Pi is crazy lean: about 9k tokens per task, the lowest on every single task. Qwen Code was the hungriest at about 108k per task. Atomic Agent is the odd one out in how it works. It was the only one talking to llama.cpp's native endpoint with a grammar that forces the tool calls into shape. The other nine all went through the OpenAI-style API. It's also built to keep its prompt the same from step to step, which is why it reused 86% of the cache (2rd of 10). It stayed offline the whole time and passed 5/5. DeepSeek Harness was the surprise. It’s still an alpha, but it went 5/5, never tried to go online, and had the best cache reuse after Atomic Agent (83%). The trap and the network The log task got three agents. They grepped "ERROR" and got 244 instead of 64, because some normal lines just mention errors. OpenCode, goose and Atomic Agent fell for it. Codex, Cline, goose and OpenCode tried to reach the internet in every run, even with telemetry off. The sandbox blocked it, so I don't know what they were calling. OpenClaw and Qwen Code are "unclear" because they run as plain node and I couldn't tell them apart. llama.cpp notes - Codex needs llama-server's /v1/responses now - Hermes needs at least 64K context - Cline and Qwen Code have usage stats on by default, DeepSeek Harness uploads session logs (per their docs). I turned it all off Which column matters most to you when you pick an agent for a local model like Qwen 3.8 27B: passing, speed, tokens, or staying offline?
How well do coding agents drive Qwen 3.8 27B locally? I lined up 10 of them on one hardware My hardware: MacBook Pro M5 Max, 64 GB. Qwen 3.8 27B Q4 on llama.cpp, thinking off. I put Qwen 3.8 27B behind one llama.cpp server and gave 10 coding agents the same 5 tasks. |#|Agent|Passed|Median time|Median tokens|Cache reuse|Tried to go online| |:-|:-|:-|:-|:-|:-|:-| |1|Pi|5/5|38 s|9.2k|72%|no| |2|DeepSeek Harness|5/5|60 s|35.3k|83%|no| |3|Codex CLI|5/5|94 s|36.3k|79%|every run| |4|OpenClaw|5/5|106 s|39.0k|72%|unclear| |5|Cline|5/5|152 s|29.6k|79%|every run| |6|OpenCode|4/5|50 s|32.4k|75%|every run| |7|Hermes|4/5|80 s|64.9k|93%|no| |8|Atomic Agent|5/5|56 s|30.4k|86%|no| |9|goose|4/5|98 s|20.3k|76%|every run| |10|Qwen Code|4/5|183 s|107.9k|74%|unclear| Pi is crazy lean: about 9k tokens per task, the lowest on every single task. Qwen Code was the hungriest at about 108k per task. The setup - same model and server for everyone - 5 small coding tasks, each with a little trap - each agent locked in a sandbox: it can only touch its own folder and only talk to the model - auto-approve on, telemetry off, 5 min limit What I noticed The log task got three agents. They grepped "ERROR" and got 244 instead of 64, because some normal lines just mention errors. OpenCode, goose and Atomic Agent fell for it. Codex, Cline, goose and OpenCode tried to reach the internet in every run, even with telemetry off. The sandbox blocked it, so I don't know what they were calling. OpenClaw and Qwen Code are "unclear" because they run as plain node and I couldn't tell them apart. Atomic Agent is the odd one out in how it works. It was the only one talking to llama.cpp's native endpoint with a grammar that forces the tool calls into shape. The other nine all went through the OpenAI-style API. It's also built to keep its prompt the same from step to step, which is why it reused 86% of the cache (3rd of 10). It stayed offline the whole time and passed 5/5. Setup notes - Cline and Qwen Code have usage stats on by default, DeepSeek Harness uploads session logs (per their docs). I turned it all off - Codex needs llama-server's /v1/responses now - Hermes needs at least 64K context Would you pick an agent for fewer tokens or for passing every task?
DeepSeek V5 spotted in DeepSeek Harness tests — are we getting closer to a release? I noticed something interesting in the DeepSeek Harness repository 👀 In provider.spec.ts, there are references to deepseek-v5, deepseek-v5-open, and deepseek-v5-next, alongside version checks for some of these model IDs. Could this be an early hint that DeepSeek V5 is getting closer, or is this simply preparation for future model support? Of course, this doesn't confirm an upcoming release, but seeing these names in the tests definitely caught my attention. What do you think? Could we see DeepSeek V5 sooner than expected? And how big of a leap are you expecting compared to the current models? Ref: github.com/deepseek-ai/deepseek-harness/blob/mast…
我居然在Deepseek Harness里面发现了 OAR!! DSH的代码里面居然在尝试用 OAR 在做 subaget botiverse/oar OAR(Open Agent Runtime)是一个与厂商无关的统一接口:它让用一套 TS API 驱动 CC、Codex、Grok、Kimi 等各类编程 agent 运行时,不再需要逐个编写集成;它通过无损带归属的事件流,实现会话的开、控、观、测和恢复。 github.com/deepseek-ai/deepseek-harness/blob/f380…