adk-typescript
Version:
TypeScript port of Google's Agent Development Kit (ADK)
160 lines (159 loc) • 6.82 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.requestProcessor = void 0;
const LlmAgent_1 = require("../../agents/LlmAgent");
/**
* A request processor that adds agent transfer capability to LLM requests.
*/
class AgentTransferLlmRequestProcessor {
/**
* Runs the processor asynchronously.
*
* @param invocationContext The invocation context
* @param llmRequest The LLM request to process
* @returns An async generator yielding events
*/
async *runAsync(invocationContext, llmRequest) {
const agent = invocationContext.agent;
// Build potential transfer targets to other agents
const targetAgents = this.buildTargetAgentsList(invocationContext);
if (!targetAgents || targetAgents.length === 0) {
// No available targets, nothing to do
return;
}
// Append instructions for the agent transfer ability
const instructions = this.buildTargetAgentInstructions(targetAgents);
llmRequest.appendInstructions(instructions);
// Add the function definition for transfer_to_agent
this.addTransferFunction(llmRequest);
// Return early - no events to yield
return;
// The code below is unreachable but satisfies the AsyncGenerator return type
yield {};
}
/**
* Adds the transfer_to_agent function definition to the LLM request.
*
* @param llmRequest The LLM request to add the function to
*/
addTransferFunction(llmRequest) {
// Use the addFunction method directly instead of type casting
llmRequest.addFunction({
name: 'transfer_to_agent',
description: 'Transfer to another agent if the current agent cannot handle the request',
parameters: {
type: 'object',
properties: {
agent_name: {
type: 'string',
description: 'Name of the agent to transfer to'
},
reason: {
type: 'string',
description: 'Reason for transferring to the specified agent'
}
},
required: ['agent_name', 'reason']
}
});
}
/**
* Builds the list of available target agents for transfer.
*
* @param invocationContext The invocation context
* @returns List of target agent objects with name and description
*/
buildTargetAgentsList(invocationContext) {
const agent = invocationContext.agent;
// Get the session from invocation context
const session = invocationContext.session;
const targetAgents = [];
// Make sure the session has an agents Map
if (!session.agents) {
session.agents = new Map();
}
// Ensure the agents property is a Map or at least has a forEach method
if (!(session.agents instanceof Map) && typeof session.agents.entries !== 'function') {
console.warn('Session agents is not a Map, creating a new Map');
const oldAgents = session.agents;
session.agents = new Map();
// If agents is an object, try to convert it to a Map
if (typeof oldAgents === 'object' && oldAgents !== null) {
Object.entries(oldAgents).forEach(([name, agent]) => {
session.agents.set(name, agent);
});
}
}
// Add the current agent to the session if not already there
if (!session.agents.has(agent.name)) {
session.agents.set(agent.name, agent);
}
// Access parent through parentAgent property from BaseAgent
if (agent.parentAgent) {
// Add parent for backward transfer if it's an LLM agent
if (agent.parentAgent instanceof LlmAgent_1.LlmAgent) {
targetAgents.push({
name: agent.parentAgent.name,
description: agent.parentAgent.description || 'Parent agent'
});
}
// Check if parent allows transfers to peer agents
// Use disallowTransferToPeers property on LlmAgent
if (agent.parentAgent instanceof LlmAgent_1.LlmAgent && !agent.parentAgent.disallowTransferToPeers) {
// Add peer agents (siblings)
// Use the agents map from the session
try {
// Safely iterate over the agents Map
for (const [peerName, peerAgent] of session.agents.entries()) {
// Skip self and non-children of parent
if (peerAgent === agent || peerAgent.parentAgent !== agent.parentAgent) {
continue;
}
targetAgents.push({
name: peerAgent.name,
description: peerAgent.description || `Peer agent: ${peerAgent.name}`
});
}
}
catch (error) {
console.error('Error iterating over agents:', error);
}
}
}
// Add sub-agents as transfer targets
// Safely iterate over the agents Map
try {
for (const [subName, subAgent] of session.agents.entries()) {
if (subAgent.parentAgent === agent) {
targetAgents.push({
name: subAgent.name,
description: subAgent.description || `Sub-agent: ${subAgent.name}`
});
}
}
}
catch (error) {
console.error('Error iterating over agents for sub-agents:', error);
}
return targetAgents;
}
/**
* Builds instructions for agent transfer capability.
*
* @param targetAgents List of target agents with name and description
* @returns Array of instruction strings
*/
buildTargetAgentInstructions(targetAgents) {
const instructions = [];
instructions.push('You can transfer to other agents when you cannot handle the request:');
// Add description for each target agent
for (const targetAgent of targetAgents) {
instructions.push(` - ${targetAgent.name}: ${targetAgent.description}`);
}
instructions.push('To transfer, call the transfer_to_agent function with the agent name and reason. ' +
'Don\'t transfer unless you need to.');
return instructions;
}
}
// Export the processor instance
exports.requestProcessor = new AgentTransferLlmRequestProcessor();