🔄 AgentScope 参数传递的所有方式

详细列举父 Agent 向子 Agent 传递参数的所有可用方式


📋 参数传递方式完整列表

方式 1:textContent(消息正文)✅

用途:传递对话内容,AI 会读取和处理

示例

Msg msg = Msg.builder()
        .textContent("用户想查询订单ORDER-001的状态")  // ← 方式1:文本内容
        .build();

特点

  • ✅ AI 会读取这个内容
  • ✅ 用于传递对话上下文
  • ⚠️ 不适合传递结构化参数

方式 2:metadata(元数据)✅ 推荐

用途:传递结构化业务参数,AI 不读取,程序提取

示例

Msg msg = Msg.builder()
        .textContent("用户想查询订单")
        .metadata(Map.of(                              // ← 方式2:元数据
            "userId", 12345L,
            "orderId", "ORDER-001",
            "priority", "HIGH"
        ))
        .build();

特点

  • ✅ 结构化数据,易于提取
  • ✅ AI 不会读取,不干扰对话
  • ✅ 支持任意键值对
  • 最常用、最推荐的方式

子 Agent 提取

String userId = msg.getMetadata().get("userId").toString();
String orderId = msg.getMetadata().get("orderId").toString();

方式 3:role(角色)⚠️

用途:指定消息角色,影响 AI 的理解

示例

Msg msg = Msg.builder()
        .textContent("用户想查询订单")
        .role("user")                                  // ← 方式3:角色
        .build();

可选值

  • "user" - 用户消息
  • "assistant" - AI 助手消息
  • "system" - 系统消息

特点

  • ⚠️ 主要用于控制对话上下文
  • ⚠️ 不用于传递业务参数
  • ⚠️ 通常由框架自动设置

方式 4:name(消息名称)⚠️

用途:标识消息来源或发送者

示例

Msg msg = Msg.builder()
        .textContent("用户想查询订单")
        .name("supervisor_agent")                      // ← 方式4:名称
        .build();

特点

  • ⚠️ 用于标识消息来源
  • ⚠️ 不常用于参数传递
  • ⚠️ 主要用于多 Agent 场景的追踪

方式 5:通过 AgentRequestOptions ✅

用途:传递请求级别的控制参数

示例

// 父 Agent 工具类
AgentRequestOptions options = AgentRequestOptions.builder()
        .taskId("task-123")                            // ← 方式5:通过 options
        .userId("user-456")
        .timeout(Duration.ofSeconds(30))
        .build();

businessAgent.call(msg, options).block();

子 Agent 接收

@Override
public Flux<Event> stream(List<Msg> requestMessages, AgentRequestOptions options) {
    String taskId = options.getTaskId();               // ← 从 options 提取
    String userId = options.getUserId();
    Duration timeout = options.getTimeout();
    // ...
}

特点

  • ✅ 用于传递请求级别的参数
  • ✅ 不会混入对话内容
  • ⚠️ 可用参数由 AgentRequestOptions 定义,不如 metadata 灵活

方式 6:通过 ContentBlock(复杂内容)⚠️

用途:传递多种类型的内容(文本、图片、工具调用结果等)

示例

Msg msg = Msg.builder()
        .content(List.of(
            TextBlock.of("用户想查询订单"),              // ← 文本内容
            ImageBlock.of("image_url"),                 // ← 图片
            ToolResultBlock.of("tool_result")           // ← 工具结果
        ))
        .build();

特点

  • ⚠️ 用于多模态内容(文本+图片+工具结果)
  • ⚠️ 不常用于简单参数传递
  • ⚠️ 比较复杂,适合高级场景

方式 7:直接在 textContent 中嵌入参数 ❌ 不推荐

用途:把参数混在文本里

示例

Msg msg = Msg.builder()
        .textContent("用户ID:12345,订单号:ORDER-001,用户想查询订单状态")  // ← 方式7:混在文本里
        .build();

子 Agent 提取

// 需要解析文本
String text = msg.getTextContent();
String userId = extractUserId(text);  // 自己写解析逻辑
String orderId = extractOrderId(text);

特点

  • ❌ 难以解析,容易出错
  • ❌ AI 会读取参数,可能干扰对话
  • ❌ 不推荐使用

方式 8:通过全局 Session/Context ⚠️

用途:在 Agent 构建时传递参数

示例

// 父 Agent 工具类
public ToolResultBlock callBusinessAgent(
        @ToolParam String context,
        @ToolParam Long userId) {
    
    // 方式8:通过 Session 传递全局参数
    Session session = sessionManager.getSession(userId);
    session.setAttribute("userId", userId);
    session.setAttribute("currentOrder", "ORDER-001");
    
    // 子 Agent 可以从 Session 读取
    Msg msg = Msg.builder()
            .textContent(context)
            .build();
    
    return businessAgent.call(msg).block();
}

特点

  • ⚠️ 用于跨多次对话的全局状态
  • ⚠️ 不适合单次请求的参数传递
  • ⚠️ 需要额外的 Session 管理

📊 方式对比表

方式用途优点缺点推荐度
textContent对话内容AI 能理解混淆参数和对话⭐⭐⭐
metadata业务参数结构化、易提取需要手动放入/提取⭐⭐⭐⭐⭐
role消息角色控制对话流程不适合传参数
name消息来源标识发送者不适合传参数
AgentRequestOptions请求参数不混入消息参数有限⭐⭐⭐⭐
ContentBlock多模态内容支持多种类型复杂⭐⭐
嵌入 textContent--难解析、易出错
Session/Context全局状态跨对话共享管理复杂⭐⭐

🎯 推荐的最佳实践

标准组合:textContent + metadata ✅

@Tool(description = "处理订单")
public ToolResultBlock callBusinessAgent(
        @ToolParam(name = "context") String context,
        @ToolParam(name = "userId") Long userId,
        @ToolParam(name = "orderId") String orderId,
        @ToolParam(name = "priority") String priority) {
    
    // 标准组合
    Msg msg = Msg.builder()
            .textContent(context)              // ← 对话内容放这里(AI 读)
            .metadata(Map.of(                  // ← 业务参数放这里(程序用)
                "userId", userId,
                "orderId", orderId,
                "priority", priority
            ))
            .build();
    
    return businessAgent.call(msg).block();
}

子 Agent 提取

@Override
public Flux<Event> stream(List<Msg> requestMessages, AgentRequestOptions options) {
    // 提取对话内容
    String textContent = requestMessages.get(0).getTextContent();
    
    // 提取业务参数
    String userId = extractMetadata(requestMessages, "userId");
    String orderId = extractMetadata(requestMessages, "orderId");
    String priority = extractMetadata(requestMessages, "priority");
    
    // 使用参数
    ReActAgent agent = buildReActAgent(userId, orderId, priority);
    return agent.stream(requestMessages);
}

🌰 完整示例:使用多种方式

场景:复杂的订单处理

@Tool(description = "处理订单")
public ToolResultBlock handleComplexOrder(
        @ToolParam(name = "context") String context,
        @ToolParam(name = "userId") Long userId,
        @ToolParam(name = "orderId") String orderId,
        @ToolParam(name = "priority") String priority,
        @ToolParam(name = "timeout") Integer timeoutSeconds) {
    
    // ========== 方式1:textContent(对话内容)==========
    String textContent = context;
    
    // ========== 方式2:metadata(业务参数)==========
    Map<String, Object> metadata = new HashMap<>();
    metadata.put("userId", userId);
    metadata.put("orderId", orderId);
    metadata.put("priority", priority);
    metadata.put("timestamp", System.currentTimeMillis());
    metadata.put("source", "supervisor-agent");
    
    // ========== 方式3:role(消息角色)==========
    String role = "user";  // 标识这是用户消息
    
    // ========== 方式4:name(消息来源)==========
    String name = "supervisor-agent";
    
    // ========== 方式5:AgentRequestOptions(请求参数)==========
    AgentRequestOptions options = AgentRequestOptions.builder()
            .taskId("task-" + System.currentTimeMillis())
            .userId(userId.toString())
            .timeout(Duration.ofSeconds(timeoutSeconds))
            .build();
    
    // 构造消息
    Msg msg = Msg.builder()
            .textContent(textContent)      // 方式1
            .metadata(metadata)            // 方式2
            .role(role)                    // 方式3
            .name(name)                    // 方式4
            .build();
    
    // 调用子 Agent(带 options)
    Msg result = businessAgent.call(msg, options).block();  // 方式5
    
    return ToolResultBlock.of(result.getContent());
}

子 Agent 接收

@Override
public Flux<Event> stream(List<Msg> requestMessages, AgentRequestOptions options) {
    Msg firstMsg = requestMessages.get(0);
    
    // ========== 从不同方式提取参数 ==========
    
    // 方式1:textContent
    String textContent = firstMsg.getTextContent();
    
    // 方式2:metadata
    Map<String, Object> metadata = firstMsg.getMetadata();
    String userId = metadata.get("userId").toString();
    String orderId = metadata.get("orderId").toString();
    String priority = metadata.get("priority").toString();
    Long timestamp = (Long) metadata.get("timestamp");
    String source = metadata.get("source").toString();
    
    // 方式3:role
    String role = firstMsg.getRole();
    
    // 方式4:name
    String name = firstMsg.getName();
    
    // 方式5:AgentRequestOptions
    String taskId = options.getTaskId();
    String optionsUserId = options.getUserId();
    Duration timeout = options.getTimeout();
    
    // 使用所有参数
    log.info("Received request - textContent: {}, userId: {}, orderId: {}, priority: {}, " +
            "timestamp: {}, source: {}, role: {}, name: {}, taskId: {}, timeout: {}",
            textContent, userId, orderId, priority, timestamp, source, role, name, taskId, timeout);
    
    ReActAgent agent = buildReActAgent(userId, orderId, priority);
    return agent.stream(requestMessages);
}

🔥 实战建议

建议 1:日常开发只用两种方式

// 90% 的场景只需要这两种
Msg msg = Msg.builder()
        .textContent(context)              // 方式1:对话内容
        .metadata(Map.of(                  // 方式2:业务参数
            "userId", userId,
            "orderId", orderId
        ))
        .build();

建议 2:参数分类

// 对话内容 → textContent
// 业务参数 → metadata
// 控制参数 → AgentRequestOptions

Msg msg = Msg.builder()
        .textContent("用户想查询订单")                    // 对话
        .metadata(Map.of("userId", 123, "orderId", "001"))  // 业务
        .build();

AgentRequestOptions options = AgentRequestOptions.builder()
        .timeout(Duration.ofSeconds(30))                    // 控制
        .build();

建议 3:避免混用

// ❌ 不要这样:参数既在 textContent 又在 metadata
.textContent("用户12345想查询订单ORDER-001")  // ❌ 参数混在文本里
.metadata(Map.of("userId", 12345, "orderId", "ORDER-001"))  // ❌ 又在 metadata

// ✅ 应该这样:清晰分离
.textContent("用户想查询订单")                // ✅ 纯粹的对话内容
.metadata(Map.of("userId", 12345, "orderId", "ORDER-001"))  // ✅ 参数在 metadata

📝 总结答案

你的问题:除了 context 和 metadata,还有哪些方式可以传递参数?

答案:共有 8 种方式,但实际常用的只有 2-3 种

方式使用频率说明
textContent⭐⭐⭐⭐⭐传对话内容,最常用
metadata⭐⭐⭐⭐⭐传业务参数,最推荐
AgentRequestOptions⭐⭐⭐传控制参数,偶尔用
role⭐⭐控制对话角色,少用
name⭐⭐标识消息来源,少用
ContentBlock多模态内容,高级场景
嵌入 textContent不推荐
Session/Context全局状态,特殊场景

最佳实践

// 90% 的场景只需要这个组合
Msg msg = Msg.builder()
        .textContent(context)      // 对话内容
        .metadata(metadata)        // 业务参数
        .build();

明白了吗?🎉

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐