HagiCode 为什么选择 Hermes 作为综合 Agent 核心

张开发
2026/4/6 17:08:02 15 分钟阅读

分享文章

HagiCode 为什么选择 Hermes 作为综合 Agent 核心
为什么 HagiCode 需要 Hermes在详细介绍 Hermes 之前先说说 HagiCode 为什么会有这样的需求。这世上的事情啊往往不是你想怎么样就能怎么样的总得找个合适的由头。作为一个 AI 代码助手HagiCode 需要同时支持多种使用场景本地开发环境开发者希望在自gu电脑上运行数据不出本地——这年头数据安全这事说大不大说小也不小团队协作环境小团队可以共享部署在服务器上的 Agent——省钱嘛大家都不容易云端弹力扩展处理复杂任务时能自动扩展到 GPU 集群——有备无患这种既要又要的需求让我们把目光投向了 Hermes。这选择对不对我不知道只是当时也没别的更好的办法了。什么是 Hermes AgentHermes Agent 是由Nous Research创建的自主 AI Agent。可能有人对 Nous Research 不熟悉——他们就是开发了 Hermes、Nomos 和 Psyché 等开源大模型的实验室。说起来他们也挺不容易的做了这么多好东西知道的人却不多。跟传统的 IDE 编程助手或者简单的 API 聊天包装器不同Hermes 有一个特点运行时间越长能力越强。它不是一次性完成任务就完事而是能在长时间运行中持续学习和积累经验。这点也挺像人的是不是核心特性Hermes 的几个核心特性正好契合了 HagiCode 的需求。你说巧不巧这意味着 HagiCode 可以根据用户场景选择最合适的部署方式。个人用户本地跑团队用户服务器部署复杂任务上 GPU——一套代码搞定。这世道能省一事算一事罢。多平台消息网关Hermes 原生支持 Telegram、Discord、Slack、WhatsApp 等平台。对 HagiCode 来说这意味着未来可以轻松支持这些渠道的 AI 助手。毕竟谁不想多几条路呢丰富的工具系统40 内置工具加上 MCPModel Context Protocol扩展能力。这对于代码助手来说太重要了——执行 shell 命令、操作文件系统、调用 Git这些都需要工具支持。没有工具的 Agent就像没有翅膀的鸟——想飞也飞不起来。跨会话记忆Hermes 有持久记忆系统用 FTS5 全文检索召回历史对话。这让 Agent 能记住之前的上下文不会每次都失忆。有时候我也想失忆一下什么都不想可就是做不到。HagiCode 如何集成 Hermes说完了为什么接下来看看怎么做。有些事情想明白了就得动手光想不做也不是个事儿。Provider 层抽象在 HagiCode 的架构中所有 AI Provider 都实现统一的IAIProvider接口public sealed class HermesCliProvider : IAIProvider, IVersionedAIProvider{public ProviderCapabilities Capabilities { get; } new ProviderCapabilities{SupportsStreaming true, // 支持流式输出SupportsTools true, // 支持工具调用SupportsSystemMessages true, // 支持系统提示SupportsArtifacts false};}这个抽象层让 HagiCode 可以无缝切换不同的 AI Provider无论是 OpenAI、Claude 还是 Hermes上层调用方式完全一致。说白了就是省事儿。ACP 通信协议Hermes 使用ACP (Agent Communication Protocol)进行通信。这是一个专门为 Agent 通信设计的协议主要方法包括方法说明initialize初始化连接获取协议版本和客户端能力authenticate处理认证支持多种认证方法session/new创建新会话设置工作目录和 MCP 服务器session/prompt发送提示并获取响应HagiCode 通过StdioAcpTransport实现 ACP 传输层启动 Hermes 子进程并通过标准输入输出进行通信。这事儿听起来复杂做起来也还行——主要是要有耐心。配置管理通过HermesPlatformConfiguration类管理配置public sealed class HermesPlatformConfiguration : IAcpPlatformConfiguration{public string ExecutablePath { get; set; } hermes;public string Arguments { get; set; } acp;public int StartupTimeoutMs { get; set; } 5000;public string ClientName { get; set; } HagiCode;public HermesAuthenticationConfiguration Authentication { get; set; }public HermesSessionDefaultsConfiguration SessionDefaults { get; set; }}在appsettings.json中配置 Hermes{Providers: {HermesCli: {ExecutablePath: hermes,Arguments: acp,StartupTimeoutMs: 10000,ClientName: HagiCode,Authentication: {PreferredMethodId: api-key,MethodInfo: {api-key: your-api-key-here}},SessionDefaults: {Model: claude-sonnet-4-20250514,ModeId: default}}}}配置这东西吧看着简单真要调对了也得费些功夫。Orleans 分布式架构HagiCode 使用 Orleans 构建分布式系统Hermes 集成通过以下组件实现HermesGrainOrleans Grain 实现处理会话执行HermesPlatformConfiguration平台特定配置HermesAcpSessionAdapterACP 会话适配器HermesConsole专用的验证控制台Orleans 这名字起得挺好听的传说中的阿里巴巴——虽然此 Orleans 非彼 Orleans但名字好听总是加分的。完整执行流程以下是 Hermes Provider 的核心执行逻辑private async IAsyncEnumerableAIStreamingChunk StreamCoreAsync(AIRequest request,string? embeddedCommandPrompt,[EnumeratorCancellation] CancellationToken cancellationToken){// 1. 创建传输层启动 Hermes 子进程await using var transport new StdioAcpTransport(platformConfiguration.GetExecutablePath(),platformConfiguration.GetArguments(),platformConfiguration.GetEnvironmentVariables(),platformConfiguration.GetStartupTimeout(),_loggerFactory.CreateLoggerStdioAcpTransport());await transport.ConnectAsync(cancellationToken);// 2. 初始化获取协议版本和认证方法var initializeResult await SendHermesRequestAsync(transport, nextRequestId, initialize,BuildInitializeParameters(platformConfiguration), cancellationToken);// 3. 处理认证var authMethods ParseAuthMethods(initializeResult);if (!isAuthenticated){var methodId platformConfiguration.Authentication.ResolveMethodId(authMethods);await SendHermesRequestAsync(transport, nextRequestId, authenticate, ...);}// 4. 创建会话var newSessionResult await SendHermesRequestAsync(transport, nextRequestId, session/new,BuildNewSessionParameters(platformConfiguration, workingDirectory, model), cancellationToken);var sessionId ParseSessionId(newSessionResult);// 5. 执行提示并收集流式响应await foreach (var payload in transport.ReceiveMessagesAsync(cancellationToken)){// 处理 session/update 通知转换为流式块if (TryParseSessionNotification(root, out var notification)){if (_responseMapper.TryConvertToStreamingChunk(notification, out var chunk)){yield return chunk;}}}}代码嘛看多了也就那么回事。重要的是思路对吧健康检查为了保证 Hermes 服务的可用性HagiCode 实现了健康检查机制public async TaskProviderTestResult PingAsync(CancellationToken cancellationToken default){var response await ExecuteAsync(new AIRequest{Prompt Reply with exactly PONG.,CessionId null,AllowedTools Array.Emptystring(),WorkingDirectory ResolveWorkingDirectory(null)},cancellationToken);var success string.Equals(response.Content.Trim(), PONG, StringComparison.OrdinalIgnoreCase);return new ProviderTestResult{ProviderName Name,Success success,ResponseTimeMs stopwatch.ElapsedMilliseconds,ErrorMessage success ? null : $Unexpected Hermes ping response: {response.Content}.};}这大概就是所谓的健康检查了罢。其实人也一样总要时不时检查一下自己——只是通常没人告诉我们应该检查什么。实践中的注意事项集成 Hermes 过程中有一些坑值得提前了解。这年头谁还没踩过几个坑呢认证方法配置Hermes 支持多种认证方法API Key、Token 等需要根据实际部署情况选择。配置错误会导致连接失败但错误信息可能不够直观。有时候报错信息跟实际原因差了十万八千里得慢慢排查。MCP 服务器配置创建会话时可以配置 MCP 服务器列表让 Hermes 调用外部工具。但要注意MCP 服务器地址必须可访问超时时间要合理设置服务器不可用时的降级处理这世道防不胜防啊。工作目录管理每个会话都需要指定工作目录确保 Hermes 能正确访问项目文件。对于多项目场景需要动态切换工作目录。说起来简单做起来要考虑的情况也挺多的。响应聚合处理Hermes 的响应可能分散在session/update通知和最终结果中需要正确合并处理否则会出现内容丢失。这事儿我也没少吃亏慢慢就好了。错误处理策略运行时错误应该明确返回而不是静默回退到其他 Provider。这样用户才知道是 Hermes 出了问题而不是莫名其妙换了别的模型。毕竟糊弄事儿也不是这么个糊弄法。

更多文章