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);
`;