Enable internal and user-facing agents to build pipelines

This commit is contained in:
akhisud3195 2025-05-06 14:49:52 +05:30
parent 1246ea47b9
commit e59a8b75cf
24 changed files with 2100 additions and 1376 deletions

View file

@ -1,7 +1,5 @@
from .access import get_agent_config_by_name, get_agent_data_by_name
from src.graph.types import ControlType
from src.utils.common import common_logger
logger = common_logger
def get_last_agent_name(state, agent_configs, start_agent_name, msg_type, latest_assistant_msg, start_turn_with_start_agent):
default_last_agent_name = state.get("last_agent_name", '')
@ -9,7 +7,7 @@ def get_last_agent_name(state, agent_configs, start_agent_name, msg_type, latest
specific_agent_data = get_agent_data_by_name(default_last_agent_name, state.get("agent_data", []))
# Overrides for special cases
logger.info("Setting agent control based on last agent and control type")
print("Setting agent control based on last agent and control type")
if msg_type == "tool":
last_agent_name = default_last_agent_name
assert last_agent_name == latest_assistant_msg.get("sender", ''), "Last agent name does not match sender of latest assistant message during tool call handling"
@ -22,7 +20,7 @@ def get_last_agent_name(state, agent_configs, start_agent_name, msg_type, latest
if control_type == ControlType.PARENT_AGENT.value:
last_agent_name = specific_agent_data.get("most_recent_parent_name", None) if specific_agent_data else None
if not last_agent_name:
logger.error("Most recent parent is empty, defaulting to same agent instead")
print("Most recent parent is empty, defaulting to same agent instead")
last_agent_name = default_last_agent_name
elif control_type == ControlType.START_AGENT.value:
last_agent_name = start_agent_name
@ -30,7 +28,7 @@ def get_last_agent_name(state, agent_configs, start_agent_name, msg_type, latest
last_agent_name = default_last_agent_name
if default_last_agent_name != last_agent_name:
logger.info(f"Last agent name changed from {default_last_agent_name} to {last_agent_name} due to control settings")
print(f"Last agent name changed from {default_last_agent_name} to {last_agent_name} due to control settings")
return last_agent_name

View file

@ -1,4 +1,4 @@
from src.graph.instructions import TRANSFER_CHILDREN_INSTRUCTIONS, TRANSFER_PARENT_AWARE_INSTRUCTIONS, RAG_INSTRUCTIONS, ERROR_ESCALATION_AGENT_INSTRUCTIONS, TRANSFER_GIVE_UP_CONTROL_INSTRUCTIONS, SYSTEM_MESSAGE
from src.graph.instructions import TRANSFER_CHILDREN_INSTRUCTIONS, TRANSFER_PARENT_AWARE_INSTRUCTIONS, RAG_INSTRUCTIONS, ERROR_ESCALATION_AGENT_INSTRUCTIONS, TRANSFER_GIVE_UP_CONTROL_INSTRUCTIONS, SYSTEM_MESSAGE, CHILD_TRANSFER_RELATED_INSTRUCTIONS
def add_transfer_instructions_to_parent_agents(agent, children, transfer_functions):
other_agent_name_descriptions_tools = f'\n{'-'*100}\n'.join([f"Name: {agent.name}\nDescription: {agent.description if agent.description else ''}\nTool for transfer: {transfer_functions[agent.name].__name__}" for agent in children.values()])
@ -36,4 +36,9 @@ def get_universal_system_message(messages):
def add_universal_system_message_to_agent(agent, universal_sys_msg):
agent.instructions = agent.instructions + f'\n\n{'-'*100}\n\n' + universal_sys_msg
return agent
return agent
def add_child_transfer_related_instructions(agent):
prompt = CHILD_TRANSFER_RELATED_INSTRUCTIONS
agent.instructions = agent.instructions + f'\n\n{'-'*100}\n\n' + prompt
return agent

View file

@ -1,5 +1,6 @@
import json
import uuid
import traceback
def handle_web_search_event(event, current_agent):
"""
@ -8,53 +9,166 @@ def handle_web_search_event(event, current_agent):
"""
messages = []
# Handle raw response web search
if event.type == "raw_response_event":
if hasattr(event, 'data') and hasattr(event.data, 'raw_item'):
raw_item = event.data.raw_item
if (hasattr(raw_item, 'type') and raw_item.type == 'web_search_call') or (
isinstance(raw_item, dict) and raw_item.get('type') == 'web_search_call'
try:
# Handle raw response web search
if event.type == "raw_response_event":
if hasattr(event, 'data') and hasattr(event.data, 'raw_item'):
raw_item = event.data.raw_item
if (hasattr(raw_item, 'type') and raw_item.type == 'web_search_call') or (
isinstance(raw_item, dict) and raw_item.get('type') == 'web_search_call'
):
call_id = None
if hasattr(raw_item, 'id'):
call_id = raw_item.id
elif isinstance(raw_item, dict) and 'id' in raw_item:
call_id = raw_item['id']
else:
call_id = str(uuid.uuid4())
status = 'unknown'
if hasattr(raw_item, 'status'):
status = raw_item.status
elif isinstance(raw_item, dict) and 'status' in raw_item:
status = raw_item['status']
tool_call_msg = {
'content': None,
'role': 'assistant',
'sender': current_agent.name if current_agent else None,
'tool_calls': [{
'function': {
'name': 'web_search',
'arguments': json.dumps({
'search_id': call_id,
'status': status
})
},
'id': call_id,
'type': 'function'
}],
'tool_call_id': None,
'tool_name': None,
'response_type': 'internal'
}
print(f"Condition for tool call matched in raw_response_event. Appending tool call message: {tool_call_msg}")
messages.append(tool_call_msg)
tool_call_output_dummy_msg = {
'content': 'Web search completed.',
'role': 'tool',
'sender': None,
'tool_calls': None,
'tool_call_id': call_id,
'tool_name': 'web_search',
'response_type': 'internal'
}
messages.append(tool_call_output_dummy_msg)
# Handle run item web search events
elif event.type == "run_item_stream_event":
if event.item.type == "tool_call_item":
try:
# Check if it's a web search call
if hasattr(event.item.raw_item, 'type') and event.item.raw_item.type == 'web_search_call':
call_id = event.item.raw_item.id if hasattr(event.item.raw_item, 'id') else str(uuid.uuid4())
tool_call_msg = {
'content': None,
'role': 'assistant',
'sender': current_agent.name if current_agent else None,
'tool_calls': [{
'function': {
'name': 'web_search',
'arguments': json.dumps({
'search_id': call_id
})
},
'id': call_id,
'type': 'function'
}],
'tool_call_id': None,
'tool_name': None,
'response_type': 'internal'
}
print(f"Condition for tool call matched in run_item_stream_event. Appending tool call message: {tool_call_msg}")
messages.append(tool_call_msg)
tool_call_output_dummy_msg = {
'content': 'Web search completed.',
'role': 'tool',
'sender': None,
'tool_calls': None,
'tool_call_id': call_id,
'tool_name': 'web_search',
'response_type': 'internal'
}
messages.append(tool_call_output_dummy_msg)
else:
# Handle regular tool calls
tool_call_msg = {
'content': None,
'role': 'assistant',
'sender': current_agent.name if current_agent else None,
'tool_calls': [{
'function': {
'name': event.item.raw_item.name,
'arguments': event.item.raw_item.arguments
},
'id': event.item.raw_item.call_id,
'type': 'function'
}],
'tool_call_id': None,
'tool_name': None,
'response_type': 'internal'
}
print(f"Condition for tool call matched in run_item_stream_event. Appending tool call message: {tool_call_msg}")
messages.append(tool_call_msg)
tool_call_output_dummy_msg = {
'content': 'Web search completed.',
'role': 'tool',
'sender': None,
'tool_calls': None,
'tool_call_id': call_id,
'tool_name': 'web_search',
'response_type': 'internal'
}
messages.append(tool_call_output_dummy_msg)
except Exception as e:
print("\n=== Error in tool_call_item handling ===")
print(f"Error: {str(e)}")
print(f"Event type: {event.type}")
print(f"Event item type: {event.item.type}")
print("Event details:")
print(f"Raw item: {event.item.raw_item}")
if hasattr(event.item.raw_item, '__dict__'):
print(f"Raw item attributes: {event.item.raw_item.__dict__}")
print(f"Traceback: {traceback.format_exc()}")
print("=" * 50)
raise
elif event.item.type == "tool_call_output_item":
if isinstance(event.item.raw_item, dict) and event.item.raw_item.get('type') == 'web_search_results':
call_id = event.item.raw_item.get('search_id', event.item.raw_item.get('id', str(uuid.uuid4())))
tool_call_output_msg = {
'content': str(event.item.output),
'role': 'tool',
'sender': None,
'tool_calls': None,
'tool_call_id': call_id,
'tool_name': 'web_search',
'response_type': 'internal'
}
print(f"Condition for tool call output matched in run_item_stream_event. Appending tool call output message: {tool_call_output_msg}")
messages.append(tool_call_output_msg)
elif event.item.type == "web_search_call_item" or (
hasattr(event.item, 'raw_item') and
hasattr(event.item.raw_item, 'type') and
event.item.raw_item.type == 'web_search_call'
):
call_id = None
if hasattr(raw_item, 'id'):
call_id = raw_item.id
elif isinstance(raw_item, dict) and 'id' in raw_item:
call_id = raw_item['id']
else:
call_id = str(uuid.uuid4())
status = 'unknown'
if hasattr(raw_item, 'status'):
status = raw_item.status
elif isinstance(raw_item, dict) and 'status' in raw_item:
status = raw_item['status']
messages.append({
'content': None,
'role': 'assistant',
'sender': current_agent.name if current_agent else None,
'tool_calls': [{
'function': {
'name': 'web_search',
'arguments': json.dumps({
'search_id': call_id,
'status': status
})
},
'id': call_id,
'type': 'function'
}],
'tool_call_id': None,
'tool_name': None,
'response_type': 'internal'
})
# Handle run item web search events
elif event.type == "run_item_stream_event":
if event.item.type == "tool_call_item":
if hasattr(event.item.raw_item, 'type') and event.item.raw_item.type == 'web_search_call':
call_id = event.item.raw_item.id if hasattr(event.item.raw_item, 'id') else str(uuid.uuid4())
messages.append({
if hasattr(event.item.raw_item, 'id'):
call_id = event.item.raw_item.id
tool_call_msg = {
'content': None,
'role': 'assistant',
'sender': current_agent.name if current_agent else None,
@ -65,107 +179,90 @@ def handle_web_search_event(event, current_agent):
'search_id': call_id
})
},
'id': call_id,
'id': call_id or str(uuid.uuid4()),
'type': 'function'
}],
'tool_call_id': None,
'tool_name': None,
'response_type': 'internal'
})
messages.append({
'content': "Web search done",
}
print(f"Condition for tool call matched in run_item_stream_event. Appending tool call message: {tool_call_msg}")
messages.append(tool_call_msg)
tool_call_output_dummy_msg = {
'content': 'Web search completed.',
'role': 'tool',
'sender': None,
'tool_calls': None,
'tool_call_id': call_id,
'tool_name': 'web_search',
'response_type': 'internal'
})
}
messages.append(tool_call_output_dummy_msg)
elif event.item.type == "tool_call_output_item":
if isinstance(event.item.raw_item, dict) and event.item.raw_item.get('type') == 'web_search_results':
call_id = event.item.raw_item.get('search_id', event.item.raw_item.get('id', str(uuid.uuid4())))
messages.append({
'content': str(event.item.output),
elif event.item.type == "web_search_results_item" or (
hasattr(event.item, 'raw_item') and (
(hasattr(event.item.raw_item, 'type') and event.item.raw_item.type == 'web_search_results') or
(isinstance(event.item.raw_item, dict) and event.item.raw_item.get('type') == 'web_search_results')
)
):
raw_item = event.item.raw_item
call_id = None
if hasattr(raw_item, 'search_id'):
call_id = raw_item.search_id
elif isinstance(raw_item, dict) and 'search_id' in raw_item:
call_id = raw_item['search_id']
elif hasattr(raw_item, 'id'):
call_id = raw_item.id
elif isinstance(raw_item, dict) and 'id' in raw_item:
call_id = raw_item['id']
else:
call_id = str(uuid.uuid4())
results = {}
if hasattr(event.item, 'output'):
results = event.item.output
elif hasattr(raw_item, 'results'):
results = raw_item.results
elif isinstance(raw_item, dict) and 'results' in raw_item:
results = raw_item['results']
results_str = ""
try:
results_str = json.dumps(results) if results else ""
except Exception as e:
print(f"Error serializing results: {str(e)}")
results_str = str(results)
tool_call_output_msg = {
'content': results_str,
'role': 'tool',
'sender': None,
'tool_calls': None,
'tool_call_id': call_id,
'tool_name': 'web_search',
'response_type': 'internal'
})
}
print(f"Condition for tool call output matched in run_item_stream_event. Appending tool call output message: {tool_call_output_msg}")
messages.append(tool_call_output_msg)
elif event.item.type == "web_search_call_item" or (
hasattr(event.item, 'raw_item') and
hasattr(event.item.raw_item, 'type') and
event.item.raw_item.type == 'web_search_call'
):
call_id = None
if hasattr(event.item.raw_item, 'id'):
call_id = event.item.raw_item.id
except Exception as e:
print("\n=== Error in handle_web_search_event ===")
print(f"Error: {str(e)}")
print(f"Event type: {event.type}")
if hasattr(event, 'item'):
print(f"Event item type: {event.item.type}")
print("Event item details:")
print(f"Raw item: {event.item.raw_item}")
if hasattr(event.item.raw_item, '__dict__'):
print(f"Raw item attributes: {event.item.raw_item.__dict__}")
print(f"Traceback: {traceback.format_exc()}")
print("=" * 50)
raise
messages.append({
'content': None,
'role': 'assistant',
'sender': current_agent.name if current_agent else None,
'tool_calls': [{
'function': {
'name': 'web_search',
'arguments': json.dumps({
'search_id': call_id
})
},
'id': call_id or str(uuid.uuid4()),
'type': 'function'
}],
'tool_call_id': None,
'tool_name': None,
'response_type': 'internal'
})
elif event.item.type == "web_search_results_item" or (
hasattr(event.item, 'raw_item') and (
(hasattr(event.item.raw_item, 'type') and event.item.raw_item.type == 'web_search_results') or
(isinstance(event.item.raw_item, dict) and event.item.raw_item.get('type') == 'web_search_results')
)
):
raw_item = event.item.raw_item
call_id = None
if hasattr(raw_item, 'search_id'):
call_id = raw_item.search_id
elif isinstance(raw_item, dict) and 'search_id' in raw_item:
call_id = raw_item['search_id']
elif hasattr(raw_item, 'id'):
call_id = raw_item.id
elif isinstance(raw_item, dict) and 'id' in raw_item:
call_id = raw_item['id']
else:
call_id = str(uuid.uuid4())
results = {}
if hasattr(event.item, 'output'):
results = event.item.output
elif hasattr(raw_item, 'results'):
results = raw_item.results
elif isinstance(raw_item, dict) and 'results' in raw_item:
results = raw_item['results']
results_str = ""
try:
results_str = json.dumps(results) if results else ""
except Exception as e:
print(f"Error serializing results: {str(e)}")
results_str = str(results)
messages.append({
'content': results_str,
'role': 'tool',
'sender': None,
'tool_calls': None,
'tool_call_id': call_id,
'tool_name': 'web_search',
'response_type': 'internal'
})
if messages:
print("-"*100)
print(f"Web search related messages: {messages}")
print("-"*100)
return messages