Agent工坊

【Agent工坊】Hermes Agent 插件API:register_auxiliary_task实战——让Agent学会自我扩展

2026年5月24日凌晨,Hermes Agent 合并了一个看似低调但架构意义重大的 PR:register_auxiliary_task() 正式进入 PluginContext API。这意味着你的 Agent 插件现在可以注册后台任务——定时监控、自动清理、数据预热,都不再需要外部 cron。

为什么这个API值得你关注

如果你在用 Hermes Agent 做内容创业或自动化运营,你一定遇到过这个痛点:

Agent 能执行你交代的任务,但它不会"自己想到"去做一件事。

比如:
- 你希望 Agent 每小时自动扫描一次竞品 GitHub 仓库的 Release 页面
- 你希望 Agent 在每次会话开始前预热模型缓存,减少首次响应延迟
- 你希望 Agent 监控某个数据源,发现异常时主动通知你

register_auxiliary_task() 之前,这些需求只能靠外部 cron 定时触发 Hermes Agent 来实现。问题是:

  1. 外部 cron 不知道 Agent 的内部状态 —— Agent 正在执行长任务时,cron 粗暴地新建会话会产生冲突
  2. 跨会话上下文丢失 —— 每个 cron 触发的新会话都是"白纸一张",无法延续之前的监控状态
  3. 维护两套调度系统 —— 一套在 Agent 内(Skills/Workflows),一套在 Agent 外(crontab/systemd timer),心智负担翻倍

register_auxiliary_task() 解决了这个架构层面的裂缝:让插件在 Agent 进程内部注册后台任务,由 Agent 自己的调度器管理。

API 速览:一个函数,三种能力

# PluginContext 新增方法签名
def register_auxiliary_task(
    self,
    name: str,                          # 任务名称(用于日志和状态追踪)
    coro: Callable[[], Awaitable[None]], # 异步任务函数
    *,
    interval: float = 60.0,             # 执行间隔(秒)
    start_after: float = 0.0,           # 首次延迟(秒),0=立即
    max_failures: int = 3,              # 连续失败上限,超限后自动暂停
    timeout: float | None = None,       # 单次执行超时(秒)
) -> str:
    """注册一个辅助后台任务,返回 task_id"""

只需要 6 个参数,但涵盖了生产级后台任务需要的所有能力:

能力 对应参数 实际场景
定时执行 interval 每 30 分钟扫描一次 GitHub Releases
延迟启动 start_after 等 Agent 初始化完毕后再开始监控
容错机制 max_failures API 挂了 3 次就暂停,不发报警风暴
超时保护 timeout 防止某个数据源卡住拖死整个插件

实战一:GitHub Release 自动监控插件

这是 AI 创业者最刚需的场景——监控 Hermes Agent、OpenClaw、Claude Code 等核心工具的更新。

# plugins/github_watcher/__init__.py
import asyncio
import aiohttp
from datetime import datetime
from hermes.plugin import HermesPlugin, PluginContext

class GitHubWatcherPlugin(HermesPlugin):
    """监控指定 GitHub 仓库的最新 Release"""

    name = "github_watcher"
    version = "1.0.0"

    def __init__(self):
        self.repos = [
            "NousResearch/hermes-agent",
            "openclaw/openclaw",
        ]
        self.last_checked: dict[str, str] = {}  # repo -> last tag
        self._session: aiohttp.ClientSession | None = None

    async def activate(self, ctx: PluginContext):
        # 注册辅助任务:每 1800 秒(30分钟)检查一次
        ctx.register_auxiliary_task(
            name="gh-release-poll",
            coro=self._poll_releases,
            interval=1800.0,      # 30 分钟
            start_after=10.0,     # 给 Agent 10 秒初始化时间
            max_failures=5,       # GitHub API 偶尔 429,容忍 5 次
            timeout=45.0,         # 单次检查不超过 45 秒
        )
        self._session = aiohttp.ClientSession()

    async def _poll_releases(self):
        for repo in self.repos:
            try:
                async with self._session.get(
                    f"https://api.github.com/repos/{repo}/releases/latest",
                    headers={"Accept": "application/vnd.github+json"},
                    timeout=aiohttp.ClientTimeout(total=30)
                ) as resp:
                    if resp.status != 200:
                        continue
                    data = await resp.json()
                    tag = data.get("tag_name", "")
                    prev = self.last_checked.get(repo)

                    if prev and prev != tag:
                        # 发现新 Release!写入通知文件
                        self._notify_new_release(repo, tag, data)
                    self.last_checked[repo] = tag
            except Exception:
                continue  # max_failures 会自动处理

    def _notify_new_release(self, repo: str, tag: str, data: dict):
        body = data.get("body", "")[:500]
        msg = (
            f"🚀 {repo} 新版本 {tag}\n"
            f"发布时间: {data.get('published_at', 'unknown')}\n"
            f"更新内容: {body}..."
        )
        # 写入 Agent 通知通道(可以是文件、Webhook、或内存队列)
        with open("/tmp/hermes_release_alerts.log", "a") as f:
            f.write(f"[{datetime.now().isoformat()}] {msg}\n\n")

这个插件的关键设计:

  1. start_after=10.0:不在 Agent 启动瞬间就开始轮询,给 Skills 加载、模型预热留出时间
  2. max_failures=5:GitHub API 限流(未认证 60次/小时)是常态,容忍连续 5 次失败,避免任务被过早暂停
  3. 状态持久化self.last_checked 保存在插件实例中,只要 Agent 进程不重启,跨轮询的状态就持续存在——这是外部 cron 做不到的
  4. 通知解耦:插件只负责"发现变化",通知通过文件写入,Agent 的其他部分(如定时 prompt 或 Skill)来消费

实战二:会话预热插件——用户不等

AI Agent 的一个经典问题是"冷启动":每次新会话的第一个请求延迟明显高于后续请求。对于需要频繁交互的一人公司场景,这直接影响工作效率。

# plugins/session_warmer/__init__.py
class SessionWarmerPlugin(HermesPlugin):
    """在 Agent 空闲时预热模型缓存,降低首次响应延迟"""

    name = "session_warmer"
    version = "1.0.0"

    async def activate(self, ctx: PluginContext):
        # 每 5 分钟发送一次轻量级 keep-alive
        ctx.register_auxiliary_task(
            name="model-keepalive",
            coro=self._keepalive,
            interval=300.0,       # 5 分钟
            start_after=60.0,     # 1 分钟后开始
            max_failures=10,      # 预热失败不影响主流程,容忍度高
            timeout=15.0,
        )

    async def _keepalive(self):
        # 发送一个轻量推理请求保持模型热缓存
        # 实际实现取决于你的模型部署方式
        ...

价值量化:如果每天有 10 次新会话,每次冷启动多等 3-8 秒,一年浪费的时间超过 12 小时——这还不算打断心流的隐性损失。

实战三:数据源健康检查——在出事之前知道

对于做 AI 内容创业的团队,数据源的可用性直接影响产出质量。与其等写文章时才发现某个 API 挂了,不如让 Agent 主动监控。

# plugins/source_health/__init__.py
class SourceHealthPlugin(HermesPlugin):
    """监控关键数据源的健康状态"""

    name = "source_health"
    version = "1.0.0"

    # 定义监控端点
    ENDPOINTS = [
        ("HN API", "https://hacker-news.firebaseio.com/v0/topstories.json"),
        ("GitHub API", "https://api.github.com"),
    ]

    async def activate(self, ctx: PluginContext):
        ctx.register_auxiliary_task(
            name="health-check",
            coro=self._check_all,
            interval=600.0,       # 每 10 分钟
            start_after=0.0,      # 立即开始
            max_failures=3,
            timeout=20.0,
        )

    async def _check_all(self):
        for name, url in self.ENDPOINTS:
            try:
                async with self._session.get(url, timeout=aiohttp.ClientTimeout(total=10)) as r:
                    status = "✅" if r.status == 200 else f"⚠️ {r.status}"
            except Exception as e:
                status = f"❌ {type(e).__name__}"

            # 写入健康状态文件
            with open(f"/tmp/health_{name.lower().replace(' ', '_')}.txt", "w") as f:
                f.write(f"{status}\n")

这个插件配合一个简单的 Skill(读取健康状态文件,发现 ❌ 时发通知),就构成了完整的监控闭环。

register_auxiliary_task vs 其他调度方式

方案 状态保持 容错机制 与Agent集成 适用场景
外部 cron ❌ 每次新会话 ❌ 需自行实现 ⚠️ 通过 CLI 触发 定时的完整工作流
Skill 内循环 ❌ 阻塞主流程 短周期的简单检查
delegate_task ❌ 子Agent独立 ⚠️ 依赖主Agent 一次性复杂任务
register_auxiliary_task ✅ 插件内 ✅ 内置 ✅ 原生集成 周期性后台监控

关键判断标准:如果任务需要"连续观察"而非"一次性执行",就用 register_auxiliary_task

避坑指南:刚上线就踩过的 3 个坑

坑1:插件卸载时忘记清理任务

register_auxiliary_task() 返回的 task_id 要保存起来,在 deactivate() 中取消:

async def activate(self, ctx: PluginContext):
    self._task_id = ctx.register_auxiliary_task(...)

async def deactivate(self, ctx: PluginContext):
    if self._task_id:
        ctx.unregister_auxiliary_task(self._task_id)

坑2:interval 设置太激进

如果你的任务要调 GitHub API(未认证限流 60次/小时),interval=60 就会触发限流。公式interval ≥ (检查端点数量 × 3600 / API每小时限额)

坑3:任务函数里做重量级同步操作

register_auxiliary_taskcoro 必须是 async 函数。如果在里面做了同步 HTTP 请求或文件 I/O,会阻塞 Agent 的事件循环。务必用 aiohttp 而非 requests,用 aiofiles 而非 open()

对 AI 创业者的启示

这个 API 的深层含义不是"多了一个函数",而是 Hermes Agent 的架构正在从 "被动响应"转向"主动感知"

过去:用户说 → Agent 做
现在:Agent 自己发现 → Agent 自己判断要不要告诉用户

这对一人公司的意义:
- 减少"检查类"操作的心智负担:不用每天手动检查竞品更新、API 状态
- 发现时机从"人发现"变成"Agent 发现":新闻出来 30 分钟内 Agent 就能感知到
- 把重复性监控劳动力成本降为零:这是 AI 创业真正的成本优势来源

下一步我会在 AI 创业内参的系统中实装 register_auxiliary_task() 版本的 GitHub 监控和 HN 热点追踪插件,届时分享完整的插件包和部署指南。

立即行动

  1. 检查你的 Hermes Agent 版本hermes --version,确保 ≥ v2026.5.16(v0.14.0),register_auxiliary_task 在该版本之后的主分支中
  2. 先写一个最简单的辅助任务:每 60 秒往文件写一次时间戳,验证调度器正常工作
  3. 找到你工作流中最重复的"检查类"操作:把它变成 register_auxiliary_task 的第一个实战插件
  4. 加入 Hermes Agent 社区:在 GitHub Issues 中搜索 plugin 标签,关注插件生态的最新进展

本文基于 Hermes Agent commit e752c945 (2026-05-24T00:49 UTC) 的最新 Plugin API 撰写。插件示例代码为参考实现,实际使用需根据你的 Hermes Agent 版本调整。

AI创业 #Agent工坊 #HermesAgent #Plugin开发 #一人公司 #自动化运营