Agent Selection Logic

Purpose

Within the broader scope of the Agent Execution Runner that manages running agents in sessions, the Agent Selection Logic subtopic specifically addresses the problem of determining which agent should handle the next user input. This selection is crucial because sessions can contain multiple agents arranged in a tree hierarchy, and conversations may transfer control between sub-agents. The logic ensures that the correct agent continues the conversation based on session event history and the agents' transfer permissions.

This subtopic exists to:

Functionality

The agent selection process works by analyzing the session's event history in reverse chronological order to find the last agent that produced an event (response) before the user's current input. The core function responsible for this is findAgentToRun in the runner package.

Key steps in the workflow:

  1. Retrieve Session Events: The session holds a list of events representing the conversation history, including user messages and agent responses.

  2. Scan Events Backwards: Starting from the most recent event before the user input, the logic looks for events authored by agents (not users).

  3. Find Matching Agent: For each agent-authored event, it attempts to locate the corresponding agent in the agent tree by name using the recursive findAgent helper.

  4. Check Transfer Permissions: Once a candidate agent is found, the logic verifies if that agent and its entire parent chain allow transfer of control (i.e., if DisallowTransferToParent is false along the chain). This ensures that the agent can legitimately handle the next input.

  5. Select the Agent: If an agent passes the transfer check, it is selected to run next.

  6. Fallback: If no suitable agent is found or agents disallow transfer, the root agent is selected by default.

Transfer Permission Check

The isTransferableAcrossAgentTree function walks up the parent chain of the candidate agent, verifying that none disallow transfer to their parent. This prevents conversation control from jumping to an agent that opts out of transfer, maintaining hierarchical integrity.

Integration with the Runner

The selection logic integrates tightly with the Runner's main Run method. Before executing an agent for a user input, the runner calls findAgentToRun to decide the proper agent instance. This ensures each input is handled by the correct conversation participant, enabling multi-agent interactions and complex workflows managed in Agent Execution Runner.

Code Illustration

A simplified snippet from runner.go exemplifies the core selection logic:

func (r *Runner) findAgentToRun(session session.Session) (agent.Agent, error) {
    events := session.Events()
    for i := events.Len() - 1; i >= 0; i-- {
        event := events.At(i)
        if event.Author == "user" {
            continue
        }
        subAgent := findAgent(r.rootAgent, event.Author)
        if subAgent == nil {
            continue
        }
        if r.isTransferableAcrossAgentTree(subAgent) {
            return subAgent, nil
        }
    }
    return r.rootAgent, nil
}

Here, the event authorship guides agent selection, and transfer permissions control agent eligibility.

The helper findAgent recursively searches the agent tree by name:

func findAgent(curAgent agent.Agent, targetName string) agent.Agent {
    if curAgent == nil || curAgent.Name() == targetName {
        return curAgent
    }
    for _, subAgent := range curAgent.SubAgents() {
        if agent := findAgent(subAgent, targetName); agent != nil {
            return agent
        }
    }
    return nil
}

Integration

This subtopic ensures seamless interaction between these components by enforcing conversation control flow rules within the session and agent tree context.

Diagram

flowchart TD
Start[Start Agent Selection]
GetEvents["Get Session Events (Latest to Oldest)"]
CheckEvent{Is Event Author an Agent?}
FindAgent[Find Agent in Tree by Name]
AgentFound{Agent Found?}
CheckTransfer[Check Transfer Permissions]
TransferAllowed{Transfer Allowed?}
SelectAgent[Select Agent to Run]
ContinueLoop[Continue to Next Older Event]
Fallback[Fallback to Root Agent]
End[Return Selected Agent]
Start --> GetEvents --> CheckEvent
CheckEvent -- No --> ContinueLoop
CheckEvent -- Yes --> FindAgent --> AgentFound
AgentFound -- No --> ContinueLoop
AgentFound -- Yes --> CheckTransfer --> TransferAllowed
TransferAllowed -- Yes --> SelectAgent --> End
TransferAllowed -- No --> ContinueLoop
ContinueLoop --> GetEvents
GetEvents -->|No More Events| Fallback --> End

This flowchart illustrates the decision process for selecting the agent that should handle the next user input, emphasizing the event inspection, agent lookup, transfer permission check, and fallback mechanism.