Agentic Mesh(智能化网格)是一种由智能体(AI Agents)组成的自组织协作网络。智能体可以在网格中独立执行任务、相互通信,并适应不断变化的环境,从而更快速、更有效的完成任务。
Agentic Mesh 的特性
- 自主智能体:每个智能体都有特定的目标和能力,能够在无人工干预的情况下自主感知环境、做出决策并执行任务。
- 协同工作:智能体之间共享信息和任务分工,通过通信和协调机制解决单个智能体难以完成的复杂任务。
- 分布式架构:采用去中心化设计,每个智能体独立决策并在网络中互相发现、协作,具有更好的容错性和弹性。
- 标准化通信与协调机制:包含智能体注册表、通信网络、任务市场、信任与安全机制等核心模块,确保智能体们在同一框架下彼此发现、分工与监管。
- 持续学习与自适应:智能体会在协作和与环境的交互中不断学习,优化自身能力,带动整体系统演化和提升。
技术实现
Inngest 由于其拥有以下几点特性,非常适合用于构建 Agentic Mesh。
事件驱动架构
Inngest的事件驱动架构允许高效处理异步任务和工作流,这对于Agentic Mesh中多个智能体之间的通信和协调至关重要。当事件发生(例如用户请求或系统更新)时,Inngest可以触发相应的智能体进行响应。
功能注册表
Inngest的功能注册表类似于Agentic Mesh Registry,充当系统内所有智能体的中央目录。它便于智能体的发现和调用,使智能体之间能够相互协作。
可扩展性
Inngest能够根据工作负载弹性扩展,这对于可能涉及大量智能体和复杂交互的Agentic Mesh至关重要。
灵活性
Inngest提供了一个灵活的架构,可以轻松集成各种服务和工具,适应Agentic Mesh中不同的使用场景和需求。
可靠性
Inngest提供了错误处理、重试和监控机制,帮助在面临故障或意外事件时保持系统稳定。此外,Inngest支持安全通信和数据加密,保护敏感信息,并确保智能体在安全的环境中运行。
可观测性
Inngest拥有用户友好的界面和开发者友好的工具,使开发者能够更轻松地在Agentic Mesh中构建和部署智能体并观测它们的执行效果和性能。
更多有关Inngest的介绍请查看现代工作流引擎
集成 Inngest
在Nest中集成Inngest, 首先需要先安装相关依赖
pnpm add inngest
创建Inngest模块,文件结构如下:
(base) ➜ inngest git:(main) ✗ tree .
.
├── index.ts
├── inngest-module-options.interface.ts
├── inngest.decorator.ts
├── inngest.module-definition.ts
├── inngest.module.ts
└── inngest.service.ts
inngest-module-options.interface.ts
用于定义模块的配置项
import { ClientOptions } from "inngest";
export interface InngestModuleOptions {
inngest: ClientOptions;
path?: string;
}
inngest.module-definition.ts
用于构建模块配置
import { ConfigurableModuleBuilder } from "@nestjs/common";
import { InngestModuleOptions } from "./inngest-module-options.interface";
export const {
ConfigurableModuleClass,
MODULE_OPTIONS_TOKEN,
OPTIONS_TYPE,
ASYNC_OPTIONS_TYPE,
} = new ConfigurableModuleBuilder<InngestModuleOptions>()
.setExtras(
{
isGlobal: true,
},
(definition, extras) => ({
...definition,
global: extras.isGlobal,
}),
)
.build();
inngest.module.ts
定义模块的依赖项和注册模块的相关服务
import { DynamicModule, Module } from "@nestjs/common";
import { ASYNC_OPTIONS_TYPE, ConfigurableModuleClass, OPTIONS_TYPE } from "./inngest.module-definition";
import { InngestService } from "./inngest.service";
@Module({
providers: [InngestService],
exports: [InngestService]
})
export class InngestModule extends ConfigurableModuleClass {
static register(options: typeof OPTIONS_TYPE): DynamicModule {
return {
...super.register(options),
};
}
static registerAsync(options: typeof ASYNC_OPTIONS_TYPE): DynamicModule {
return {
...super.registerAsync(options),
};
}
}
inngest.service.ts
创建Inngest实例
import { Inject, Injectable } from "@nestjs/common";
import { Inngest } from "inngest";
import { InngestModuleOptions } from "./inngest-module-options.interface";
import { MODULE_OPTIONS_TOKEN } from "./inngest.module-definition";
@Injectable()
export class InngestService extends Inngest {
constructor(
@Inject(MODULE_OPTIONS_TOKEN)
private readonly moduleOptions: InngestModuleOptions
) {
if (!moduleOptions) {
throw new Error("InngestModuleOptions is not defined");
}
super(moduleOptions.inngest);
}
}
inngest.decorator.ts
使用自定义装饰器来标识Agent函数(Inngest Function)
import { DiscoveryService } from "@nestjs/core";
import { Inngest } from "inngest";
export const Agent = DiscoveryService.createDecorator<{
config: Parameters<Inngest["createFunction"]>[0],
trigger: Parameters<Inngest["createFunction"]>[1],
}>();
由于使用了DiscoveryService所以需要在InngestModule中导入DiscoveryModule
import { DiscoveryModule } from "@nestjs/core";
@Module({
imports: [DiscoveryModule]
})
export class InngestModule extends ConfigurableModuleClass {
}
Agent装饰器的使用示例:
import { Agent } from "@/shared/modules/inngest";
import { Injectable } from "@nestjs/common";
import { Context } from "inngest";
@Injectable()
export class WelcomeScene {
@Agent({
config: {
id: 'welcome-greet',
name: "Greeting Agent",
description: 'This is an agent used to greet users.'
},
trigger: {
event: 'welcome-greet',
}
})
async greeting({ event, step }: Context) {
await step.sleep("wait-a-moment", "1s");
return { message: `Hello ${event.data.username}!` };
}
}
Agent发现与注册
在Nest中可通过结合DiscoveryService和MetadataScanner实现Agent的发现与注册
修改InngestService的代码如下:
import { Inject, Injectable } from "@nestjs/common";
import { DiscoveryService, MetadataScanner } from "@nestjs/core";
import { Inngest } from "inngest";
import { InngestModuleOptions } from "./inngest-module-options.interface";
import { Agent } from "./inngest.decorator";
import { MODULE_OPTIONS_TOKEN } from "./inngest.module-definition";
@Injectable()
export class InngestService extends Inngest {
// Agent 注册表
private readonly agents: ReturnType<Inngest["createFunction"]>[] = [];
constructor(
@Inject(MODULE_OPTIONS_TOKEN)
private readonly moduleOptions: InngestModuleOptions,
private readonly discoveryService: DiscoveryService,
private readonly metadataScanner: MetadataScanner
) {
if (!moduleOptions) {
throw new Error("InngestModuleOptions is not defined");
}
super(moduleOptions.inngest);
}
getPath() {
return this.moduleOptions.path;
}
getAgents() {
if (this.agents.length > 0) {
return this.agents;
}
// 遍历所有服务提供者
const providers = this.discoveryService.getProviders();
for (const wrapper of providers) {
if (!wrapper.metatype?.prototype) {
continue;
}
const handlers = this.metadataScanner.getAllMethodNames(
wrapper.metatype.prototype
);
// 遍历所有服务提供者的方法
for (const handler of handlers) {
// 找到用 @Agent 装饰的方法
const metadata = this.discoveryService.getMetadataByDecorator(
Agent,
wrapper,
handler
);
if (!metadata) {
continue;
}
const { config, trigger } = metadata;
// 注册并保存 Agent
this.agents.push(this.createFunction(
config,
trigger,
wrapper.instance[handler].bind(wrapper.instance)
));
}
}
return this.agents;
}
}
为Inngest UI提供访问Inngest实例的中间件
import { DynamicModule, MiddlewareConsumer, Module, NestModule } from "@nestjs/common";
import { DiscoveryModule } from "@nestjs/core";
import { serve } from "inngest/express";
import { ASYNC_OPTIONS_TYPE, ConfigurableModuleClass, OPTIONS_TYPE } from "./inngest.module-definition";
import { InngestService } from "./inngest.service";
@Module({
imports: [DiscoveryModule],
providers: [InngestService],
exports: [InngestService],
})
export class InngestModule extends ConfigurableModuleClass implements NestModule {
constructor(
private readonly inngestService: InngestService,
) {
super();
}
configure(consumer: MiddlewareConsumer) {
consumer
.apply(
serve({
client: this.inngestService,
functions: this.inngestService.getAgents()
})
)
// 将中间件应用到 /api/inngest 路由
.forRoutes(this.inngestService.getPath());
}
static register(options: typeof OPTIONS_TYPE): DynamicModule {
return {
...super.register(options),
};
}
static registerAsync(options: typeof ASYNC_OPTIONS_TYPE): DynamicModule {
return {
...super.registerAsync(options),
};
}
}
inngest.config.ts
定义配置文件
import constant from "@/shared/constants";
import { InngestModuleOptions } from "@/shared/modules/inngest";
import { registerAs } from "@nestjs/config";
export default registerAs<InngestModuleOptions>("inngest", () => {
return {
path: 'api/inngest',
inngest: {
id: 'Agentic Mesh'
}
};
});
最后在根模块中注册 InngestModule
import { InngestModule } from "@/shared/modules/inngest";
@Module({
imports: [
InngestModule.registerAsync({
inject: [ConfigService],
useFactory: (config: ConfigService) => config.get("inngest"),
}),
]
...
})
export class AppModule { }
为了防止多次注册相同的Agent可以使用条件装配模块
import { ConditionalModule, ConfigModule, ConfigService } from "@nestjs/config";
ConditionalModule.registerWhen(
InngestModule.registerAsync({
inject: [ConfigService],
useFactory: (config: ConfigService) => config.get("inngest"),
}),
() => process.env.ENABLE_INNGEST // 只有环境变量 `ENABLE_INNGEST` 为true时才注册 `InngestModule`
),
运行Inngest UI观测智能体
npx inngest-cli@latest dev -u http://localhost:9000/api/inngest
访问http://127.0.0.1:8288/可以查看Inngest控制台
查看Functions页面可以看到我们通过@Agent装饰器定义的智能体函数
通过InngestService或者手动的方式可以触发智能体函数的执行
在Runs页面可以查看智能体的运行结果和相关元数据
使用 DeepSeek 优化 Greeting Agent
私有化部署DeepSeek请查看基于DeepSeek R1模型的私有化部署实践
import { AgentService } from "@/shared/modules/agent";
import { Agent } from "@/shared/modules/inngest";
import { Injectable } from "@nestjs/common";
import { generateText } from "ai";
import { Context } from "inngest";
@Injectable()
export class WelcomeScene {
constructor(private readonly agentService: AgentService) { }
@Agent({
config: {
id: 'welcome-greet',
name: "Greeting Agent",
description: 'This is an agent used to greet users.'
},
trigger: {
event: 'welcome-greet',
}
})
async greeting({ event, step }: Context) {
await step.sleep("wait-a-moment", "1s");
const model = this.agentService.createDeepSeekR1Model();
const { text } = await generateText({
model,
prompt: `请用一句话向${event.data.username}问好。`,
});
return { message: text };
}
}
<think>
好,用户让我用一句话向Roy Lin问好。首先,我需要确认Roy Lin是谁。查一下,Roy Lin是中国台湾省著名的演员和导演,以在电影和电视剧中的出色表现而闻名。所以,我应该用正式且尊重的方式称呼他。
接下来,我需要考虑如何礼貌地问好。通常,问好可以用“您好”或者“Hello”,但考虑到Roy Lin是公众人物,使用更正式的称呼会更合适。所以,我应该使用“Hello Roy Lin”或者“Hi Roy Lin”。
然后,我需要确保整个句子简洁明了,没有多余的信息。用户只要求一句问好,所以不需要添加额外的内容。
最后,检查一下语法和礼貌程度,确保问好是真诚的,并且符合正式场合的用语。
综上所述,我应该回复“Hello Roy Lin”或者“Hi Roy Lin”。
</think>
"Hello Roy Lin!"
智能体互操作
const agents = this.inngestService.getAgents();
const mesh = `
系统中所有的Agent信息如下:
${agents.map((agent) => `名称:${agent.name} 职责:${agent.description} ID:${agent.id}`).join('\n')}
要让某个Agent工作,请使用它的ID作为事件名称构建payload, 例如:
const payload = {
"name": "welcome-greet",
"data": { "username": "Roy Lin" }
};
触发事件请使用下面的命令:
await inngestService.send(payload);
`;