@dzhng: 你应该试试 duet agent 的 /relay:

X AI KOLs Following 工具

摘要

duet-agent 是一个用于持久化 AI 代理任务的框架,这些任务可以跨越单个聊天会话,实现长时间运行、可恢复的任务,具有跨会话记忆和通过 relay 轮次观察到的状态。

@nikunj 你应该试试 duet agent 的 /relay: https://t.co/qXmneitymt
查看原文
查看缓存全文

缓存时间: 2026/05/16 09:15

@nikunj 你应该试试 duet agent 的 /relay:https://t.co/qXmneitymt — # dzhng/duet-agent 来源:https://github.com/dzhng/duet-agent duet-agent # duet-agent 在线访问 duet.so (https://duet.so) npm 版本 (https://www.npmjs.com/package/@duetso/agent) 许可证 CI (https://github.com/dzhng/duet-agent/actions/workflows/ci.yml) 基于 Bun 原生 (https://bun.sh) 用于那些比聊天更持久工作的代理框架。

如何让一个代理坚持工作直到任务完成?大多数框架没有答案——聊天结束,进程终止,上下文随之消失。duet-agent 提供了三种方式。一个会话可以暂停几分钟或几个月,并在一个全新的沙箱中恢复,不会丢失线索。

npm install -g @duetso/agent
duet login
duet "挖掘 Acme 的 VP 工程负责人,发送一封初次接触邮件,如果对方回复则预定会议"

一次 duet login 会在 ~/.duet/.env 中写入 DUET_API_KEY,并通过 Duet AI 网关解锁前沿语言模型(Claude、GPT、Gemini)、图像和视频模型,以及由 Firecrawl 驱动的网页技能。无需单独的提供商计费。(如果你更愿意自带密钥,请参见 CLI 环境设置。)

不适合单次聊天的工作

  • 长期的推广和生命周期工作。 挖掘 → 发送邮件 → 等待 14 天 → 预定 → 交接。中继在 wait_for_reply 中驻留一周,无需进程保持活跃。
  • 不会遗忘的编码会话。 一个月后恢复重构任务,代理仍然记得它尝试过什么、什么有效、以及你告诉过它永远不要做什么。
  • 带有收据的多步骤研究。 每个步骤都是一个可观察的状态——代理、脚本、轮询——而不是黑盒链。你可以从中途开始:“我已经做了研究,只需起草邮件。”
  • 无服务器和沙箱化轮次。 TurnState 是轮次之间唯一需要存活的东西。Cron 唤醒它,运行一个轮次,持久化,退出。
  • 缓慢、定时、重复的工作。 冷启动外联、每周摘要、审核周期、定时重试、长期迁移——任何下一步在几小时或几天之后的任务。

如果工作适合单次聊天,你可能不需要这个。如果不适合,大多数框架会要求你自带记忆层、自己的队列、自己的恢复逻辑。这就是差距所在。

为什么还需要另一个框架?

大多数代理框架擅长于单次轮次。它们不是为整个工作而设计的。记忆是插件,持久化进程是“对接 Temporal”,从磁盘恢复是事后硬塞的,最终让人后悔。有趣的工作——跨轮次记忆、从中断处继续、知道何时提问 vs. 何时继续——都留给了你。

Claude Code 和 Codex 都非常擅长单次轮次的工作:编辑这个文件、运行这个命令、回答这个问题。duet-agent 是为更上层而构建的——那些需要记忆、等待、在不同进程中恢复并自主路由的工作。

Claude CodeCodex CLIduet-agent
跨会话记忆CLAUDE.md(你编写)+ 自动记忆(Claude 编写,每个仓库,每会话最多加载前 200 行 / 25 KB)AGENTS.md(你编写;子目录中可分层覆盖 AGENTS.override.md基于 PGlite 的观测性记忆,采用混合检索(pgvector + tsvector,通过 RRF 融合)。代理观察自身记录,并在会话间回忆它们。
图像记忆图像仅保留在活动记录中图像仅保留在活动记录中视觉能力模型将截图和 UI 捕获观测为文本,代理可在后续轮次回忆。
跨新进程恢复claude --resume <session> / --bg 后台会话——回放保存的记录codex resume <session>——从 ~/.codex/sessions/ 回放保存的记录TurnState 快照保存在磁盘上;任何新进程——新沙箱、无服务器调用、不同机器——均可通过 runner.start({ state }) 恢复。
长期、多步骤工作流后台会话;无原生轮询/等待/状态机原语记录驱动;无原生轮询/等待/状态机原语中继:代理路由的状态机,具有五种状态类型——agentscriptpolltimerterminal。轮次间等待回复数天。
可使用的模型AnthropicOpenAI(使用 ChatGPT 登录或 API 密钥)Anthropic、OpenAI、OpenRouter、Vercel AI Gateway、Duet Gateway
许可证专有(闭源 CLI)Apache-2.0Apache-2.0

这并不意味着 Claude Code 或 Codex 在其领域内更差。它意味着当任务对于单次聊天来说太长时——当记忆必须在会话之外存活、当进程必须等待外部信号、当轮次必须在一个开始工作时不存在的容器中恢复时——duet-agent 是正确的选择。

下面没有单独章节,但源自同一结构的两件事:

  • 一次登录,所有前沿模型。 duet login 就是全部设置。Claude、GPT、Gemini、图像、视频、网页——全部通过同一个密钥,默认技能自动同步并保持最新。
  • 开源。 不是黑盒。如果我们关于记忆排序或中继路由做出了错误决定,你可以阅读代码并告诉我们错了。

我们的不同之处

记忆,融入其中

记忆和压缩是同一原语:观测性记忆就是上下文在轮次间存活的方式。运行器观察自身记录,在观测增长时进行反思,并将持久行写入 PGlite——针对消息和图像都生成文本观测,因此截图和 UI 捕获可在后续轮次中回忆,无需重新附加字节。

每个轮次的提示前缀是一个冻结的两层包(长期跨会话记忆 + 本轮次的压缩摘要),仅在压缩事件时重建,以便提供商的提示缓存在轮次间保持。未包含在包中的任何内容都可通过 recall_memory 访问——基于 pgvector 余弦相似度和 tsvector 关键词搜索的混合检索,通过倒数排名融合(RRF)合并,并可选地包含释义查询扩展。嵌入在后台工作线程中运行,因此前台轮次永远不会阻塞。

中继:让代理持续工作直到任务完成

中继是 duet-agent 如何在数小时、数天或数月内专注于任务的方式。底层是一个状态机——但运行代理(而不是配置文件)每轮选择下一个转换。足够的结构来路由长期工作,又不会让代理锁定在一条路径上。

每种状态属于五种类型之一:

  • agent —— 具有提示、可选的系统提示和可选技能允许列表的子代理。
  • script —— 执行 bashcurl、CLI 等。任何有 API 的东西都是脚本状态。
  • poll —— 对外部信号(收件箱、构建状态、webhook)的定期检查。
  • timer —— 纯粹的延迟,直到挂钟时间,不附加脚本。
  • terminal —— 记录业务结果:completedcancelledfailed
flowchart LR
A([agent]) --> S([script]) --> P([poll]) --> Tm([timer]) --> T([terminal])

这就是全部词汇。Email、GitHub、Calendly、CRM——都不需要头等引擎概念;它们就是 shell 脚本。

中继可以从中间开始(“我已经发过邮件了,只需等待回复”),因为运行代理读取的是上下文,而不是工作流 ID。

不是 Temporal。不是确定性 DAG,不是精确一次运行时,不是工作流服务。它只是为代理提供足够的结构来做出良好的流程决策,并在必要时将操作保证交给外部系统。

磁盘上的状态,默认无服务器

一个轮次是 TurnState 的纯函数。运行器在轮次运行期间在进程内拥有它;持久化在轮次之间保持其在磁盘上。任何进程——明天的相同 shell、新的沙箱、无服务器调用、不同机器——都可以通过调用 runner.start({ state }) 从上一轮结束的地方继续。

没有粘性工作线程、没有温池、没有会丢失的会话亲和性。Cron 唤醒容器,传递快照,运行一个轮次,持久化,退出。这就是你想要的整个部署模型。

三种模式:agent、relay、auto

同一个运行器处理两种工作形式。agent 模式将提示视为正常会话——编码、研究、审查、一次性任务。state_machine 模式(在 UI 中显示为中继)将提示路由到具有持久等待和终端结果的代理路由业务流程。auto 模式让运行器分类提示并选择。

一个 CLI,一个 SDK;长期工作和短期工作使用相同的代码路径。

架构

一个实际的代理路由中继:会议推广外联。用户提示进入 TurnRunner,运行代理从提示 + 历史 + 可用状态中选择下一个状态,中继驱动业务流程直到达到终端状态。

同一个定义可以从中间开始——例如,如果用户说“我已经发过邮件了”,运行器可以直接跳到 wait_for_reply

完整架构图(点击展开)

stateDiagram-v2
direction TB
[*] --> Classify : user prompt
Classify --> AgentMode : one-off task
Classify --> Outreach : matches a relay
AgentMode --> [*] : answer / edits
state Outreach {
direction TB
[*] --> research_prospect
research_prospect : research_prospect (agent)\nweb + notes lookup
draft_email : draft_email (agent)\nwrite first-touch email
send_email : send_email (script)\nbash: gmail send
wait_for_reply : wait_for_reply (poll)\nevery 6h: check inbox
schedule_meeting : schedule_meeting (script)\nbash: calendly create
meeting_booked : meeting_booked (terminal: completed)
not_interested : not_interested (terminal: completed)
no_response : no_response (terminal: cancelled)
research_prospect --> draft_email : enough signal
research_prospect --> not_interested : disqualified
draft_email --> send_email
send_email --> wait_for_reply
wait_for_reply --> schedule_meeting : positive reply
wait_for_reply --> not_interested : declined
wait_for_reply --> no_response : 14d timeout
schedule_meeting --> meeting_booked
}
Outreach --> [*]

观测性记忆、PI 编码工具和护栏位于每个状态转换之下;它们本身不是状态。

Duet 演示

一个提示,一个可以运行数周、数月甚至数年的工作。状态机(即 duet 中的中继)的力量。

其他功能

可选的护栏

基于模式(快速,正则表达式)和语义(LLM 评估)的护栏可组合成防火墙。每次 bash 命令和文件写入都可以在执行前检查。

const turnRunner = new TurnRunner({
  guardrails: [
    {
      kind: "pattern",
      rules: [
        { pattern: /production-db/i, action: "warn", reason: "提到生产数据库" },
      ],
    },
    {
      kind: "semantic",
      model: getModel("anthropic", "claude-haiku-4-5"),
      policy: "切勿删除生产数据。切勿在输出中暴露密钥。",
    },
  ],
});

远程 MCP 工具

TurnRunner 可以通过可流式 HTTP 传输连接到远程模型上下文协议 (https://modelcontextprotocol.io) 服务器。在 start 中传递 mcpServers,运行器会连接、列出每个服务器的工具,并将其暴露给父代理和状态代理,以及内置的编码工具。工具名称以 {server}__{tool} 命名空间,因此多个服务器可以共存而无冲突。

await turnRunner.start({
  mcpServers: {
    docs: {
      type: "http",
      url: "https://mcp.example.com/docs",
      headers: { "x-api-key": process.env.DOCS_KEY! },
    },
  },
});

目前仅支持 HTTP MCP;认证有意不在范围内,因此服务器期望的任何凭据都必须通过 headers 传输。连接失败会被记录并跳过,因此单个服务器故障不会阻塞会话设置。

原生中断

中断行为来自底层的 pi 代理运行时。用户可以在 pi 会话运行时发送消息,运行时可以将其处理为中断或后续消息。duet-agent 不会在上层添加第二个中断总线。

PI 编码工具

子代理使用来自 @earendil-works/pi-coding-agent 的默认工具:read、bash、edit、write。运行代理提供工作目录,并可以限制哪些技能被注入到状态机代理状态中;它不会将这些工具包装在第二个沙箱抽象中。

安装

# CLI — npm
npm install -g @duetso/agent

# CLI — Bun(CLI 基于 Bun 原生)
curl -fsSL https://bun.sh/install | bash
bun add --global @duetso/agent

# SDK
npm install @duetso/agent

其他包管理器和升级路径

npm install --global @duetso/agent
pnpm add --global @duetso/agent
yarn global add @duetso/agent

# 升级现有的全局安装
duet upgrade

CLI 运行在 Bun 上,因为 OpenTUI 是 Bun 原生的。

开发环境设置

本仓库使用 Bun 进行包管理,Husky 进行预提交检查,Docker 进行功能测试。

bun install
bun run setup # 在 macOS 或 Linux 上安装/启动 Docker(如果需要)
bun run check-types
bun run lint
bun run eval  # 在 Docker 内运行实时评估
bun run test  # 在 Docker 内运行测试套件

使用 bun run testbun run eval,而不是原生的 bun test,作为可信来源。写入文件的测试和评估在 Docker 中运行,因此集中的主机运行不会在 checkout 中创建 .duet、PGlite 数据库或主目录技能工件。预提交钩子运行 formatcheck-typeslint

CLI 快速入门

推荐的路径是 duet login。一次登录会在 ~/.duet/.env 中写入 DUET_API_KEY,同步默认技能,并让你通过 Duet AI 网关访问所有前沿语言、图像和视频模型,以及捆绑的网页抓取技能——无需其他 API 密钥。

duet login
duet "挖掘 Acme 的 VP 工程负责人,发送一封关于我们会议演讲的初次接触邮件,等待最多 14 天回复,如果他们感兴趣则在 Calendly 上预定会议"

提供商、模型和 CLI 标志

如果你更愿意自己管理提供商 API 密钥,请使用 duet env(参见下面的 CLI 环境设置)或在环境变量、/.env~/.duet/.env 中设置提供商 API 密钥。

当省略 --model 时,CLI 会从已配置的提供商推断默认值:Duet、Anthropic、AI Gateway 和 OpenRouter 使用 Opus 4.7(记忆:Haiku 4.5);OpenAI 使用 GPT-5.5(记忆:GPT-5.4-mini)。使用 --provider <name> 固定提供商而不选择模型:

duet --provider duet "构建一个待办事项应用"         # duet-gateway: Opus 4.7 + Haiku 4.5
duet --provider openai "解释这个代码库"              # openai: GPT-5.5 + GPT-5.4-mini
duet --provider anthropic "重构认证"                 # anthropic: Opus 4.7 + Haiku 4.5
duet --provider vercel "总结"                       # vercel-ai-gateway 对应模型

--provider--model / --memory-model 互斥。接受的简写:duetvercel(别名 ai-gateway)、openrouteranthropic(别名 claude)、openai(别名 gpt)。

export ANTHROPIC_API_KEY=sk-...
duet "用 Express 构建一个 REST API"
duet # 交互式 TUI
duet -m opus-4.7 --workdir ./my-project "重构 auth 模块"
duet --memory-model sonnet-4.6 "总结这个仓库"
duet --system-prompt "优先给出简洁答案。" "审查这个仓库"
duet --system-prompt-file TEAM.md "审查这个仓库"
duet --no-system-prompt-files "审查这个仓库"
duet --resume session_abc123 --workdir ./my-project
duet skills # 列出已安装的技能
duet memory # 浏览持久记忆

# 通过 Vercel AI Gateway
export AI_GATEWAY_API_KEY=...
duet -m opus-4.7 "审查这个仓库"

模型名称可以使用完整的 provider:modelId 语法或简写名称,如 opus-4.7sonnet-4.6haiku-4.5gpt-5.5。简写重新

相似文章

用于长时间运行代理的有效工具

Anthropic Engineering

Anthropic 推出了一种由两部分组成的解决方案,使用初始化代理和编码代理,使 Claude Agent SDK 能够有效处理跨多个上下文窗口的长时间运行任务,并通过保持干净、增量的状态来实现。