基于 Spring AI 与 Spring AI Alibaba 的 Agent 设计与实现说明

本人就最近开发的Agent框架设计和实现交流,不喜勿喷!
平台级 Agent 能力整合中的设计思想、动机与价值:

  • 设计模板:本平台基于 DDD(领域驱动设计)分层理念,将高阶 AI Agent 编排需求拆分至 interfaces、application、domain、infrastructure 四层,各层解耦、接口清晰,便于插件式扩展与测试。依托 Spring AI 及 Alibaba Graph 能力,将 Agent 流程以 StateGraph 编排,统一状态持久化、能力调用、权限校验与上下文封装。每层有约束、各司其职,实现“能力即契约”、“状态即协议”。

  • 核心解决的问题

    1. 统一会话与能力管理:将对话记忆、状态信息、多轮推理等能力抽象为标准端口与状态键,支撑复杂 Agent 编排、多步 LLM 工作流与能力市场插件化。
    2. 可组合的 Agent 流程编排:基于 Spring AI Alibaba StateGraph,实现灵活、多节点、多策略的 Agent 运行路径,支持插拔式节点拓展与能力市场动态挂载。
    3. 多租户与权限体系:强制以 tenantId 作用域贯穿数据、能力注册、插件安装,保证隔离性与多租户安全,并结合 Sa-Token RBAC 做到 API 指令级、能力级精细化管控。
    4. 上下文融合与持续对话:通过会话消息、领域上下文、元模型、知识库等多维上下文的自动汇聚、窗口管理,增强 LLM 任务的连续性、准确性与可解释性。
    5. 基础设施与工程可落地性:严格规范数据库迁移、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 图运行时。

image.png

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 / DefaultExecutionPlanningEngineGraph 配置类在确定性路径中注入使用。

image.png

1.4 Supervisor 双路径(PlantUML)

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

image.png


2. Spring AI + Spring AI Alibaba 实现要点

2.1 Supervisor 设计与实现

配置类 PlatformSupervisorGraphConfiguration 集中定义三类 Bean:

  1. LLM SupervisorLlmRoutingAgentplatformLlmSupervisor),绑定 ChatModelCompileConfigMemorySaver + Store)、ModelCallLimitHook,并注册子 Agent 列表(当前示例为 platformEchoReactAgent)。
  2. 子 AgentReactAgentecho),通过 MethodToolCallbackProvider 注入 SupervisorCapabilityTools,将能力调用包装为 LLM 可调用的 Tool。
  3. 确定性图StateGraphplatformDeterministicSupervisorGraph)单节点 deterministic_pipeline:内部顺序执行 ExecutionPlanningEngine.plan → 逐步 CapabilityInvoker.invoke,并把 PIPELINE_TRACEEXECUTION_PLANecho 槽位与 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
  • 初始状态包含 inputtenantIdsessionIdsessionPreset 及上下文装配结果。
  • 在独立线程中调用 invoke,并 传播 TenantContextRequestContextHolder,避免异步丢失租户与请求上下文。
  • 使用 超时SupervisorProperties.invokeTimeoutMs)包装 Future.get,映射为 SupervisorTerminalStateFINISH_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_summaryontology_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 路由即可读取。

image.png


2.3 Agent 市场(插件市场)

工程中的「市场」分为两层:

  1. 目录(Catalog)PluginMarketCatalogConfiguration 以 Bean List<PluginMarketEntry> 形式 代码声明 可选插件(名称、描述、关联 preset、是否需安装等)。
  2. 租户安装态TenantPluginMarketService 读写表 tenant_plugin_install,提供 listInstalledPluginIdsinstallisInstalled

目录 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
  • SSESupervisorStreamController 异步调用 AgentSupervisorStreamService.streamRun,在完成时发送 supervisor_resultdone 事件(与 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();

image.png


2.5 Memory 设计与实现

记忆分为 三条线,职责分离:

能力 接口 实现要点
会话与审计事件 MemoryFacade MybatisMemoryFacadeagent_session 存会话与 checkpoint_thread_idsession_event 追加 SUPERVISOR_RUN_* 等事件;可选 Neo4jMemorySink.onSessionEvent 做图侧关联(默认可为 no-op)
多轮对话持久化与 LLM 窗口 ConversationMemoryFacade MybatisConversationMemoryFacade:表 agent_conversation_messageMessageWindowChatMemorysessionId:agentId 缓存并 DB 预热;saveExchange 事务写入 USER/ASSISTANT 同一 turn_seq
Supervisor 成功后的摘要写回 应用层 SupervisorRunApplicationServiceFINISH_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 旁路分层,便于单独演进与测试。
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐