基于 Spring AI 与 Spring AI Alibaba 的 Agent 设计与实现说明
基于 Spring AI 与 Spring AI Alibaba 的 Agent 设计与实现说明
本人就最近开发的Agent框架设计和实现交流,不喜勿喷!
平台级 Agent 能力整合中的设计思想、动机与价值:
-
设计模板:本平台基于 DDD(领域驱动设计)分层理念,将高阶 AI Agent 编排需求拆分至 interfaces、application、domain、infrastructure 四层,各层解耦、接口清晰,便于插件式扩展与测试。依托 Spring AI 及 Alibaba Graph 能力,将 Agent 流程以 StateGraph 编排,统一状态持久化、能力调用、权限校验与上下文封装。每层有约束、各司其职,实现“能力即契约”、“状态即协议”。
-
核心解决的问题:
- 统一会话与能力管理:将对话记忆、状态信息、多轮推理等能力抽象为标准端口与状态键,支撑复杂 Agent 编排、多步 LLM 工作流与能力市场插件化。
- 可组合的 Agent 流程编排:基于 Spring AI Alibaba StateGraph,实现灵活、多节点、多策略的 Agent 运行路径,支持插拔式节点拓展与能力市场动态挂载。
- 多租户与权限体系:强制以 tenantId 作用域贯穿数据、能力注册、插件安装,保证隔离性与多租户安全,并结合 Sa-Token RBAC 做到 API 指令级、能力级精细化管控。
- 上下文融合与持续对话:通过会话消息、领域上下文、元模型、知识库等多维上下文的自动汇聚、窗口管理,增强 LLM 任务的连续性、准确性与可解释性。
- 基础设施与工程可落地性:严格规范数据库迁移、DTO 转换、Graph 配置、插件注册、扩展入口,兼容主流云原生与 DevOps 流程,为企业级 AI Agent 实战提供标准参考。
-
带来的价值:
- 扩展性:能力市场、插件机制和 StateGraph 图模型,使新能力、业务场景、行业插件能快速接入与迭代,无需侵入核心编排代码。
- 工程规范性:按 DDD 拆分、配置驱动、强约束接口,降低后期维护/升级/迁移成本,提高研发协作效率。
- 安全与合规:租户隔离、权限校验、操作审计、状态全链路管控,满足合规/安全要求,适应制造、政企等高要求场景。
- 知识落地与创新基础:通过通用上下文融合、会议/报告/QA 等能力沉淀,为后续自定义 Agent、自动化业务流程、MCP 工具生态提供平台级支撑。
整体而言,agent-platform 结合 Spring AI Alibaba,提供了一套高可用、高扩展性、工程化规范的多智能体平台基座,既满足复杂业务编排,又支撑持续进化与生态发展,是 AI Agent 能力产品化、服务化的重要基础设施。
1. 设计思想与整体框架
1.1 目标与分层
- 统一编排入口:以 Supervisor 作为单次用户请求的编排边界,对上暴露 REST/SSE,对下组合「规划 → 能力调用 → 状态收尾」。
- 能力即契约:业务动作抽象为 Capability(元数据 + 权限 +
CapabilityHandler实现),由 CapabilityRegistry 注册,由 CapabilityInvoker 统一鉴权与审计后调用。 - 插件市场(Agent 市场):插件目录由代码装配(
PluginMarketCatalogConfiguration),租户是否启用某插件由tenant_plugin_install持久化;会话 preset 与插件安装状态联动(例如 QA 模拟预设要求先安装对应插件)。 - DDD 分层:
interfaces(REST/SSE)→application(用例:会话、Supervisor 运行、上下文装配)→domain(会话聚合、Supervisor 状态键、能力端口、记忆端口)→infrastructure(MyBatis、Neo4j 可选 Sink、Graph 配置、安全)。
1.1.1 逻辑分层架构图
下图从调用链与依赖方向概括服务边界:网关仅作路由与鉴权;application 编排用例并依赖 domain 端口;infrastructure 实现端口并装配 Spring AI Alibaba 图运行时。

1.2 与 Spring AI Alibaba 的映射关系
| 概念 | 工程中的落点 |
|---|---|
图状态 OverAllState / StateGraph |
PlatformSupervisorGraphConfiguration 中确定性流水线图;LLM 路径则使用 LlmRoutingAgent |
| 子 Agent | ReactAgent(如 echo)作为 LlmRoutingAgent 的 sub-agent;工具侧通过 SupervisorCapabilityTools 暴露为 @Tool |
| Checkpoint / Thread | RunnableConfig.threadId 与会话 checkpointThreadId 绑定(CheckpointBinding),MemorySaver 用于图编译配置 |
| Hooks | ModelCallLimitHook 限制 Supervisor 与子 Agent 的模型/工具调用次数 |
1.3 模块依赖总览(PlantUML)
下图按 DDD 四层 + 关键类 展开,仅画主要依赖,避免蜘蛛网式连线;CapabilityInvoker / DefaultExecutionPlanningEngine 由 Graph 配置类在确定性路径中注入使用。

1.4 Supervisor 双路径(PlantUML)
运行时根据是否启用 LLM Supervisor 在 LLM 路由子 Agent 与 确定性 StateGraph 单节点流水线 之间二选一(见 SupervisorRunApplicationService.invokeWithTimeout)。

2. Spring AI + Spring AI Alibaba 实现要点
2.1 Supervisor 设计与实现
配置类 PlatformSupervisorGraphConfiguration 集中定义三类 Bean:
- LLM Supervisor:
LlmRoutingAgent(platformLlmSupervisor),绑定ChatModel、CompileConfig(MemorySaver+Store)、ModelCallLimitHook,并注册子 Agent 列表(当前示例为platformEchoReactAgent)。 - 子 Agent:
ReactAgent(echo),通过MethodToolCallbackProvider注入SupervisorCapabilityTools,将能力调用包装为 LLM 可调用的 Tool。 - 确定性图:
StateGraph(platformDeterministicSupervisorGraph)单节点deterministic_pipeline:内部顺序执行 ExecutionPlanningEngine.plan → 逐步 CapabilityInvoker.invoke,并把PIPELINE_TRACE、EXECUTION_PLAN、echo槽位与supervisor_terminal写入状态。
LlmRoutingAgent 注册与 CompileConfig 示例:
@Bean
@ConditionalOnProperty(name = "agent.platform.supervisor.llm-enabled", havingValue = "true")
@ConditionalOnBean(ChatModel.class)
public LlmRoutingAgent platformLlmSupervisor(
ChatModel chatModel,
@Qualifier("platformEchoReactAgent") ReactAgent echo,
SupervisorProperties supervisorProperties,
MemorySaver platformSupervisorMemorySaver,
Store platformSupervisorStore) {
CompileConfig compileConfig = CompileConfig.builder()
.saverConfig(SaverConfig.builder().register(platformSupervisorMemorySaver).build())
.store(platformSupervisorStore)
.build();
return LlmRoutingAgent.builder()
.name("platform_supervisor")
.description("Routes user requests to registered sub-agents (e.g. echo).")
.model(chatModel)
.subAgents(List.of(echo)) // 示例
.systemPrompt("""
You are the platform supervisor. Choose the best sub-agent for the user message.
If the user only needs a connectivity test or echo, delegate to the echo agent.
When done, respond with a short summary of the sub-agent result.""")
.instruction("{input}")
.compileConfig(compileConfig)
.hooks(ModelCallLimitHook.builder()
.runLimit(supervisorProperties.getMaxSupervisorLlmCalls())
.build())
.build();
}
确定性单节点:plan → 循环 invoke → 写出终态:
@Bean("platformDeterministicSupervisorGraph")
public StateGraph platformDeterministicSupervisorGraph(
CapabilityInvoker capabilityInvoker,
ExecutionPlanningEngine executionPlanningEngine,
CapabilityRegistry capabilityRegistry) throws GraphStateException {
StateGraph graph = new StateGraph("platform_supervisor_deterministic", () -> {
Map<String, KeyStrategy> strategies = new HashMap<>();
strategies.put(STATE_INPUT, new ReplaceStrategy());
strategies.put("tenantId", new ReplaceStrategy());
strategies.put("sessionId", new ReplaceStrategy());
strategies.put("sessionPreset", new ReplaceStrategy());
strategies.put(STATE_ECHO, new ReplaceStrategy());
strategies.put(STATE_SUPERVISOR_TERMINAL, new ReplaceStrategy());
strategies.put(SupervisorGraphStateKeys.ONTOLOGY_SUMMARY, new ReplaceStrategy());
strategies.put(SupervisorGraphStateKeys.ONTOLOGY_REVISION, new ReplaceStrategy());
strategies.put(SupervisorGraphStateKeys.PIPELINE_TRACE, new ReplaceStrategy());
strategies.put(SupervisorGraphStateKeys.EXECUTION_PLAN, new ReplaceStrategy());
strategies.put(SupervisorGraphStateKeys.CONVERSATION_HISTORY, new AppendStrategy());
return strategies;
});
...
graph.addNode("deterministic_pipeline", node_async(node))
.addEdge(START, "deterministic_pipeline")
.addEdge("deterministic_pipeline", END);
return graph;
}
运行服务 SupervisorRunApplicationService:
- 从
MemoryFacade加载SessionAggregate,使用checkpointThreadId构造RunnableConfig。 - 初始状态包含
input、tenantId、sessionId、sessionPreset及上下文装配结果。 - 在独立线程中调用
invoke,并 传播TenantContext与RequestContextHolder,避免异步丢失租户与请求上下文。 - 使用 超时(
SupervisorProperties.invokeTimeoutMs)包装Future.get,映射为SupervisorTerminalState(FINISH_OK/FINISH_ERROR/TIMEOUT等)。
单次 run:初始状态、threadId、双路径选择与成功后 saveExchange:
public SupervisorRunResult run(String sessionId, String userMessage) {
Long tenantId = TenantContext.get();
if (tenantId == null) {
throw new IllegalStateException("tenant context missing");
}
SessionAggregate session = memoryFacade.findSession(tenantId, sessionId)
.orElseThrow(() -> new IllegalArgumentException("session not found"));
String threadId = session.checkpointThreadId();
RunnableConfig config = RunnableConfig.builder().threadId(threadId).build();
Map<String, Object> initial = new HashMap<>();
initial.put(PlatformSupervisorGraphConfiguration.STATE_INPUT, userMessage == null ? "" : userMessage);
initial.put("tenantId", tenantId);
initial.put("sessionId", sessionId);
initial.put("sessionPreset", session.preset() == null ? "" : session.preset());
SessionRoot sessionRoot = new SessionRoot(tenantId, null, sessionId, threadId, null, session.preset());
initial.putAll(supervisorContextAssemblyService.assemble(sessionRoot));
String msg = userMessage == null ? "" : userMessage;
memoryFacade.appendEvent(tenantId, sessionId, "SUPERVISOR_RUN_START", Map.of(
"message", msg,
"preset", session.preset(),
SupervisorGraphStateKeys.ONTOLOGY_REVISION, String.valueOf(initial.get(SupervisorGraphStateKeys.ONTOLOGY_REVISION))));
LlmRoutingAgent llm = llmSupervisorProvider.getIfAvailable();
if (llm == null) {
log.debug("LlmRoutingAgent bean not available — using deterministic graph. "
+ "Enable agent.platform.supervisor.llm-enabled=true and configure spring.ai.openai.api-key (ChatModel).");
}
try {
Optional<OverAllState> out = invokeWithTimeout(llm, initial, config);
if (out.isEmpty()) {
memoryFacade.appendEvent(tenantId, sessionId, "SUPERVISOR_RUN_FINISH", Map.of("terminal", "EMPTY_STATE"));
return new SupervisorRunResult(SupervisorTerminalState.FINISH_ERROR, Map.of(), "empty graph state");
}
OverAllState state = out.get();
Map<String, Object> snap = new LinkedHashMap<>(state.data());
memoryFacade.appendEvent(tenantId, sessionId, "SUPERVISOR_RUN_FINISH", Map.of("terminal", "OK"));
// Save conversation exchange after successful supervisor run
try {
String answer = Objects.toString(snap.get(PlatformSupervisorGraphConfiguration.STATE_ECHO), "");
String agentId = conversationMemoryProperties.resolveAgentId(session.preset());
conversationMemoryFacade.saveExchange(tenantId, sessionId, agentId, msg, answer, "{}");
} catch (Exception e) {
log.warn("Failed to save conversation exchange for sessionId={}", sessionId, e);
}
return new SupervisorRunResult(SupervisorTerminalState.FINISH_OK, snap, "ok");
} catch (TimeoutException e) {
log.warn("supervisor invoke timeout sessionId={} ms={}", sessionId, supervisorProperties.getInvokeTimeoutMs());
memoryFacade.appendEvent(tenantId, sessionId, "SUPERVISOR_RUN_TIMEOUT", Map.of("ms", supervisorProperties.getInvokeTimeoutMs()));
return new SupervisorRunResult(SupervisorTerminalState.TIMEOUT, Map.of(), e.getMessage());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
memoryFacade.appendEvent(tenantId, sessionId, "SUPERVISOR_RUN_ERROR", Map.of("error", "interrupted"));
return new SupervisorRunResult(SupervisorTerminalState.FINISH_ERROR, Map.of(), "interrupted");
} catch (Exception e) {
log.warn("supervisor invoke failed sessionId={}", sessionId, e);
memoryFacade.appendEvent(tenantId, sessionId, "SUPERVISOR_RUN_ERROR", Map.of("error", String.valueOf(e.getMessage())));
return new SupervisorRunResult(SupervisorTerminalState.FINISH_ERROR, Map.of(), e.getMessage());
}
}
异步线程内切换 LLM 图与确定性图:
private Optional<OverAllState> invokeWithTimeout(
LlmRoutingAgent llm,
Map<String, Object> initial,
RunnableConfig config) throws Exception {
Long tenantId = TenantContext.get();
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
ExecutorService pool = Executors.newSingleThreadExecutor();
try {
Future<Optional<OverAllState>> future = pool.submit(() -> {
try {
if (requestAttributes != null) {
RequestContextHolder.setRequestAttributes(requestAttributes, true);
}
if (tenantId != null) {
TenantContext.set(tenantId);
}
if (llm != null) {
return llm.invoke(initial, config);
}
return deterministicCompiledGraph.invoke(initial, config);
} finally {
TenantContext.clear();
RequestContextHolder.resetRequestAttributes();
}
});
return future.get(supervisorProperties.getInvokeTimeoutMs(), TimeUnit.MILLISECONDS);
} catch (ExecutionException e) {
Throwable c = e.getCause() != null ? e.getCause() : e;
if (c instanceof Exception ex) {
throw ex;
}
throw new IllegalStateException(c);
} finally {
pool.shutdownNow();
}
}
图状态键(写入 / 读取 OverAllState 的契约):
public final class SupervisorGraphStateKeys {
public static final String ONTOLOGY_SUMMARY = "ontology_summary";
public static final String ONTOLOGY_REVISION = "ontology_revision";
/** Non-LLM deterministic pipeline: list of per-step trace (capabilityId, rationale, output). */
public static final String PIPELINE_TRACE = "pipeline_trace";
/** Structured intent + plan summary from {@link com.wasp.agentplatform.platform.application.ExecutionPlanningEngine}. */
public static final String EXECUTION_PLAN = "execution_plan";
/** Conversation history list (List of ConversationMessage). */
public static final String CONVERSATION_HISTORY = "conversation_history";
2.2 Context 构建
模式:可插拔 贡献者链。SupervisorContextAssemblyService 收集全部 SupervisorContextContributor 实现,按 Spring @Order 排序,将各 ContextFragment 合并为图初始 Map(后写覆盖同键)。
装配入口:
@Service
public class SupervisorContextAssemblyService {
private final List<SupervisorContextContributor> contributors;
public SupervisorContextAssemblyService(List<SupervisorContextContributor> contributors) {
List<SupervisorContextContributor> copy = new ArrayList<>(contributors);
copy.sort(AnnotationAwareOrderComparator.INSTANCE);
this.contributors = List.copyOf(copy);
}
public Map<String, Object> assemble(SessionRoot root) {
Map<String, Object> merged = new LinkedHashMap<>();
for (SupervisorContextContributor c : contributors) {
for (ContextFragment f : c.contribute(root)) {
merged.put(f.key(), f.value());
}
}
return merged;
}
}
当前内置贡献者:
| 顺序 | 类 | 注入状态键 |
|---|---|---|
| 0 | OntologySummaryContextContributor |
ontology_summary、ontology_revision(经 OntologyFacade.getContextSlice) |
| 1 | ConversationHistoryContributor |
conversation_history(从 ConversationMemoryFacade.getRecentHistory 格式化为文本,控制轮数与截断) |
本体片段写入示例:
@Override
public List<ContextFragment> contribute(SessionRoot root) {
OntologyContextSlice slice = ontologyFacade.getContextSlice(root);
return List.of(
new ContextFragment("ontology", SupervisorGraphStateKeys.ONTOLOGY_SUMMARY, slice.summaryText()),
new ContextFragment("ontology", SupervisorGraphStateKeys.ONTOLOGY_REVISION, slice.revisionToken())
);
}
该设计与 Spring AI Alibaba 的 图初始状态 一致:在 invoke 前一次性写入 OverAllState,后续节点或 LLM 路由即可读取。

2.3 Agent 市场(插件市场)
工程中的「市场」分为两层:
- 目录(Catalog):
PluginMarketCatalogConfiguration以 BeanList<PluginMarketEntry>形式 代码声明 可选插件(名称、描述、关联 preset、是否需安装等)。 - 租户安装态:
TenantPluginMarketService读写表tenant_plugin_install,提供listInstalledPluginIds、install、isInstalled。
目录 Bean 示例:
@Configuration
public class PluginMarketCatalogConfiguration {
@Bean
public List<PluginMarketEntry> pluginMarketCatalog() {
return List.of(
new PluginMarketEntry(
PluginMarketIds.QA_SIM,
"QA 模拟 Agent",
"模拟本体仿真引擎 QA 四段式:Intent → Data → Analyst → Executor(确定性桩 + echo 收尾),用于联调插件市场与会话流。",
PluginMarketIds.PRESET_QA_SIM,
true
)
);
}
}
与会话联动:AgentSessionApplicationService.createSession 在特定 preset(如 PRESET_QA_SIM)下校验租户是否已安装对应插件(PluginMarketIds.QA_SIM),未安装则拒绝创建会话。
public String createSession(String preset) {
Long tenantId = TenantContext.get();
if (tenantId == null) {
throw new IllegalStateException("tenant context missing");
}
String sessionId = UUID.randomUUID().toString();
String p = preset == null ? "default" : preset;
if (PluginMarketIds.PRESET_QA_SIM.equals(p)) {
if (!tenantPluginMarketService.isInstalled(tenantId, PluginMarketIds.QA_SIM)) {
throw new IllegalArgumentException("plugin not installed: " + PluginMarketIds.QA_SIM);
}
}
String checkpointThreadId = CheckpointBinding.threadId(tenantId, sessionId);
memoryFacade.saveSession(tenantId, sessionId, checkpointThreadId, p);
log.info("agent.session.created sessionId={} tenantId={} preset={}", sessionId, tenantId, p);
return sessionId;
}
这样 市场 控制「能用哪些 Agent 预设」,能力注册表 控制「运行时可调哪些 Capability」。
2.4 Agent 调度执行与退出
调度:
- 确定性路径:
ExecutionPlanningEngine基于用户文本、可见能力列表与ontology_summary做 意图分析(IntentAnalysis)与 步骤分解(PlanStep),再循环调用CapabilityInvoker;单节点图保证 START → deterministic_pipeline → END 一次走完。 - LLM 路径:由
LlmRoutingAgent内部完成「选子 Agent → 子 Agent ReAct」;子 Agent 通过 Tool 间接调用同一套CapabilityInvoker,能力边界一致。
规划引擎入口:
@Override
public ExecutionPlan plan(ExecutionPlanningRequest request) {
String message = request.userMessage() == null ? "" : request.userMessage().trim();
List<CapabilityEntry> caps = request.visibleCapabilities() == null ? List.of() : request.visibleCapabilities();
IntentAnalysis intent = parseIntent(message, caps);
List<PlanStep> steps = decompose(intent, message, request.ontologySummary(), caps);
String summary = intent.kind() + " (" + String.format(Locale.ROOT, "%.2f", intent.confidence()) + "): "
+ intent.rationale() + " → " + steps.size() + " step(s)";
return new ExecutionPlan(intent, List.copyOf(steps), summary);
}
CapabilityInvoker:注册表查找 → 权限 → Handler:
public Map<String, Object> invoke(String capabilityId, Map<String, Object> args) {
CapabilityEntry entry = registry.findById(capabilityId)
.orElseThrow(() -> new IllegalArgumentException("unknown capability: " + capabilityId));
try {
permissionService.checkPermissions(entry.requiredPermissions());
} catch (RuntimeException e) {
auditLogger.capabilityDenied(
TenantContext.get() != null ? TenantContext.get() : -1L,
AgentPlatformSecuritySupport.currentUserIdOrUnknown(),
capabilityId,
e.getMessage());
throw e;
}
CapabilityHandler handler = handlers.get(capabilityId);
if (handler == null) {
throw new IllegalStateException("no handler for capability: " + capabilityId);
}
auditLogger.capabilityInvoked(
TenantContext.get() != null ? TenantContext.get() : -1L,
AgentPlatformSecuritySupport.currentUserIdOrUnknown(),
capabilityId);
return handler.invoke(args != null ? args : Map.of());
}
退出与结果:
- 确定性图将
supervisor_terminal设为FINISH_OK,并填充echo与追踪字段。 SupervisorRunApplicationService将成功快照封装为SupervisorRunResult;超时或异常映射为TIMEOUT/FINISH_ERROR。- SSE:
SupervisorStreamController异步调用AgentSupervisorStreamService.streamRun,在完成时发送supervisor_result与done事件(与 REST 同一套SupervisorRunApplicationService.run)。
SSE 侧复用同一 run:
memoryFacade.appendEvent(tenantId, sessionId, "SUPERVISOR_STREAM_START", Map.of("message", message));
try {
var result = supervisorRunApplicationService.run(sessionId, message);
send(emitter, Map.of(
"type", "supervisor_result",
"sessionId", sessionId,
"preset", session.preset(),
"terminal", result.terminal().name(),
"snapshot", result.stateSnapshot()));
send(emitter, Map.of("type", "done", "sessionId", sessionId, "preset", session.preset()));
memoryFacade.appendEvent(tenantId, sessionId, "SUPERVISOR_STREAM_DONE", Map.of("terminal", result.terminal().name()));
emitter.complete();

2.5 Memory 设计与实现
记忆分为 三条线,职责分离:
| 能力 | 接口 | 实现要点 |
|---|---|---|
| 会话与审计事件 | MemoryFacade |
MybatisMemoryFacade:agent_session 存会话与 checkpoint_thread_id;session_event 追加 SUPERVISOR_RUN_* 等事件;可选 Neo4jMemorySink.onSessionEvent 做图侧关联(默认可为 no-op) |
| 多轮对话持久化与 LLM 窗口 | ConversationMemoryFacade |
MybatisConversationMemoryFacade:表 agent_conversation_message;MessageWindowChatMemory 按 sessionId:agentId 缓存并 DB 预热;saveExchange 事务写入 USER/ASSISTANT 同一 turn_seq |
| Supervisor 成功后的摘要写回 | 应用层 | SupervisorRunApplicationService 在 FINISH_OK 后调用 conversationMemoryFacade.saveExchange(见 2.1 节) |
对话持久化(同一 turn_seq 双行插入):
@Transactional
@Override
public void saveExchange(long tenantId, String sessionId, String agentId,
String userText, String assistantText, String metadataJson) {
if (agentId == null || agentId.isBlank()) {
throw new IllegalArgumentException("agentId must not be blank");
}
int turnSeq = nextTurnSeq(tenantId, sessionId, agentId);
long now = System.currentTimeMillis();
AgentConversationMessagePO userRow = new AgentConversationMessagePO();
userRow.setTenantId(tenantId);
...
mapper.insert(assistantRow);
}
与 Spring AI 的衔接:ConversationMemoryFacade.getOrCreateWindow 返回 MessageWindowChatMemory,可直接配合 MessageChatMemoryAdvisor 等组件为后续 LLM 节点提供滑动窗口;当前工程重点是把 结构化会话存 MySQL 与 向 Supervisor 状态注入历史字符串 打通。
3. 小结
- Supervisor 在 Alibaba Graph 上同时支持 LlmRoutingAgent(多子 Agent + Tool) 与 StateGraph 确定性流水线,共享 CapabilityInvoker 与 上下文装配。
- Context 通过 SupervisorContextContributor 扩展 ontology、对话历史等,符合开闭原则。
- Agent 市场 以 代码目录 + 租户安装表 实现,并与 session preset 绑定。
- 执行与退出 由规划引擎、图终态与
SupervisorRunResult统一表达,SSE 与同步路径复用同一运行服务。 - Memory 将会话元数据、事件流、对话消息与可选 Neo4j 旁路分层,便于单独演进与测试。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)