### Complete Studio integration example (StudioExample.java) Source: https://java.agentscope.io/v1/zh/docs/task/observability Shows the full setup for connecting to AgentScope Studio, initializing it, creating a ReActAgent with a StudioMessageHook, creating a StudioUserAgent, and running a conversation loop. Requires DASHSCOPE_API_KEY environment variable and a running Studio instance at http://localhost:3000. The loop exits when the user types 'exit'. ```java package io.agentscope.examples; import io.agentscope.core.ReActAgent; import io.agentscope.core.message.Msg; import io.agentscope.extensions.model.dashscope.DashScopeChatModel; import io.agentscope.core.studio.StudioManager; import io.agentscope.core.studio.StudioMessageHook; import io.agentscope.core.studio.StudioUserAgent; public class StudioExample { public static void main(String[] args) throws Exception { String apiKey = System.getenv("DASHSCOPE_API_KEY"); System.out.println("Connecting to Studio at http://localhost:3000..."); // 初始化 Studio StudioManager.init() .studioUrl("http://localhost:3000") .project("JavaExamples") .runName("studio_demo_" + System.currentTimeMillis()) .initialize() .block(); System.out.println("Connected to Studio\n"); try { // 创建 Agent(带 Studio Hook) ReActAgent agent = ReActAgent.builder() .name("Assistant") .sysPrompt("You are a helpful AI assistant.") .model(DashScopeChatModel.builder() .apiKey(apiKey) .modelName("qwen3-max") .build()) .hook(new StudioMessageHook(StudioManager.getClient())) .build(); // 创建用户 Agent StudioUserAgent user = StudioUserAgent.builder() .name("User") .studioClient(StudioManager.getClient()) .webSocketClient(StudioManager.getWebSocketClient()) .build(); // 对话循环 System.out.println("Starting conversation (type 'exit' to quit)"); System.out.println("Open http://localhost:3000 to interact\n"); Msg msg = null; int turn = 1; while (true) { System.out.println("[Turn " + turn + "] Waiting for user input..."); msg = user.call(msg).block(); if (msg == null || "exit".equalsIgnoreCase(msg.getTextContent())) { System.out.println("\nConversation ended"); break; } System.out.println("[Turn " + turn + "] User: " + msg.getTextContent()); msg = agent.call(msg).block(); if (msg != null) { System.out.println("[Turn " + turn + "] Agent: " + msg.getTextContent() + "\n"); } turn++; } } finally { System.out.println("\nShutting down..."); StudioManager.shutdown(); System.out.println("Done\n"); } } } ``` -------------------------------- ### 运行 QuickstartExample 的 Shell 命令 Source: https://java.agentscope.io/v1/zh/docs/harness/overview 设置 DASHSCOPE_API_KEY 环境变量,首次运行需将依赖模块 install 到本地仓库(跳过 javadoc 与 spotless),然后执行 main 方法。 ```bash export DASHSCOPE_API_KEY=your_key_here # 首次运行需要把依赖模块 install 到本地仓库(跳过 javadoc 与 spotless) mvn -pl agentscope-examples/agents/harness-examples/harness-quickstart -am install \ -DskipTests -Dspotless.check.skip=true -Dmaven.javadoc.skip=true -q # 执行 main mvn -pl agentscope-examples/agents/harness-examples/harness-quickstart exec:java \ -Dexec.mainClass=io.agentscope.harness.example.QuickstartExample \ -Dspotless.check.skip=true -q ``` -------------------------------- ### 运行 HookExample 的 Maven 命令 Source: https://java.agentscope.io/v1/zh/docs/task/hook 在 quickstart 模块目录下运行 Maven exec 插件,以执行 HookExample 主类。 ```bash cd agentscope-examples/documentation/quickstart mvn exec:java -Dexec.mainClass="io.agentscope.examples.quickstart.HookExample" ``` -------------------------------- ### Basic DashScopeChatModel setup Source: https://java.agentscope.io/v1/zh/docs/task/model Creates a DashScopeChatModel with an API key from the DASHSCOPE_API_KEY environment variable and the qwen3-max model. ```java DashScopeChatModel model = DashScopeChatModel.builder() .apiKey(System.getenv("DASHSCOPE_API_KEY")) .modelName("qwen3-max") .build(); ``` -------------------------------- ### Quick Start: Create Bailian Knowledge Base and Retrieve Documents Source: https://java.agentscope.io/v1/zh/docs/task/rag Creates a BailianConfig with access keys from environment variables, builds a BailianKnowledge, and retrieves documents with a limit of 5 and a score threshold of 0.3. The retrieve call returns a reactive stream that is blocked to get the results. ```java // 创建知识库 BailianConfig config = BailianConfig.builder() .accessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")) .accessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")) .workspaceId("llm-xxx") .indexId("mymxbdxxxx") .build(); BailianKnowledge knowledge = BailianKnowledge.builder().config(config).build(); // 检索 List results = knowledge.retrieve("查询内容", RetrieveConfig.builder().limit(5).scoreThreshold(0.3).build()).block(); ``` -------------------------------- ### Complete BailianConfig Example with All Options Source: https://java.agentscope.io/v1/zh/docs/task/rag Shows a fully commented BailianConfig builder with required connection settings, optional endpoint, retrieval, reranking, query rewriting, and other settings. Includes default values and constraints such as denseSimilarityTopK + sparseSimilarityTopK <= 200. ```java BailianConfig config = BailianConfig.builder() // === 连接配置(必填)=== .accessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")) .accessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")) .workspaceId("llm-xxx") // 百炼工作空间 ID .indexId("mymxbdxxxx") // 知识库索引 ID // === 端点配置(可选)=== .endpoint("bailian.cn-beijing.aliyuncs.com") // 默认值 // 其他可用端点: // - bailian.cn-shanghai-finance-1.aliyuncs.com (金融云) // - bailian-vpc.cn-beijing.aliyuncs.com (VPC) // === 检索配置(可选)=== .denseSimilarityTopK(100) // 向量检索 Top K,范围 0-100,默认 100 .sparseSimilarityTopK(100) // 关键词检索 Top K,范围 0-100,默认 100 // 注意:denseSimilarityTopK + sparseSimilarityTopK <= 200 // === 重排序配置(可选)=== .enableReranking(true) // 启用重排序,默认 true .rerankConfig(RerankConfig.builder() .modelName("gte-rerank-hybrid") // 重排序模型 .rerankMinScore(0.3f) // 最小分数阈值 .rerankTopN(5) // 返回结果数量 .build()) // === 查询重写配置(可选,用于多轮对话)=== .enableRewrite(true) // 启用查询重写,默认 false .rewriteConfig(RewriteConfig.builder() .modelName("conv-rewrite-qwen-1.8b") // 重写模型 .build()) // === 其他配置(可选)=== .searchFilters(List.of(Map.of("tag", "value"))) // 搜索过滤条件 .saveRetrieverHistory(false) // 保存检索历史,默认 false .build(); ``` -------------------------------- ### Quick start: Register a sub-agent as a tool Source: https://java.agentscope.io/v1/zh/docs/task/agent-as-tool Creates a sub-agent provider using a lambda and registers it with a toolkit. The main agent can then call the sub-agent tool automatically. Requires a DashScope API key. ```java import io.agentscope.core.ReActAgent; import io.agentscope.core.tool.Toolkit; import io.agentscope.extensions.model.dashscope.DashScopeChatModel; // 创建模型 DashScopeChatModel model = DashScopeChatModel.builder() .apiKey(System.getenv("DASHSCOPE_API_KEY")) .modelName("qwen-plus") .build(); // 创建子智能体的 Provider(工厂) // 注意:必须使用 lambda 表达式,确保每次调用创建新实例 Toolkit toolkit = new Toolkit(); toolkit.registration() .subAgent(() -> ReActAgent.builder() .name("Expert") .sysPrompt("你是一个领域专家,负责回答专业问题。") .model(model) .build()) .apply(); // 创建主智能体,配置工具 ReActAgent mainAgent = ReActAgent.builder() .name("Coordinator") .sysPrompt("你是一个协调员。当遇到专业问题时,调用 call_expert 工具咨询专家。") .model(model) .toolkit(toolkit) .build(); // 主智能体会在需要时自动调用专家智能体 Msg response = mainAgent.call(userMsg).block(); ``` -------------------------------- ### 进阶方案 B:NAS 运行时 + OSS Snapshot 冷备的 AgentRunFilesystemSpec 配置 Source: https://java.agentscope.io/v1/zh/docs/harness/sandbox/agentrun 同时配置 NAS 和 OSS Snapshot,实现低延迟实时读写与版本化、跨集群可携带的 tar 归档。快照 bucket 必须与挂载 bucket 隔离(或至少 key prefix 错开),避免循环引用。stop() 时先执行 sync 让 NAS 落盘,再触发 tar 持久化;next start() 优先走 NAS,若 NAS 不可达则从 OSS Snapshot 恢复。 ```java AgentRunFilesystemSpec spec = new AgentRunFilesystemSpec() .setApiKey(...).setAccountId(...).setRegion("cn-hangzhou") .setTemplateName("agentscope-default") .setMcpServerUrl(...) .setNasConfig(nas) .setWorkspaceRoot("/mnt/nas/workspace") .snapshotSpec(new OssSnapshotSpec( // 与 NAS 不同的 bucket / key prefix ossClient, "agentscope-snapshots", "agentrun/workspaces/")); ``` -------------------------------- ### MsgHub.getParticipants() Source: https://java.agentscope.io/v1/zh/docs/task/msghub Gets the current participants. ```APIDOC ## MsgHub.getParticipants() ### Description Gets the current participants. ### Method getParticipants ### Return Type List ``` -------------------------------- ### MsgHub.getName() Source: https://java.agentscope.io/v1/zh/docs/task/msghub Gets the Hub name. ```APIDOC ## MsgHub.getName() ### Description Gets the Hub name. ### Method getName ### Return Type String ``` -------------------------------- ### Sandbox.start() 4-分支恢复逻辑 Source: https://java.agentscope.io/v1/zh/docs/harness/sandbox/index 展示 Sandbox.start() 根据 workspaceRootReady 和容器内目录是否存在、快照是否可用,决定如何初始化工作区的四种分支。Branch A 热启动最快,Branch D 冷启动。 ```text Branch A: workspaceRootReady=true & 容器内目录仍存在 → 只重新应用 ephemeral 条目(最快,热启动) Branch B: workspaceRootReady=true & 容器内目录已丢失 → 从快照还原 + 重新应用 ephemeral 条目 Branch C: workspaceRootReady=false & 快照可用 → 从快照还原 + 重新应用所有条目 Branch D: workspaceRootReady=false & 无可用快照 → 从 WorkspaceSpec 全量初始化(冷启动) ``` -------------------------------- ### Filter events by depth or path for nested agents Source: https://java.agentscope.io/v1/zh/docs/harness/streaming Use these filters to select events from specific levels or paths. The first filter gets only REASONING events from direct child agents (depth == 1). The second filter gets events whose path contains 'executor' at any depth. ```java // 仅取第一层子 agent 的 REASONING 事件 events.filter(e -> e.getSource() != null && e.getSource().getDepth() == 1 && e.getType() == EventType.REASONING) .subscribe(...); // 仅取路径包含 "executor" 的事件(任意深度) events.filter(e -> e.getSource() != null && e.getSource().getPath().contains("executor")) .subscribe(...); ``` -------------------------------- ### MsgHub.enter() Source: https://java.agentscope.io/v1/zh/docs/task/msghub Enters the Hub context and sets up subscriptions. ```APIDOC ## MsgHub.enter() ### Description Enters the Hub context and sets up subscriptions. ### Method enter ### Return Type Mono ### Response Example ```java hub.enter() .then(alice.call()) .block(); ``` ``` -------------------------------- ### Add agentscope-a2a-spring-boot-starter dependency Source: https://java.agentscope.io/v1/zh/docs/task/a2a Maven dependency for the Spring Boot starter. Required for the recommended Spring Boot setup. ```xml io.agentscope agentscope-a2a-spring-boot-starter ${agentscope.version} ``` -------------------------------- ### QuickstartExample 完整 Java 代码 Source: https://java.agentscope.io/v1/zh/docs/harness/overview 演示工作区驱动的人格、会话持久化和显式启用对话压缩。第一次运行生成 AGENTS.md,后续复用。使用 DashScopeChatModel 和 HarnessAgent,同一 sessionId 的第二轮对话能恢复第一轮状态。 ```java public class QuickstartExample { public static void main(String[] args) throws Exception { // 1. 准备工作区:第一次运行生成 AGENTS.md,后续运行复用 Path workspace = Paths.get(".agentscope/workspace"); initWorkspaceIfAbsent(workspace); // 2. 构建模型 Model model = DashScopeChatModel.builder() .apiKey(System.getenv("DASHSCOPE_API_KEY")) .modelName("qwen-max") .stream(true) .build(); // 3. 构建 HarnessAgent:工作区注入、会话持久化、追踪日志默认开启; // 这里显式启用对话压缩 HarnessAgent agent = HarnessAgent.builder() .name("quickstart-agent") .sysPrompt("你是一个帮助用户做笔记的助手。") .model(model) .workspace(workspace) .compaction(CompactionConfig.builder() .triggerMessages(30) .keepMessages(10) .flushBeforeCompact(true) // 压缩前把事实提取到日流水账 .build()) .build(); // 4. 同一个 RuntimeContext 发起两轮对话 // sessionId 相同 → 第二轮自动从 Session 恢复第一轮的状态 RuntimeContext ctx = RuntimeContext.builder() .sessionId("demo-session") .userId("alice") .build(); Msg turn1 = agent.call( Msg.builder().role(MsgRole.USER) .textContent("我叫天宇,今天准备一个关于 ReAct 的技术分享。") .build(), ctx).block(); System.out.println("[turn1] " + turn1.getTextContent()); Msg turn2 = agent.call( Msg.builder().role(MsgRole.USER) .textContent("我叫什么?我今天要干什么?") .build(), ctx).block(); System.out.println("[turn2] " + turn2.getTextContent()); } private static void initWorkspaceIfAbsent(Path workspace) throws Exception { Files.createDirectories(workspace); Path agentsMd = workspace.resolve("AGENTS.md"); if (Files.exists(agentsMd)) return; Files.writeString(agentsMd, """ # 笔记助手 你是一个帮助用户整理笔记和知识的助手。 ## 行为约定 - 主动记录用户提到的关键事实(姓名、计划、偏好等) - 回答用简洁中文,必要时给出要点列表 - 对不确定的内容要主动说明,不要臆造 """); } } ``` -------------------------------- ### NAS-first 最佳实践配置(AgentRunNasMountConfig + AgentRunFilesystemSpec + HarnessAgent) Source: https://java.agentscope.io/v1/zh/docs/harness/sandbox/agentrun 配置 NAS 挂载、文件系统规格并构建 HarnessAgent。工作区落在 NAS 内,无需 Snapshot。需设置环境变量 AGENTRUN_API_KEY、ALIYUN_ACCOUNT_ID、AGENTRUN_MCP_URL。 ```java import io.agentscope.harness.agent.sandbox.impl.agentrun.*; import io.agentscope.harness.agent.HarnessAgent; import io.agentscope.harness.agent.sandbox.IsolationScope; AgentRunNasMountConfig nas = new AgentRunNasMountConfig() .setServerAddr("12345abc-xxx.cn-hangzhou.nas.aliyuncs.com") .setMountDir("/mnt/nas") // 必须以 /home、/mnt 或 /data 开头 .setRemotePath("/") .setEnableTLS(false); AgentRunFilesystemSpec spec = new AgentRunFilesystemSpec() .setApiKey(System.getenv("AGENTRUN_API_KEY")) .setAccountId(System.getenv("ALIYUN_ACCOUNT_ID")) .setRegion("cn-hangzhou") .setTemplateName("agentscope-default") .setMcpServerUrl(System.getenv("AGENTRUN_MCP_URL")) // 必填,见 §8 .setNasConfig(nas) .setWorkspaceRoot("/mnt/nas/workspace") // ★ 工作区落在 NAS 内 .setSandboxIdleTimeoutSeconds(1800) .isolationScope(IsolationScope.SESSION); HarnessAgent agent = HarnessAgent.builder() .name("my-agent") .model(model) .filesystem(spec) .build(); ``` -------------------------------- ### 退路方案 A:无 NAS 纯 tar 快照的 AgentRunFilesystemSpec 配置 Source: https://java.agentscope.io/v1/zh/docs/harness/sandbox/agentrun 当未开通 NAS 或仅做 demo 时,省略 nasConfig/ossMountConfigs,工作区写到沙箱临时盘。必须显式挂 SnapshotSpec。代价是 stop() 时通过 MCP 远程执行 tar 并 base64 上传,大工作区耗时显著;start() 时分块 base64 写入临时文件再解压,链路较长。 ```java AgentRunFilesystemSpec spec = new AgentRunFilesystemSpec() .setApiKey(...) .setAccountId(...) .setRegion("cn-hangzhou") .setTemplateName("agentscope-default") .setMcpServerUrl(...) .setWorkspaceRoot("/home/agentscope/workspace") .snapshotSpec(new OssSnapshotSpec(...)); // ← 必须显式挂 SnapshotSpec ``` -------------------------------- ### Custom SandboxExecutionGuard Implementation Source: https://java.agentscope.io/v1/zh/docs/harness/sandbox SandboxExecutionGuard is a @FunctionalInterface, so any lock backend can be integrated. This example shows a JVM-memory-based Semaphore implementation for single-process multi-threaded scenarios. ```APIDOC ## Custom SandboxExecutionGuard Implementation ### Description Shows how to implement SandboxExecutionGuard with a custom lock backend. The example uses a ConcurrentHashMap of Semaphores to guard keys in a single JVM. ### Implementation Contract 1. `tryEnter` must block until execution right is obtained or the thread is interrupted (throw InterruptedException). 2. `lease.close()` must be idempotent and must not throw exceptions (failures should only be logged internally). 3. The implementation must be thread-safe. ### Example ```java Map semaphores = new ConcurrentHashMap<>(); SandboxExecutionGuard jvmGuard = key -> { Semaphore sem = semaphores.computeIfAbsent(key.toString(), k -> new Semaphore(1)); sem.acquire(); // blocks until available, responds to InterruptedException return sem::release; // SandboxLease: releases the semaphore }; ``` ``` -------------------------------- ### Multi-turn dialogue with session_id Source: https://java.agentscope.io/v1/zh/docs/task/agent-as-tool Shows the expected tool return format for multi-turn conversations. The first call starts a new session, subsequent calls continue it. ```text // 第一次调用:不传 session_id,开始新会话 // 工具返回格式: // session_id: abc-123-def // // 专家回复内容... // 后续调用:传入 session_id,继续之前的对话 // 父智能体会自动从上次返回中提取 session_id 并传入 ``` -------------------------------- ### MsgHub.builder() Source: https://java.agentscope.io/v1/zh/docs/task/msghub Builder methods for configuring a MsgHub instance. ```APIDOC ## MsgHub.builder() ### Description Builder methods for configuring a MsgHub instance. ### Method Builder ### Parameters - **name(String)** - Optional - Sets the Hub name. Default: UUID - **participants(AgentBase...)** - Required - Sets participants. - **participants(List)** - Required - Sets participants from a list. - **announcement(Msg...)** - Optional - Sets announcement messages. Default: none - **announcement(List)** - Optional - Sets announcement messages from a list. - **enableAutoBroadcast(boolean)** - Optional - Enables/disables auto broadcast. Default: true ### Request Example ```java MsgHub hub = MsgHub.builder() .participants(alice, bob, charlie) .announcement(announcement) .build(); ``` ### Response Returns a MsgHub instance. ``` -------------------------------- ### Simplified SkillBox Integration with ReActAgent Source: https://java.agentscope.io/v1/zh/docs/task/agent-skill Registers a skill with SkillBox and builds a ReActAgent with the skill box. Use this basic setup when you have a single skill and no need for advanced tool binding. ```java SkillBox skillBox = new SkillBox(new Toolkit()); skillBox.registerSkill(dataSkill); ReActAgent agent = ReActAgent.builder() .name("Assistant") .model(model) .skillBox(skillBox) .build(); ``` -------------------------------- ### 通过 npm 安装并启动 Studio Source: https://java.agentscope.io/v1/zh/docs/task/observability 使用 npm 全局安装 @agentscope/studio 包,然后运行 as_studio 命令启动 Studio。 ```bash npm install -g @agentscope/studio # or npm install @agentscope/studio as_studio ``` -------------------------------- ### Custom SandboxExecutionGuard using JVM Semaphore Source: https://java.agentscope.io/v1/zh/docs/harness/sandbox/index Example of a custom SandboxExecutionGuard implementation using a ConcurrentHashMap of Semaphores for single-process multi-thread scenarios. tryEnter blocks until a permit is available and returns a SandboxLease that releases the semaphore. ```java // 示例:基于 JVM 内存的 Semaphore(单进程多线程场景) Map semaphores = new ConcurrentHashMap<>(); SandboxExecutionGuard jvmGuard = key -> { Semaphore sem = semaphores.computeIfAbsent(key.toString(), k -> new Semaphore(1)); sem.acquire(); // 阻塞直到可用,响应 InterruptedException return sem::release; // SandboxLease:释放信号量 }; ``` -------------------------------- ### 运行 MCP 工具示例 Source: https://java.agentscope.io/v1/zh/docs/task/mcp 使用 Maven 运行 McpToolExample 主类,需要先进入示例项目目录。 ```bash cd agentscope-examples/documentation/quickstart mvn exec:java -Dexec.mainClass="io.agentscope.examples.quickstart.McpToolExample" ``` -------------------------------- ### 运行 Mem0 示例 Source: https://java.agentscope.io/v1/zh/docs/task/memory 运行 Mem0Example 的命令,包含 Platform 和自建 Mem0 两种配置的环境变量设置。 ```bash # Platform Mem0(默认) export MEM0_API_KEY=your_api_key export MEM0_API_BASE_URL=https://api.mem0.ai # 可选,默认为此值 cd agentscope-examples/documentation/advanced mvn exec:java -Dexec.mainClass="io.agentscope.examples.advanced.Mem0Example" # 自建 Mem0 export MEM0_API_KEY=your_api_key # 可选,取决于服务配置 export MEM0_API_BASE_URL=http://localhost:8000 export MEM0_API_TYPE=self-hosted cd agentscope-examples/documentation/advanced mvn exec:java -Dexec.mainClass="io.agentscope.examples.advanced.Mem0Example" ``` -------------------------------- ### Routing action example after sales agent Source: https://java.agentscope.io/v1/zh/docs/multi-agent/handoffs Implements the apply method for a routing action that reads active_agent from the state. Returns the support agent if active_agent equals SUPPORT_AGENT, otherwise returns "__end__". ```java @Override public CompletableFuture apply(OverAllState state, RunnableConfig config) { String active = state.value(AgentScopeStateConstants.ACTIVE_AGENT) .map(Object::toString) .orElse(""); String target = AgentScopeStateConstants.SUPPORT_AGENT.equals(active) ? AgentScopeStateConstants.SUPPORT_AGENT : "__end__"; return CompletableFuture.completedFuture(new Command(target)); } ``` -------------------------------- ### 从源码启动 Studio Server Source: https://java.agentscope.io/v1/zh/docs/task/observability 通过克隆 agentscope-studio 仓库并运行 npm 命令启动 Studio 前端开发服务器。 ```bash git clone https://github.com/agentscope-ai/agentscope-studio cd agentscope-studio npm install npm run dev ``` -------------------------------- ### Configure timeout and retry with ExecutionConfig Source: https://java.agentscope.io/v1/zh/docs/task/model Builds an ExecutionConfig with a 2-minute timeout, 3 max attempts, and exponential backoff starting at 1 second, doubling up to 10 seconds. Pass it to GenerateOptions to apply to model generation. ```java ExecutionConfig execConfig = ExecutionConfig.builder() .timeout(Duration.ofMinutes(2)) .maxAttempts(3) .initialBackoff(Duration.ofSeconds(1)) .maxBackoff(Duration.ofSeconds(10)) .backoffMultiplier(2.0) .build(); GenerateOptions options = GenerateOptions.builder() .executionConfig(execConfig) .build(); ``` -------------------------------- ### SandboxExecutionGuard lifecycle sequence Source: https://java.agentscope.io/v1/zh/docs/harness/sandbox/index Shows the lifecycle of a sandbox call with the guard: tryEnter blocks until the previous call completes, then acquire/resume, start, agent call, persistState, stop/shutdown, and finally lease.close() releases execution right. ```text tryEnter(key) ← 可能在此阻塞,直到上一个 call 完成 └─ acquire / resume sandbox └─ sandbox.start() └─ [agent call 执行中] └─ persistState() └─ sandbox.stop() + shutdown() lease.close() ← 释放执行权,下一个等待方可进入 ``` -------------------------------- ### Create synchronous and asynchronous MCP clients Source: https://java.agentscope.io/v1/zh/docs/task/mcp Shows how to create both asynchronous (recommended) and synchronous clients. The async client uses buildAsync().block(), while the sync client uses buildSync() for blocking operations. ```java // 异步客户端(推荐) McpClientWrapper asyncClient = McpClientBuilder.create("async-mcp") .stdioTransport("npx", "-y", "@modelcontextprotocol/server-filesystem", "/tmp") .buildAsync() .block(); // 同步客户端(用于阻塞操作) McpClientWrapper syncClient = McpClientBuilder.create("sync-mcp") .stdioTransport("npx", "-y", "@modelcontextprotocol/server-filesystem", "/tmp") .buildSync(); ``` -------------------------------- ### Invoke the compiled graph with user input Source: https://java.agentscope.io/v1/zh/docs/multi-agent/handoffs Calls compiledGraph.invoke with a user input map and prints the text of each message from the resulting state. The graph starts with the initial agent and routes based on handoff tool calls. ```java Map inputs = Map.of("input", "你好,我登录账户遇到问题,能帮忙吗?"); Optional resultOpt = compiledGraph.invoke(inputs); resultOpt.ifPresent(state -> { List messages = (List) state.value("messages").orElse(List.of()); messages.forEach(msg -> System.out.println(msg.getText())); }); ``` -------------------------------- ### Manually create A2A server with AgentScopeA2aServer Source: https://java.agentscope.io/v1/zh/docs/task/a2a Builds an A2A server manually, configures deployment properties (host, port), retrieves a JSON-RPC transport wrapper for web frameworks, and signals readiness after the web service starts. ```java import io.agentscope.core.a2a.server.AgentScopeA2aServer; import io.agentscope.core.a2a.server.transport.DeploymentProperties; // 创建 A2A Server AgentScopeA2aServer server = AgentScopeA2aServer.builder( ReActAgent.builder() .name("my-assistant") .sysPrompt("你是一个有用的助手")) .deploymentProperties(DeploymentProperties.builder() .host("localhost") .port(8080) .build()) .build(); // 获取传输处理器用于 Web 框架 JsonRpcTransportWrapper transport = server.getTransportWrapper("JSON-RPC", JsonRpcTransportWrapper.class); // Web 服务就绪后调用 server.postEndpointReady(); ``` -------------------------------- ### 添加参与者:使用 MsgHub.add() 动态添加参与者 Source: https://java.agentscope.io/v1/zh/docs/task/msghub 在对话过程中使用 hub.add(charlie) 添加新参与者。新添加的参与者不会收到之前的消息,只会收到加入后的消息。 ```java try (MsgHub hub = MsgHub.builder() .participants(alice, bob) .build()) { hub.enter().block(); // Alice 和 Bob 对话 alice.call().block(); bob.call().block(); // 对话中途添加 Charlie hub.add(charlie).block(); // 现在 Charlie 也会收到消息 alice.call().block(); // Charlie 会收到 charlie.call().block(); // Alice 和 Bob 会收到 } ``` -------------------------------- ### 启用计划功能:使用默认配置 (enablePlan) Source: https://java.agentscope.io/v1/zh/docs/task/plan 通过 ReActAgent.builder() 的 enablePlan() 方法启用计划功能,使用默认配置。这是推荐的方式。 ```java ReActAgent agent = ReActAgent.builder() .name("Assistant") .model(model) .toolkit(toolkit) .enablePlan() // 启用计划功能 .build(); ``` -------------------------------- ### Add nodes and conditional edges to the graph Source: https://java.agentscope.io/v1/zh/docs/multi-agent/handoffs Adds sales and support agents as nodes, then configures conditional edges from START and after each agent based on the active_agent state. Defaults to sales_agent when active_agent is unset. Uses RouteInitialAction, RouteAfterSalesAction, and RouteAfterSupportAction. ```java graph.addNode(AgentScopeStateConstants.SALES_AGENT, salesAgent.asNode()); graph.addNode(AgentScopeStateConstants.SUPPORT_AGENT, supportAgent.asNode()); // START → sales_agent 或 support_agent(默认 sales) graph.addConditionalEdges(START, new RouteInitialAction(), Map.of( AgentScopeStateConstants.SALES_AGENT, AgentScopeStateConstants.SALES_AGENT, AgentScopeStateConstants.SUPPORT_AGENT, AgentScopeStateConstants.SUPPORT_AGENT)); // sales_agent → support_agent 或 END graph.addConditionalEdges(AgentScopeStateConstants.SALES_AGENT, new RouteAfterSalesAction(), Map.of(AgentScopeStateConstants.SUPPORT_AGENT, AgentScopeStateConstants.SUPPORT_AGENT, "__end__", END)); // support_agent → sales_agent 或 END graph.addConditionalEdges(AgentScopeStateConstants.SUPPORT_AGENT, new RouteAfterSupportAction(), Map.of(AgentScopeStateConstants.SALES_AGENT, AgentScopeStateConstants.SALES_AGENT, "__end__", END)); CompiledGraph compiledGraph = graph.compile(); ``` -------------------------------- ### Configure HarnessAgent and Search Memory with MemoryIndex Source: https://java.agentscope.io/v1/zh/docs/harness/memory Build a HarnessAgent with compaction settings (trigger after 30 messages, keep 10) and tool result eviction defaults. Then open a MemoryIndex on the workspace agent scope directory and search for '数据库迁移' returning up to 10 hits, each with path, lineNumber, content, and rank. ```java HarnessAgent agent = HarnessAgent.builder() .name("MyAgent") .model(model) .workspace(workspace) .compaction(CompactionConfig.builder() .triggerMessages(30) .keepMessages(10) .build()) .toolResultEviction(ToolResultEvictionConfig.defaults()) .build(); // agent 可随时调用 memory_search MemoryIndex index = new MemoryIndex(workspaceAgentScopeDir); index.open(); List hits = index.search("数据库迁移", 10); // hit: { path, lineNumber, content, rank } ``` -------------------------------- ### Query AgentRun Sandbox Status via REST API Source: https://java.agentscope.io/v1/zh/docs/harness/sandbox/agentrun Use this GET request to observe sandbox status externally. The response 'status' field contains values like READY, RUNNING, or FAILED. Replace placeholders with your account ID, region, and sandbox ID. ```http GET https://{accountId}.agentrun-data.{region}.aliyuncs.com/2025-09-10/sandboxes/{sandboxId} X-API-Key: ... X-Acs-Parent-Id: {accountId} ```