mcpField
A
agentscope-java

agentscope-java

github.com/agentscope-aiAgent 工作流6.2k101 次安装今天更新
代码仓库

关于 agentscope-java

agentscope-java 是基于 Project Reactor、面向 Java 17+ 的响应式多 Agent 框架。此技能指导编码 Agent 正确使用其 API,涵盖非阻塞代码、项目配置与常见用法。

主要功能

  1. 01基于 Reactor 的异步 Agent 操作
  2. 02消息驱动的 Agent 通信
  3. 03可组合的串行与并行流水线
  4. 04Toolkit 工具与生命周期钩子
  5. 05Java 17 配置与 API 指引

适用场景

  1. 01编写非阻塞的 AgentScope Java 逻辑
  2. 02配置模型与 Maven 依赖
  3. 03创建工具、钩子和 Agent 流水线

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/agentscope-ai/agentscope-java --skill agentscope-java

安装后在 Claude Code 中输入/agentscope-java确认已加载。

详细介绍

当用户要求你编写 AgentScope Java 代码时,请严格遵循以下说明。

关键规则——绝不可违反

🚫 绝对禁止:

  1. 绝不要在示例代码中使用 .block()——这是最常见的错误。只有在 main() 方法或测试代码中明确创建可运行示例时,才可以使用 .block()。
  2. 绝不要使用 Thread.sleep()——请改用 Mono.delay()。
  3. 绝不要使用 ThreadLocal——请使用 Reactor Context 和 Mono.deferContextual()。
  4. 绝不要硬编码 API 密钥——始终使用 System.getenv()。
  5. 绝不要默默忽略错误——始终记录错误并提供回退值。
  6. 绝不要使用错误的导入路径——共享模型接口位于 io.agentscope.core.model.*;提供商模型位于 io.agentscope.extensions.model.<provider>.*。

✅ 始终遵循:

  1. 对所有异步操作使用 Mono 和 Flux。
  2. 使用 .map()、.flatMap()、.then() 链接操作。
  3. 使用 Builder 模式创建 Agent、模型和消息。
  4. 使用 .onErrorResume() 或 .onErrorReturn() 处理错误。
  5. 使用 SLF4J 为重要操作添加日志。
  6. 使用正确的导入:import io.agentscope.extensions.model.dashscope.DashScopeChatModel;
  7. 使用正确的 API(许多方法并不存在或已更改):
    • 使用 toolkit.registerTool(),而不是 registerObject()
    • 使用 toolkit.getToolNames(),而不是 getTools()
    • 使用 event.getToolUse().getName(),而不是 getToolName()
    • 使用 result.getOutput(),而不是 getContent()(ToolResultBlock)
    • 使用 event.getToolResult(),而不是 getResult()(PostActingEvent)
    • 使用 toolUse.getInput(),而不是 getArguments()(ToolUseBlock)
    • 模型 Builder:没有 temperature() 方法,请使用 defaultOptions(GenerateOptions.builder()...)
    • Hook 事件:没有 getMessages()、getResponse()、getIterationCount()、getThinkingBlock() 方法
    • ToolResultBlock:没有 getToolUseName() 方法,请改用 event.getToolUse().getName()
    • ToolResultBlock.getOutput() 返回 List<ContentBlock>,而不是 String,需要进行转换
    • @ToolParam 格式:必须使用 @ToolParam(name = "x", description = "y"),而不是 @ToolParam(name="x")

生成代码时

首先:确定上下文

  • 这是 main() 方法或测试代码吗?→ 可以使用 .block()(但请添加警告注释)
  • 这是 Agent 逻辑、服务方法或库代码吗?→ 禁止使用 .block()

对于你提供的每个代码示例:

  1. 检查:是否使用了 .block()?→ 如果在非 main、非测试代码中使用了,请重写。
  2. 检查:所有操作是否都为非阻塞?→ 如果不是,请修正。
  3. 检查:是否处理了错误?→ 如果没有,请添加。
  4. 检查:API 密钥是否来自环境变量?→ 如果不是,请修改。
  5. 检查:导入是否正确?→ 如果从 io.agentscope.core.model.* 导入提供商模型,请改为 io.agentscope.extensions.model.<provider>.*。

Agent 逻辑的默认代码结构:

// ✅ CORRECT - Non-blocking, reactive (use this pattern by default)
return model.generate(messages, null, null)
    .map(response -> processResponse(response))
    .onErrorResume(e -> {
        log.error("Operation failed", e);
        return Mono.just(fallbackValue);
    });

// ❌ WRONG - Never generate this in agent logic
String result = model.generate(messages, null, null).block(); // DON'T DO THIS

仅用于 main() 方法(添加警告注释):

public static void main(String[] args) {
    // ⚠️ .block() is ONLY allowed here because this is a main() method
    Msg response = agent.call(userMsg).block();
    System.out.println(response.getTextContent());
}

项目设置

创建新的 AgentScope 项目时,请使用正确的 Maven 依赖:

Maven 配置(pom.xml)

用于生产环境(推荐):

<properties>
    <java.version>17</java.version>
</properties>

<dependencies>
    
    <dependency>
        <groupId>io.agentscope</groupId>
        <artifactId>agentscope</artifactId>
        <version>1.0.12</version>
    </dependency>
</dependencies>

用于本地开发(如果正在处理源代码):

<properties>
    <agentscope.version>1.0.12</agentscope.version>
    <java.version>17</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>io.agentscope</groupId>
        <artifactId>agentscope-core</artifactId>
        <version>${agentscope.version}</version>
    </dependency>
    <dependency>
        <groupId>io.agentscope</groupId>
        <artifactId>agentscope-extensions-model-dashscope</artifactId>
        <version>${agentscope.version}</version>
    </dependency>
</dependencies>

⚠️ 重要:版本选择

  • 生产环境使用 agentscope:1.0.12(稳定版,来自 Maven Central)
  • 仅在开发 AgentScope 本身时使用 agentscope-core:1.0.12
  • 绝不要使用版本 0.1.0-SNAPSHOT——该版本不存在
⚠️ 关键:常见依赖错误

❌ 错误——这些构件不存在:


<dependency>
    <groupId>io.agentscope</groupId>
    <artifactId>agentscope-model-dashscope</artifactId>  
</dependency>
<dependency>
    <groupId>io.agentscope</groupId>
    <artifactId>agentscope-model-openai</artifactId>  
</dependency>

❌ 错误——这些版本不存在:

<dependency>
    <groupId>io.agentscope</groupId>
    <artifactId>agentscope-core</artifactId>
    <version>0.1.0-SNAPSHOT</version>  
</dependency>
<dependency>
    <groupId>io.agentscope</groupId>
    <artifactId>agentscope</artifactId>
    <version>0.1.0</version>  
</dependency>

✅ 正确——使用稳定版本:


<dependency>
    <groupId>io.agentscope</groupId>
    <artifactId>agentscope</artifactId>
    <version>1.0.12</version>  
</dependency>
可用模型类(特定提供商的扩展模块)
// DashScope (Alibaba Cloud)
import io.agentscope.extensions.model.dashscope.DashScopeChatModel;

// OpenAI
import io.agentscope.extensions.model.openai.OpenAIChatModel;

// Gemini (Google)
import io.agentscope.extensions.model.gemini.GeminiChatModel;

// Anthropic (Claude)
import io.agentscope.extensions.model.anthropic.AnthropicChatModel;

// Ollama (Local models)
import io.agentscope.extensions.model.ollama.OllamaChatModel;
可选扩展

<dependency>
    <groupId>io.agentscope</groupId>
    <artifactId>agentscope-extensions-mem0</artifactId>
    <version>${agentscope.version}</version>
</dependency>


<dependency>
    <groupId>io.agentscope</groupId>
    <artifactId>agentscope-extensions-rag-dify</artifactId>
    <version>${agentscope.version}</version>
</dependency>

项目概述与架构

AgentScope Java 是一个基于 Project Reactor 和 Java 17+ 构建的响应式、消息驱动型多 Agent 框架。

核心抽象
  • Agent:执行的基本单元。大多数 Agent 都扩展 AgentBase。
  • Msg:Agent 之间交换的消息对象。
  • Memory:存储对话历史(InMemoryMemory、LongTermMemory)。
  • Toolkit & AgentTool:定义 Agent 可使用的能力。
  • Model:与大模型(OpenAI、DashScope、Gemini、Anthropic 等)交互。
  • Hook:在生命周期的不同阶段拦截并修改 Agent 执行过程。
  • Pipeline:以串行或并行模式编排多个 Agent。
响应式特性

几乎所有操作(Agent 调用、模型推理、工具执行)都返回 Mono<T> 或 Flux<T>。

核心设计原则
  1. 非阻塞:所有 I/O 操作均为异步
  2. 消息驱动:Agent 通过不可变的 Msg 对象通信
  3. 可组合:Agent 和 Pipeline 可以嵌套和组合
  4. 可扩展:Hook 和自定义工具支持深度定制

编码规范与最佳实践

2.1 Java 版本与风格

目标版本为 Java 17(LTS),以获得最大的兼容性:

  • 使用 Java 17 特性(Record、Switch 表达式、instanceof 模式匹配、var、Sealed 类)
  • 避免使用 Java 21+ 预览特性(switch 中的模式匹配、Record 模式)
  • 遵循标准 Java 约定(类名使用 PascalCase,方法和变量名使用 camelCase)
  • 适当使用 Lombok(用于 DTO/Message 的 @Data、@Builder)
  • 数据类优先采用不可变设计
  • 使用能体现领域概念的有意义的名称

⚠️ 关键:避免使用预览特性

// ❌ WRONG - Requires Java 21 with --enable-preview
return switch (event) {
    case PreReasoningEvent e -> Mono.just(e);  // Pattern matching in switch
    default -> Mono.just(event);
};

// ✅ CORRECT - Java 17 compatible
if (event instanceof PreReasoningEvent e) {  // Pattern matching for instanceof (Java 17)
    return Mono.just(event);
} else {
    return Mono.just(event);
}
2.2 响应式编程(关键)

⚠️ 切勿在 Agent 逻辑中阻塞

阻塞操作会中断响应式链并导致性能问题。

规则:

  • ❌ 切勿使用 .block() 执行 Agent 逻辑(仅可用于 main 方法或测试)
  • ✅ 单个结果使用 Mono(例如 agent.call())
  • ✅ 流式响应使用 Flux(例如 model.stream())
  • ✅ 使用 .map()、.flatMap()、.then() 链接操作
  • ✅ 使用 Mono.defer() 进行延迟求值
  • ✅ 使用 Mono.deferContextual() 访问响应式上下文

示例:

// ❌ WRONG - Blocking
public Mono<String> processData(String input) {
    String result = externalService.call(input).block(); // DON'T DO THIS
    return Mono.just(result);
}

// ✅ CORRECT - Non-blocking
public Mono<String> processData(String input) {
    return externalService.call(input)
        .map(this::transform)
        .flatMap(this::validate);
}
2.3 消息处理(Msg)

使用 Builder 模式创建消息:

Msg userMsg = Msg.builder()
    .role(MsgRole.USER)
    .content(TextBlock.builder().text("Hello").build())
    .name("user")
    .build();

内容块:

  • TextBlock:用于文本内容
  • ThinkingBlock:用于思维链(CoT)推理
  • ToolUseBlock:用于工具调用
  • ToolResultBlock:用于工具输出

辅助方法:

// Prefer safe helper methods
String text = msg.getTextContent();  // Safe, returns null if not found

// Avoid direct access
String text = msg.getContent().get(0).getText();  // May throw NPE
2.4 实现 Agent

扩展 AgentBase 并实现 doCall(List<Msg> msgs):

public class MyAgent extends AgentBase {
    private final Model model;
    private final Memory memory;

    public MyAgent(String name, Model model) {
        super(name, "A custom agent", true, List.of());
        this.model = model;
        this.memory = new InMemoryMemory();
    }

    @Override
    protected Mono<Msg> doCall(List<Msg> msgs) {
        // 1. Process inputs
        if (msgs != null) {
            msgs.forEach(memory::addMessage);
        }

        // 2. Call model or logic
        return model.generate(memory.getMessages(), null, null)
            .map(response -> Msg.builder()
                .name(getName())
                .role(MsgRole.ASSISTANT)
                .content(TextBlock.builder().text(response.getText()).build())
                .build());
    }
}
2.5 工具定义

使用 @Tool 注解定义基于函数的工具。工具可以返回:

  • String(同步)
  • Mono<String>(异步)
  • Mono<ToolResultBlock>(用于复杂结果)

⚠️ 关键:@ToolParam 格式

  • ✅ 正确:@ToolParam(name = "city", description = "City name")
  • ❌ 错误:@ToolParam(name="city", description="...")(= 两侧没有空格)
  • ❌ 错误:@ToolParam("city")(缺少 name= 和 description=)

同步工具示例:

public class WeatherTools {
    @Tool(description = "Get current weather for a city. Returns temperature and conditions.")
    public String getWeather(
            @ToolParam(name = "city", description = "City name, e.g., 'San Francisco'")
            String city) {
        // Implementation
        return "Sunny, 25°C";
    }
}

异步工具示例:

public class AsyncTools {
    private final WebClient webClient;

    @Tool(description = "Fetch data from trusted API endpoint")
    public Mono<String> fetchData(
            @ToolParam(name = "url", description = "API endpoint URL (must start with https://api.myservice.com)")
            String url) {
        // SECURITY: Validate URL to prevent SSRF
        if (!url.startsWith("https://api.myservice.com")) {
            return Mono.just("Error: URL not allowed. Must start with https://api.myservice.com");
        }

        return webClient.get()
            .uri(url)
            .retrieve()
            .bodyToMono(String.class)
            .timeout(Duration.ofSeconds(10))
            .onErrorResume(e -> Mono.just("Error: " + e.getMessage()));
    }
}

注册到 Toolkit:

Toolkit toolkit = new Toolkit();
toolkit.registerTool(new WeatherTools());
toolkit.registerTool(new AsyncTools());

Hook 系统

Hook 可在生命周期的不同阶段拦截并修改 Agent 执行过程。

Hook 接口
public interface Hook {
    <T extends HookEvent> Mono<T> onEvent(T event);
    default int priority() { return 100; }  // Lower = higher priority
}
常见 Hook 事件
  • PreReasoningEvent:LLM 推理之前(可修改)
  • PostReasoningEvent:LLM 推理之后(可修改)
  • ReasoningChunkEvent:流式推理分块(通知)
  • PreActingEvent:工具执行之前(可修改)
  • PostActingEvent:工具执行之后(可修改)
  • ActingChunkEvent:流式工具执行(通知)
Hook 示例

兼容 Java 17+(推荐):

Hook loggingHook = new Hook() {
    @Override
    public <T extends HookEvent> Mono<T> onEvent(T event) {
        // Use if-instanceof instead of switch patterns (Java 17 compatible)
        if (event instanceof PreReasoningEvent e) {
            log.info("Reasoning with model: {}", e.getModelName());
            return Mono.just(event);
        } else if (event instanceof PreActingEvent e) {
            log.info("Calling tool: {}", e.getToolUse().getName());
            return Mono.just(event);
        } else if (event instanceof PostActingEvent e) {
            log.info("Tool {} completed", e.getToolUse().getName());
            return Mono.just(event);
        } else {
            return Mono.just(event);
        }
    }

    @Override
    public int priority() {
        return 500;  // Low priority (logging)
    }
};

ReActAgent agent = ReActAgent.builder()
    .name("Assistant")
    .model(model)
    .hook(loggingHook)
    .build();

替代方案:传统 if-else(Java 17):

Hook loggingHook = new Hook() {
    @Override
    public <T extends HookEvent> Mono<T> onEvent(T event) {
        if (event instanceof PreReasoningEvent) {
            PreReasoningEvent e = (PreReasoningEvent) event;
            log.info("Reasoning with model: {}", e.getModelName());
        } else if (event instanceof PreActingEvent) {
            PreActingEvent e = (PreActingEvent) event;
            log.info("Calling tool: {}", e.getToolUse().getName());
        } else if (event instanceof PostActingEvent) {
            PostActingEvent e = (PostActingEvent) event;
            log.info("Tool {} completed", e.getToolUse().getName());
        }
        return Mono.just(event);
    }

    @Override
    public int priority() {
        return 500;
    }
};

优先级指南:

  • 0-50:关键系统 Hook(身份验证、安全)
  • 51-100:高优先级 Hook(验证、预处理)
  • 101-500:普通优先级 Hook(业务逻辑)
  • 501-1000:低优先级 Hook(日志、指标)

PIPELINE 模式

Pipeline 用于在结构化工作流中编排多个 Agent。

顺序 Pipeline

按顺序执行 Agent(一个 Agent 的输出成为下一个 Agent 的输入):

SequentialPipeline pipeline = SequentialPipeline.builder()
    .addAgent(researchAgent)
    .addAgent(summaryAgent)
    .addAgent(reviewAgent)
    .build();

Msg result = pipeline.execute(userInput).block();
扇出 Pipeline

并行执行 Agent 并汇总结果:

FanoutPipeline pipeline = FanoutPipeline.builder()
    .addAgent(agent1)
    .addAgent(agent2)
    .addAgent(agent3)
    .build();

Msg result = pipeline.execute(userInput).block();

适用场景:

  • 顺序:每个 Agent 都依赖前一个 Agent 的输出时
  • 扇出:Agent 可以独立工作且需要汇总结果时

内存管理

内存中(短期)
Memory memory = new InMemoryMemory();
长期记忆
// Configure long-term memory
LongTermMemory longTermMemory = Mem0LongTermMemory.builder()
    .apiKey(System.getenv("MEM0_API_KEY"))
    .userId("user_123")
    .build();

// Use with agent
ReActAgent agent = ReActAgent.builder()
    .name("Assistant")
    .model(model)
    .longTermMemory(longTermMemory)
    .longTermMemoryMode(LongTermMemoryMode.BOTH)  // STATIC_CONTROL, AGENTIC, or BOTH
    .build();

内存模式:

  • STATIC_CONTROL:框架自动管理内存(通过 Hook)
  • AGENTIC:Agent 决定何时使用内存(通过工具)
  • BOTH:结合两种方式

MCP(模型上下文协议)集成

AgentScope 支持 MCP,可用于集成外部工具和资源。

// Create MCP client
// SECURITY: In production, use a specific version or a local binary to prevent supply chain attacks
McpClientWrapper mcpClient = McpClientBuilder.stdio()
    .command("npx")
    .args("-y", "@modelcontextprotocol/[email protected]", "/path/to/files") // Always pin versions
    .build();

// Register with toolkit
Toolkit toolkit = new Toolkit();
toolkit.registration()
    .mcpClient(mcpClient)
    .enableTools(List.of("read_file", "write_file"))
    .apply();

// Use with agent
ReActAgent agent = ReActAgent.builder()
    .name("Assistant")
    .model(model)
    .toolkit(toolkit)
    .build();

测试

使用 StepVerifier 进行单元测试
@Test
void testAgentCall() {
    Msg input = Msg.builder()
        .role(MsgRole.USER)
        .content(TextBlock.builder().text("Hello").build())
        .build();

    StepVerifier.create(agent.call(input))
        .assertNext(response -> {
            assertEquals(MsgRole.ASSISTANT, response.getRole());
            assertNotNull(response.getTextContent());
        })
        .verifyComplete();
}
模拟外部依赖
@Test
void testWithMockModel() {
    Model mockModel = mock(Model.class);
    when(mockModel.generate(any(), any(), any()))
        .thenReturn(Mono.just(ChatResponse.builder()
            .text("Mocked response")
            .build()));

    ReActAgent agent = ReActAgent.builder()
        .name("TestAgent")
        .model(mockModel)
        .build();

    // Test agent behavior
}

测试最佳实践:

  • 始终使用 StepVerifier 测试响应式链
  • 模拟外部依赖(模型、API)
  • 测试错误情况和边界条件
  • 验证 Hook 是否正确调用
  • 测试超时和取消场景

代码风格指南

日志记录
private static final Logger log = LoggerFactory.getLogger(MyClass.class);

// Use parameterized logging
log.info("Processing message from user: {}", userId);
log.error("Failed to call model: {}", modelName, exception);
错误处理
// Prefer specific error messages
return Mono.error(new IllegalArgumentException(
    "Invalid model name: " + modelName + ". Expected one of: " + VALID_MODELS));

// Use onErrorResume for graceful degradation
return model.generate(msgs, null, null)
    .onErrorResume(e -> {
        log.error("Model call failed, using fallback", e);
        return Mono.just(fallbackResponse);
    });
空值安全
// Use Optional for nullable returns
public Optional<AgentTool> findTool(String name) {
    return Optional.ofNullable(tools.get(name));
}

// Use Objects.requireNonNull for validation
public MyAgent(Model model) {
    this.model = Objects.requireNonNull(model, "Model cannot be null");
}
注释
// Use Javadoc for public APIs
/**
 * Creates a new agent with the specified configuration.
 *
 * @param name The agent name (must be unique)
 * @param model The LLM model to use
 * @return Configured agent instance
 * @throws IllegalArgumentException if name is null or empty
 */
public static ReActAgent create(String name, Model model) {
    // Implementation
}

// Use inline comments sparingly, only for complex logic
// Calculate exponential backoff: 2^attempt * baseDelay
Duration delay = Duration.ofMillis((long) Math.pow(2, attempt) * baseDelayMs);

主要库

  • Reactor Core:用于响应式编程的 Mono、Flux
  • Jackson:JSON 序列化/反序列化
  • SLF4J:日志记录(private static final Logger log = LoggerFactory.getLogger(MyClass.class);)
  • OkHttp:用于模型 API 的 HTTP 客户端
  • MCP SDK:模型上下文协议集成
  • JUnit 5:测试框架
  • Mockito:模拟框架
  • Lombok:减少样板代码

禁止的做法

❌ 绝对不要这样做
  1. 在响应式链中阻塞

    // ❌ WRONG
    return someMonoOperation().block();
    
  2. 使用 Thread.sleep() 或阻塞式 I/O

    // ❌ WRONG
    Thread.sleep(1000);
    
    // ✅ CORRECT
    return Mono.delay(Duration.ofSeconds(1));
    
  3. 未同步就修改共享状态

    // ❌ WRONG
    private List<Msg> messages = new ArrayList<>();
    public void addMessage(Msg msg) {
        messages.add(msg);  // Not thread-safe
    }
    
  4. 静默忽略错误

    // ❌ WRONG
    .onErrorResume(e -> Mono.empty())
    
    // ✅ CORRECT
    .onErrorResume(e -> {
        log.error("Operation failed", e);
        return Mono.just(fallbackValue);
    })
    
  5. 在响应式代码中使用 ThreadLocal

    // ❌ WRONG
    ThreadLocal<String> context = new ThreadLocal<>();
    
    // ✅ CORRECT
    return Mono.deferContextual(ctx -> {
        String value = ctx.get("key");
        // Use value
    });
    
  6. 创建 Agent 时未妥善管理资源

    // ❌ WRONG - No cleanup
    public void processRequests() {
        for (int i = 0; i < 1000; i++) {
            ReActAgent agent = createAgent();
            agent.call(msg).block();
        }
    }
    
  7. 将 API 密钥或机密硬编码

    // ❌ WRONG
    String apiKey = "sk-1234567890";
    
    // ✅ CORRECT
    String apiKey = System.getenv("OPENAI_API_KEY");
    
  8. 使用 Java 预览功能(需要 --enable-preview)

    // ❌ WRONG - Requires Java 21 with --enable-preview
    return switch (event) {
        case PreReasoningEvent e -> handleReasoning(e);
        case PostActingEvent e -> handleActing(e);
        default -> Mono.just(event);
    };
    
    // ✅ CORRECT - Java 17 compatible
    if (event instanceof PreReasoningEvent e) {
        return handleReasoning(e);
    } else if (event instanceof PostActingEvent e) {
        return handleActing(e);
    } else {
        return Mono.just(event);
    }
    

常见陷阱与解决方案

❌ 阻塞操作
// WRONG
Msg response = agent.call(msg).block();  // Don't block in agent logic
// CORRECT
return agent.call(msg)
    .flatMap(response -> processResponse(response));
❌ 空值处理
// WRONG
String text = msg.getContent().get(0).getText();  // May throw NPE
// CORRECT
String text = msg.getTextContent();  // Safe helper method
// OR
String text = msg.getContentBlocks(TextBlock.class).stream()
    .findFirst()
    .map(TextBlock::getText)
    .orElse("");
❌ 线程上下文
// WRONG
ThreadLocal<String> context = new ThreadLocal<>();  // May not work in reactive streams
// CORRECT
return Mono.deferContextual(ctx -> {
    String value = ctx.get("key");
    // Use value
});
❌ 吞掉错误
// WRONG
.onErrorResume(e -> Mono.empty())  // Silent failure
// CORRECT
.onErrorResume(e -> {
    log.error("Failed to process: {}", input, e);
    return Mono.just(createErrorResponse(e));
})

完整示例

package com.example.agentscope;

import io.agentscope.core.ReActAgent;
import io.agentscope.core.hook.Hook;
import io.agentscope.core.hook.HookEvent;
import io.agentscope.core.hook.ReasoningChunkEvent;
import io.agentscope.core.memory.InMemoryMemory;
import io.agentscope.core.message.Msg;
import io.agentscope.core.message.MsgRole;
import io.agentscope.core.message.TextBlock;
import io.agentscope.core.model.Model;
import io.agentscope.core.tool.Tool;
import io.agentscope.core.tool.ToolParam;
import io.agentscope.core.tool.Toolkit;
import io.agentscope.extensions.model.dashscope.DashScopeChatModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * Complete example demonstrating AgentScope best practices.
 */
public class CompleteExample {

    private static final Logger log = LoggerFactory.getLogger(CompleteExample.class);

    public static void main(String[] args) {
        // 1. Create model (no .temperature() method, use defaultOptions)
        Model model = DashScopeChatModel.builder()
            .apiKey(System.getenv("DASHSCOPE_API_KEY"))
            .modelName("qwen-plus")
            .stream(true)
            .build();

        // 2. Create toolkit with tools
        Toolkit toolkit = new Toolkit();
        toolkit.registerTool(new WeatherTools());
        toolkit.registerTool(new TimeTools());

        // 3. Create hook for streaming output
        Hook streamingHook = new Hook() {
            @Override
            public <T extends HookEvent> Mono<T> onEvent(T event) {
                if (event instanceof ReasoningChunkEvent e) {
                    String text = e.getIncrementalChunk().getTextContent();
                    if (text != null) {
                        System.out.print(text);
                    }
                }
                return Mono.just(event);
            }

            @Override
            public int priority() {
                return 500;  // Low priority
            }
        };

        // 4. Build agent
        ReActAgent agent = ReActAgent.builder()
            .name("Assistant")
            .sysPrompt("You are a helpful assistant. Use tools when appropriate.")
            .model(model)
            .toolkit(toolkit)
            .memory(new InMemoryMemory())
            .hook(streamingHook)
            .maxIters(10)
            .build();

        // 5. Use agent
        Msg userMsg = Msg.builder()
            .role(MsgRole.USER)
            .content(TextBlock.builder()
                .text("What's the weather in San Francisco and what time is it?")
                .build())
            .build();

        try {
            System.out.println("User: " + userMsg.getTextContent());
            System.out.print("Assistant: ");

            // ⚠️ IMPORTANT: .block() is ONLY allowed in main() methods for demo purposes
            // NEVER use .block() in agent logic, service methods, or library code
            Msg response = agent.call(userMsg).block();

            System.out.println("\n\n--- Response Details ---");
            System.out.println("Role: " + response.getRole());
            System.out.println("Content: " + response.getTextContent());

        } catch (Exception e) {
            log.error("Error during agent execution", e);
            System.err.println("Error: " + e.getMessage());
        }
    }

    /**
     * Example tool class for weather information.
     */
    public static class WeatherTools {

        @Tool(description = "Get current weather for a city. Returns temperature and conditions.")
        public String getWeather(
                @ToolParam(name = "city", description = "City name, e.g., 'San Francisco'")
                String city) {

            log.info("Getting weather for city: {}", city);

            // Simulate API call
            return String.format("Weather in %s: Sunny, 22°C, Light breeze", city);
        }
    }

    /**
     * Example tool class for time information.
     */
    public static class TimeTools {

        private static final DateTimeFormatter FORMATTER =
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        @Tool(description = "Get current date and time")
        public String getCurrentTime() {
            LocalDateTime now = LocalDateTime.now();
            String formatted = now.format(FORMATTER);

            log.info("Returning current time: {}", formatted);

            return "Current time: " + formatted;
        }
    }
}

快速参考

创建 Agent
ReActAgent agent = ReActAgent.builder()
    .name("AgentName")
    .sysPrompt("System prompt")
    .model(model)
    .toolkit(toolkit)
    .memory(memory)
    .hooks(hooks)
    .maxIters(10)
    .build();
创建消息
Msg msg = Msg.builder()
    .role(MsgRole.USER)
    .content(TextBlock.builder().text("Hello").build())
    .build();
注册工具
Toolkit toolkit = new Toolkit();
toolkit.registerTool(new MyTools());
创建 Hook
Hook hook = new Hook() {
    public <T extends HookEvent> Mono<T> onEvent(T event) {
        // Handle event
        return Mono.just(event);
    }
};
创建 Pipeline
SequentialPipeline pipeline = SequentialPipeline.builder()
    .addAgent(agent1)
    .addAgent(agent2)
    .build();

评论

支持 Markdown