feat: 归档 XL08 异步工具协议

- 新增 AsyncToolSpec 与 AsyncSubTools 五子工具展开能力

- 增加异步工具事件、上下文事件发射和模型可见结果裁剪

- 补充 AgentScope 异步工具协议提示与 runtime 单元测试
This commit is contained in:
2026-06-04 15:23:04 +08:00
parent 43f45956ff
commit 7cac558b6c
22 changed files with 2894 additions and 2 deletions

View File

@@ -54,6 +54,18 @@ import java.util.function.Supplier;
*/
public class AgentScopeReActRuntime implements AgentRuntime {
private static final String ASYNC_TOOL_SYSTEM_PROMPT = """
Async tool protocol:
- Async tools may expose submit, observe, result, cancel, and list sub-tools. Treat these sub-tools as one user-facing tool.
- Do not ask the user to choose submit, observe, result, cancel, or list. These are internal execution phases.
- For a normal user request to use an async tool, call its submit sub-tool first with the user-provided arguments by default.
- After submit returns task_id, immediately call observe with that task_id to check progress.
- If the task is completed and result is available, use the returned result to answer the user.
- If the task is still running after observation, tell the user that the task is running and keep task_id/next_action for later tool calls.
- Use result, list, or cancel directly only when the user explicitly asks to get a known task result, list tasks, or cancel a task.
""";
private final AgentScopeModelFactory modelFactory;
private final AgentScopeToolAdapter toolAdapter;
private final AgentScopeKnowledgeAdapter knowledgeAdapter;
@@ -1090,7 +1102,7 @@ public class AgentScopeReActRuntime implements AgentRuntime {
ReActAgent.Builder builder = ReActAgent.builder()
.name(definition.getAgentName())
.description(definition.getDescription())
.sysPrompt(definition.getSystemPrompt())
.sysPrompt(systemPrompt(definition))
.model(model)
.toolkit(toolkit)
.memory(memory)
@@ -1110,6 +1122,30 @@ public class AgentScopeReActRuntime implements AgentRuntime {
return builder.build();
}
private String systemPrompt(AgentDefinition definition) {
String prompt = definition.getSystemPrompt();
if (!hasAsyncTool(definition)) {
return prompt;
}
if (prompt == null || prompt.isBlank()) {
return ASYNC_TOOL_SYSTEM_PROMPT.strip();
}
return prompt.stripTrailing() + ASYNC_TOOL_SYSTEM_PROMPT;
}
private boolean hasAsyncTool(AgentDefinition definition) {
if (definition == null || definition.getToolSpecs() == null) {
return false;
}
for (AgentToolSpec toolSpec : definition.getToolSpecs()) {
// AsyncToolSpecExpander marks all generated sub-tools with this runtime metadata.
if (toolSpec != null && Boolean.TRUE.equals(toolSpec.getMetadata().get("asyncTool"))) {
return true;
}
}
return false;
}
/**
* 构建 AgentScope Toolkit并返回按 Skill ID 分组的工具。
*

View File

@@ -364,6 +364,7 @@ public class AgentScopeToolAdapter {
if (param != null && param.getToolUseBlock() != null) {
context.setToolCallId(param.getToolUseBlock().getId());
}
context.setEventEmitter(this::emit);
context.getMetadata().put("toolName", toolSpec.getName());
context.getMetadata().put("category", toolSpec.getCategory());
appendSkillPayload(context.getMetadata(), activeSkillBinding());
@@ -372,7 +373,7 @@ public class AgentScopeToolAdapter {
}
/**
* 将运行时结果转换为 AgentScope 结果块。
* 将 AgentToolResult 转换为 AgentScope 结果块。
*
* @param param 工具调用参数
* @param result 运行时结果