agent - 认识智能体接口
2026年1月14日 上午11:36:16
在 Solon AI 框架中,Agent(智能体) 是执行任务的核心单元。它不仅是对大语言模型(LLM)的封装,更是集成了 状态管理(Session)、工具调用(Tools)、长短记忆(History) 和 工作流控制(Flow) 的自治实体。
1、智能体接口(Agent)
智能体(Agent)是 Solon AI Agent 的最小协作单元。在设计上,它具有“多重身份”以满足不同层级的交互需求:
| 维度 | 属性 | 描述 | 视角 |
|---|---|---|---|
| 对外身份 | name | 唯一标识:智能体在团队中的名字 | 同伴视角(你是谁) |
| description | 职责描述:用于语义路由与任务分发的参考依据 | 主管视角(你能干什么) | |
| profile | 交互契约:定义能力画像、输入限制等约束条件 | 团队视角(如何用你) | |
| 对内身份 | systemPrompt | 系统提示词:赋予底层 LLM 角色灵魂与执行标准 | 核心视角(我该怎么做) |
| 行为实现 | call | 核心逻辑:具体的推理与工具执行过程 | 执行视角 |
| run | 节点驱动:由团队协议(TeamProtocol)驱动的生命周期管理 | 框架视角 |
Agent 接口继承自 AgentHandler 和 NamedTaskComponent,支持在 Solon Flow 工作流中自动化运行。
2、快速开始:定制一个智能体
您可以直接实现 Agent 接口来定义特定的业务逻辑:
Agent coder = new Agent() {
@Override public String name() { return "Coder"; }
@Override public String description() { return "负责编写核心业务代码"; }
@Override public AssistantMessage call(Prompt prompt, AgentSession session) {
return ChatMessage.ofAssistant("代码已提交: login.java");
}
};
框架内置实现:
- SimpleAgent: 基础智能体,适用于简单的指令响应。
- ReActAgent: 具备“思考-行动-观察”循环的自反思智能体,支持工具调用。
- TeamAgent: 复合智能体,负责指挥成员按协议(如 A2A)进行协作。
3、智能体构建样例
SimpleAgent resumeAgent = SimpleAgent.of(chatModel)
.name("ResumeExtractor")
.title("简历信息提取器")
.systemPrompt(SimpleSystemPrompt.builder()
.role("你是一个专业的人事助理")
.instruction("请从用户提供的文本中提取关键信息")
.build())
.outputSchema(ResumeInfo.class)
.build();
ReActAgent illustrator = ReActAgent.of(chatModel)
.name("illustrator")
.description("负责视觉风格定义")
.profile(p -> p.skillAdd("矢量插画", "色彩心理学")
.modeAdd("text", "image")
.metaPut("engine", "Nano Banana")
.style("极简主义"))
.systemPrompt(ReActSystemPrompt.builder()
.role("首席矢量插画专家")
.instruction("1. 擅长极简主义风格,通过‘色彩心理学’选择能引起情感共鸣的主色调。\n" +
"2. 针对用户需求,先构思视觉隐喻(Thought),再定义具体的视觉规格。\n" +
"3. 如果需要生成图片,请输出具体的 Prompt 给底层图像引擎(Nano Banana)。\n" +
"4. 最终输出应包含:风格描述、配色方案、圆角/线条规范,以及可选的图片描述。")
.build())
.build();
TeamAgent team = TeamAgent.of(chatModel)
.name("sequential_pipeline")
.protocol(TeamProtocols.SEQUENTIAL)
.agentAdd(extractor, converter, polisher)
.build();
4、具体接口参考
public interface Agent extends AgentHandler, NamedTaskComponent {
static final Logger LOG = LoggerFactory.getLogger(Agent.class);
/**
* 智能体名称(唯一标识)
*/
String name();
/**
* 智能体职责描述(用于语义路由与任务分发参考)
*/
String description();
/**
* 智能体档案(能力画像与交互契约)
*/
default AgentProfile profile() {
return null;
}
/**
* 生成动态职责描述(支持模板渲染)
*/
default String descriptionFor(FlowContext context) {
if (context == null) {
return description();
}
return SnelUtil.render(description(), context.model());
}
/**
* 响应式任务执行(继续上次的任务)
*
* @param session 会话上下文
*/
default AssistantMessage call(AgentSession session) throws Throwable {
return call(null, session);
}
/**
* 指定指令的任务执行(开始新任务)
*
* @param prompt 显式指令
* @param session 会话上下文
*/
AssistantMessage call(Prompt prompt, AgentSession session) throws Throwable;
/**
* Solon Flow 节点运行实现
* <p>处理 Session 初始化、协议注入、推理执行及轨迹同步。</p>
*/
@Override
default void run(FlowContext context, Node node) throws Throwable {
// 1. 获取或初始化会话
AgentSession session = context.computeIfAbsent(KEY_SESSION, k -> new InMemoryAgentSession("tmp"));
// 2. 处理团队协作轨迹与拦截
String traceKey = context.getAs(KEY_CURRENT_TRACE_KEY);
TeamTrace trace = (traceKey != null) ? context.getAs(traceKey) : null;
if (trace != null) {
trace.setLastAgentName(this.name());
for (RankEntity<TeamInterceptor> item : trace.getOptions().getInterceptorList()) {
if (item.target.shouldAgentContinue(trace, this) == false) {
trace.addStep(ChatRole.ASSISTANT, name(),
"[Skipped] Cancelled by " + item.target.getClass().getSimpleName(), 0);
if (LOG.isDebugEnabled()) {
LOG.debug("Agent [{}] execution skipped by interceptor: {}", name(), item.target.getClass().getSimpleName());
}
return;
}
}
}
// 3. 准备提示词并执行推理
Prompt effectivePrompt = null;
if (trace != null) {
effectivePrompt = trace.getProtocol().prepareAgentPrompt(trace, this, trace.getPrompt(), trace.getConfig().getLocale());
}
if (LOG.isDebugEnabled()) {
LOG.debug("Agent [{}] start calling...", name());
}
long start = System.currentTimeMillis();
AssistantMessage msg = call(effectivePrompt, session);
long duration = System.currentTimeMillis() - start;
// 4. 同步执行轨迹与结果处理
if (trace != null) {
String rawContent = (msg.getContent() == null) ? "" : msg.getContent().trim();
String finalResult = trace.getProtocol().resolveAgentOutput(trace, this, rawContent);
if (finalResult == null || finalResult.isEmpty()) {
finalResult = "Agent [" + name() + "] processed but returned no textual content.";
}
trace.addStep(ChatRole.ASSISTANT, name(), finalResult, duration);
// 执行后置回调
trace.getProtocol().onAgentEnd(trace, this);
trace.getOptions().getInterceptorList().forEach(item -> item.target.onAgentEnd(trace, this));
}
if (LOG.isDebugEnabled()) {
LOG.debug("Agent [{}] call completed in {}ms", name(), duration);
}
}
// --- Context Keys ---
static String KEY_CURRENT_TRACE_KEY = "_current_trace_key_";
static String KEY_SESSION = "_SESSION_";
static String KEY_PROTOCOL = "_PROTOCOL_";
// --- Node IDs ---
static String ID_START = "start";
static String ID_END = "end";
static String ID_REASON_BEF = "reason_bef";
static String ID_REASON = "reason";
static String ID_ACTION_BEF = "action_bef";
static String ID_ACTION = "action";
static String ID_SYSTEM = "system";
static String ID_SUPERVISOR = "supervisor";
static String ID_BIDDING = "bidding";
}