/*
* Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved.
*/
package magic.agent
import magic.core.*
import magic.model.ModelManager
import magic.log.LogUtils
import magic.tool.AgentAsTool
import magic.parser.{Tag, WithTag}
/**
* This agent is used to dispatch user question to other agents.
* It's a special case of ToolSelectAgent, whose tools are agents.
* Normally, this agent plays the role of the leader of LeaderGroup.
**/
public class DispatchAgent <: BaseAgent {
public init(model!: String) {
super(name: "Dispatch Agent", model: ModelManager.createChatModel(model))
}
override public func chat(request: AgentRequest): AgentResponse {
if (let Some(agent) <- this.doSelect(request)) {
return agent.chat(request)
} else {
return AgentResponse("Unknown Question")
}
}
override public func asyncChat(request: AgentRequest): AsyncAgentResponse {
if (let Some(agent) <- this.doSelect(request)) {
if (request.verbose) {
let execInfo = AgentExecutionInfo()
execInfo.verboseChannel.put("Dispatch to the agent: ${agent.name}".withTag(Tag.INFO))
request.execInfo = execInfo
}
return agent.asyncChat(request)
} else {
return AsyncAgentResponse(["Unknown Question"].iterator())
}
}
private func doSelect(request: AgentRequest): Option<Agent> {
// Tools are updated when building the leader group, so we build the prompt every time
let selectAgent = ToolSelectAgent(this.model, this.toolManager.getTools())
if (let Some(toolRequest) <- selectAgent.select(request.question)) {
if (let Some(tool) <- this.toolManager.findTool(toolRequest.name)) {
LogUtils.info(this.name, "Dispatch to ${toolRequest.name}")
// All tools are agents
// Pass LLM generated arguments or the original request?
// tool.invoke(toolRequest.args)
return (tool as AgentAsTool).getOrThrow().agent
} else {
throw AgentExecutionException("Fail to find the agent `${name}`")
}
}
return None
}
}