mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-06-09 19:45:17 +02:00
Update agent control flow stack logic
This commit is contained in:
parent
a09004a635
commit
f35d5f0b0b
1 changed files with 24 additions and 28 deletions
|
|
@ -404,11 +404,12 @@ function getStartOfTurnAgentName(
|
|||
workflow: z.infer<typeof Workflow>,
|
||||
): string {
|
||||
logger = logger.child(`getStartOfTurnAgentName`);
|
||||
logger.log(`stack: ${stack.join(', ')}`);
|
||||
logger.log(`stack: ${JSON.stringify(stack)}`);
|
||||
|
||||
|
||||
// if control type is retain, return last agent
|
||||
const lastAgentName = stack.pop() || workflow.startAgent;
|
||||
logger.log(`popped agent from stack: ${lastAgentName} || reason: last agent logic`);
|
||||
const lastAgentConfig = agentConfig[lastAgentName];
|
||||
if (!lastAgentConfig) {
|
||||
logger.log(`last agent ${lastAgentName} not found in agent config, returning start agent: ${workflow.startAgent}`);
|
||||
|
|
@ -420,6 +421,7 @@ function getStartOfTurnAgentName(
|
|||
return lastAgentName;
|
||||
case 'relinquish_to_parent':
|
||||
const parentAgentName = stack.pop() || workflow.startAgent;
|
||||
logger.log(`popped agent from stack: ${lastAgentName} || reason: relinquish to parent triggered`);
|
||||
logger.log(`last agent ${lastAgentName} control type is relinquish_to_parent, returning most recent parent: ${parentAgentName}`);
|
||||
return parentAgentName;
|
||||
case 'relinquish_to_start':
|
||||
|
|
@ -566,23 +568,6 @@ async function* emitGreetingTurn(logger: PrefixLogger, workflow: z.infer<typeof
|
|||
yield* emitEvent(logger, new UsageTracker().asEvent());
|
||||
}
|
||||
|
||||
function createAgentCallStack(messages: z.infer<typeof Message>[]): string[] {
|
||||
console.log(`createAgentCallStack: Messages: ${JSON.stringify(messages)}`);
|
||||
const stack: string[] = [];
|
||||
for (const msg of messages) {
|
||||
if (msg.role === 'assistant' && msg.agentName) {
|
||||
// skip duplicate entries
|
||||
if (stack.length > 0 && stack[stack.length - 1] === msg.agentName) {
|
||||
continue;
|
||||
}
|
||||
// add to stack
|
||||
stack.push(msg.agentName);
|
||||
}
|
||||
}
|
||||
console.log(`createAgentCallStack: Stack: ${JSON.stringify(stack)}`);
|
||||
return stack;
|
||||
}
|
||||
|
||||
function createTools(logger: PrefixLogger, workflow: z.infer<typeof Workflow>, toolConfig: Record<string, z.infer<typeof WorkflowTool>>): Record<string, Tool> {
|
||||
const tools: Record<string, Tool> = {};
|
||||
for (const [toolName, config] of Object.entries(toolConfig)) {
|
||||
|
|
@ -683,8 +668,11 @@ export async function* streamResponse(
|
|||
// create map of agent, tool and prompt configs
|
||||
const { agentConfig, toolConfig, promptConfig } = mapConfig(workflow, projectTools);
|
||||
|
||||
// create agent call stack from input messages
|
||||
const stack = createAgentCallStack(messages);
|
||||
// create agent call stack from input messages - TODO - remove this
|
||||
// const stack = createAgentCallStack(messages);
|
||||
|
||||
const stack: string[] = [];
|
||||
logger.log(`initialized stack: ${JSON.stringify(stack)}`);
|
||||
|
||||
// create tools
|
||||
const tools = createTools(logger, workflow, toolConfig);
|
||||
|
|
@ -708,6 +696,8 @@ export async function* streamResponse(
|
|||
|
||||
// loop indefinitely
|
||||
turnLoop: while (true) {
|
||||
|
||||
logger.log(`starting turn loop iteration: ${iter}`);
|
||||
// increment loop counter
|
||||
iter++;
|
||||
|
||||
|
|
@ -716,7 +706,7 @@ export async function* streamResponse(
|
|||
|
||||
// log agent info
|
||||
loopLogger.log(`agent name: ${agentName}`);
|
||||
loopLogger.log(`stack: ${stack.join(', ')}`);
|
||||
loopLogger.log(`stack: ${JSON.stringify(stack)}`);
|
||||
if (!agents[agentName]) {
|
||||
throw new Error(`agent not found in agent config!`);
|
||||
}
|
||||
|
|
@ -751,7 +741,6 @@ export async function* streamResponse(
|
|||
// handle streaming events
|
||||
for await (const event of result) {
|
||||
const eventLogger = loopLogger.child(event.type);
|
||||
eventLogger.log(`----------> stack: ${JSON.stringify(stack)}`);
|
||||
|
||||
switch (event.type) {
|
||||
case 'raw_model_stream_event':
|
||||
|
|
@ -814,15 +803,20 @@ export async function* streamResponse(
|
|||
// update transfer counter
|
||||
transferCounter.increment(agentName, event.item.targetAgent.name);
|
||||
|
||||
// add current agent to stack only if new agent is internal
|
||||
const newAgentName = event.item.targetAgent.name;
|
||||
if (agentConfig[newAgentName]?.outputVisibility === 'internal') {
|
||||
stack.push(newAgentName);
|
||||
}
|
||||
|
||||
loopLogger.log(`switched to agent: ${newAgentName} || reason: handoff by ${agentName}`);
|
||||
|
||||
// add current agent to stack only if new agent is internal
|
||||
if (agentConfig[newAgentName]?.outputVisibility === 'internal') {
|
||||
stack.push(agentName);
|
||||
loopLogger.log(`-- pushed agent to stack: ${agentName} || reason: new agent ${newAgentName} is internal`);
|
||||
loopLogger.log(`-- stack is now: ${JSON.stringify(stack)}`);
|
||||
}
|
||||
|
||||
// set this as the new agent name
|
||||
agentName = newAgentName;
|
||||
loopLogger.log(`switched to agent: ${agentName}`);
|
||||
|
||||
}
|
||||
|
||||
// handle tool call result
|
||||
|
|
@ -873,6 +867,8 @@ export async function* streamResponse(
|
|||
const current = agentName;
|
||||
// pop the stack
|
||||
agentName = stack.pop()!;
|
||||
loopLogger.log(`-- popped agent from stack: ${agentName} || reason: it is an internal agent and it put out a message, hence the flow of control needs to return to the previous agent`);
|
||||
loopLogger.log(`-- stack is now: ${JSON.stringify(stack)}`);
|
||||
|
||||
// emit transfer tool call invocation
|
||||
const [transferStart, transferComplete] = createTransferEvents(current, agentName);
|
||||
|
|
@ -889,7 +885,7 @@ export async function* streamResponse(
|
|||
transferCounter.increment(current, agentName);
|
||||
|
||||
// set this as the new agent name
|
||||
loopLogger.log(`switched to agent (reason: internal agent put out a message): ${agentName}`);
|
||||
loopLogger.log(`switched to agent: ${agentName} || reason: internal agent (${current}) put out a message`);
|
||||
|
||||
// run the turn from the previous agent
|
||||
continue turnLoop;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue