Validating Agent Output With FunctionTarget: A Comprehensive Guide to Custom Validation in Multi-Agent Conversations#
This notebook demonstrates how to use FunctionTarget to implement custom validation logic that intercepts and validates agent outputs before they proceed to the next stage in a multi-agent conversation. You’ll learn how to create validation functions that can accept or reject agent responses, route messages to different agents based on validation results, and maintain context throughout the conversation flow.
Setup and Imports#
In this section, we import all necessary modules and configure the LLM settings. We’ll set up the LLMConfig with OpenAI API credentials and initialize an empty ContextVariables object that will be used to store shared state across agents during the conversation.
import os
from typing import Any
from autogen import ConversableAgent, LLMConfig
from autogen.agentchat.group import AgentNameTarget, ContextVariables, FunctionTarget, FunctionTargetResult, StayTarget
from autogen.agentchat.group.multi_agent_chat import run_group_chat
from autogen.agentchat.group.patterns import DefaultPattern
cfg = LLMConfig(api_type="openai", model="gpt-4o-mini", api_key=os.getenv("OPENAI_API_KEY"))
ctx = ContextVariables(data={})
Agent Definitions#
Here we define two specialized agents that will participate in our multi-agent workflow:
-
Job Application Agent: This agent is responsible for drafting compelling job application emails. It receives information about a specific job role and generates a professional application email that must follow specific formatting requirements (starting with ‘Dear Stope Recruiting Team,’ and ending with ‘Sincerely, [Your Name]’).
-
Application Review Agent: This agent acts as a senior recruiter at Stope (a company specializing in GPU optimization for AI workloads). It reviews the application emails generated by the job application agent and makes acceptance or rejection decisions based on the content quality and relevance.
# Agents
job_application_agent = ConversableAgent(
name="job_application_agent",
llm_config=cfg,
system_message="""
You are a job application agent helping users draft compelling job application emails for tech roles.
You will receive info about the specific job role that you are applying for.
Start your email with the exact words 'Dear Stope Recruiting Team,' and end with 'Sincerely, [Your Name]'.
Make the email highly compelling such that it would convince a senior recruiter to accept your application.
""",
)
application_review_agent = ConversableAgent(
name="application_review_agent",
llm_config=cfg,
system_message="""You are a senior recruiter reviewing job applications, working at the company Stope, a leader in GPU optimization for AI workloads.
Review the application email provided to you and determine whether you would accept or reject the application based on its content.""",
)
FunctionTarget Definition: Implementing Custom Validation Logic#
The FunctionTarget is a powerful mechanism that allows you to intercept agent outputs and apply custom validation or processing logic before routing messages to the next agent. In this example, we define a validate_application function that:
- Validates Format Requirements: Checks if the application email starts with the required salutation ‘Dear Stope Recruiting Team’
- Stores Context: Saves the validated application to the shared context variables for later use
- Routes Based on Validation:
- If validation passes: Routes the message to the
application_review_agentfor final review - If validation fails: Returns the message to the same agent (
StayTarget) with feedback requesting a revision
- If validation passes: Routes the message to the
This pattern enables you to enforce quality gates and ensure agent outputs meet specific criteria before proceeding in the conversation workflow.
# A FunctionTarget must have the signature (input: str, context_variables: Any) -> FunctionTargetResult
def validate_application(application: str, context_variables: Any) -> FunctionTargetResult:
"""
Custom FunctionTarget to validate the application draft, ensuring it begins with exactly 'Dear Stope Recruiting Team', as instructed.
If it does, proceed to the next agent for review; if not, explain the issue and ask for a revision.
"""
# Save application to context
context_variables["application"] = application
# Simple validation example
if "Dear Stope Recruiting Team" in application:
return FunctionTargetResult(
messages=f"Review the following job application: {application}",
target=AgentNameTarget("application_review_agent"),
context_variables=context_variables,
)
else:
return FunctionTargetResult(
messages="The application does not start with the required salutation 'Dear Stope Recruiting Team'. Please regenerate it, ensuring it starts with this exact phrase.",
target=StayTarget(),
context_variables=context_variables,
)
Pattern Configuration and Group Chat Initiation#
In this final section, we configure the conversation pattern and initiate the multi-agent group chat:
-
Pattern Setup: We create a
DefaultPatternthat defines the conversation structure, specifying the initial agent, all participating agents, and shared context variables. -
Handoff Registration: We register the
validate_applicationfunction as an after-work handoff for thejob_application_agent. This means that every time the job application agent completes its work, the validation function will be automatically invoked to check the output before routing it to the next agent. -
Chat Initiation: We start the group chat with an initial message describing the job application scenario. The conversation will proceed through multiple rounds (up to 8 rounds) as the agents collaborate to create and review a job application email, with validation ensuring quality at each step.
# Conversation pattern
pattern = DefaultPattern(
initial_agent=job_application_agent,
agents=[job_application_agent, application_review_agent],
user_agent=None,
context_variables=ctx,
group_manager_args={"llm_config": cfg},
)
# Register after-work handoff
job_application_agent.handoffs.set_after_work(FunctionTarget(validate_application))
# Run
response = run_group_chat(
pattern=pattern,
messages="You are applying for the position of Software Engineer at Stope, a leader in GPU Optimization for AI workloads.",
max_rounds=8,
)
response.process()