lockin-ai / app /agent /handler.py
MarcHabib's picture
fix: fixed variable intent synthax
c5ab8f7
Raw
History Blame Contribute Delete
5.17 kB
"""
Agent handler for LockIn AI.
Main entry point for agent execution - the run_agent_handler() function.
"""
import time
import uuid
from typing import Dict, Any
from app.agent.intent_router import intent_router
from app.agent.agent_service import agent_service
from app.guardrails import input_guardrails, profile_guardrails, output_guardrails
from app.services.profile_service import profile_service
from app.models.enums import RequestStatus, Intent
from app.schemas.chat import ChatResponse
def run_agent_handler(user_id: str, message: str) -> ChatResponse:
"""
Main handler function for agent execution.
This is the required handler function that orchestrates the entire
agent pipeline from input validation to response generation.
Args:
user_id: User identifier
message: User message
Returns:
ChatResponse with result or error
"""
start_time = time.time()
request_id = f"req_{uuid.uuid4().hex[:12]}"
# Step 1: Input Guardrails
is_valid, guardrail_code, user_message = input_guardrails.validate(message)
if not is_valid:
latency_ms = int((time.time() - start_time) * 1000)
return ChatResponse(
request_id=request_id,
status=RequestStatus.BLOCKED,
response=user_message,
guardrail_triggered=guardrail_code,
latency_ms=latency_ms
)
# Step 2: Profile Guardrails
profile, missing_fields = profile_guardrails.get_profile_or_error(user_id)
if not profile:
latency_ms = int((time.time() - start_time) * 1000)
return ChatResponse(
request_id=request_id,
status=RequestStatus.PROFILE_REQUIRED,
missing_fields=missing_fields,
latency_ms=latency_ms
)
# Step 3: Intent Classification
intent = intent_router.classify(message)
# Step 4: Agent Execution
try:
agent_result = agent_service.run(
message=message,
profile=profile,
intent=intent,
user_id=user_id
)
# Check if agent returned an error
if agent_result.get('error'):
latency_ms = int((time.time() - start_time) * 1000)
return ChatResponse(
request_id=request_id,
status=RequestStatus.ERROR,
response=agent_result.get('response', 'An error occurred'),
latency_ms=latency_ms
)
response_text = agent_result.get('response', '')
tool_calls = agent_result.get('tool_calls', [])
tool_results = agent_result.get('tool_results', [])
# Step 5: Output Guardrails
is_valid_output, output_error = output_guardrails.validate(
response=response_text,
tool_results=tool_results,
intent=intent,
allow_profile_numbers=profile is not None
)
if not is_valid_output:
latency_ms = int((time.time() - start_time) * 1000)
return ChatResponse(
request_id=request_id,
status=RequestStatus.BLOCKED,
response="I can't provide unsafe or medical advice.",
guardrail_triggered="output_validation_failed",
latency_ms=latency_ms
)
# Clean response to remove internal reflection text
cleaned_response = output_guardrails.clean_response(response_text)
# Extract structured data from tool results for meal plans
structured_data = None
if intent == Intent.MEAL_PLAN and tool_results:
for result in tool_results:
if result.get('tool_name') == 'daily_planner' and result.get('success'):
structured_data = result.get('result')
break
# Step 6: Build Response
latency_ms = int((time.time() - start_time) * 1000)
return ChatResponse(
request_id=request_id,
status=RequestStatus.SUCCESS,
intent=intent,
response=cleaned_response,
data=structured_data,
latency_ms=latency_ms,
tool_calls=tool_calls if tool_calls else None
)
except Exception as e:
latency_ms = int((time.time() - start_time) * 1000)
return ChatResponse(
request_id=request_id,
status=RequestStatus.ERROR,
response=f"An error occurred: {str(e)}",
latency_ms=latency_ms
)
def get_handler_metadata() -> Dict[str, Any]:
"""
Get metadata about the handler.
Returns:
Dict with handler information
"""
return {
'handler_name': 'run_agent_handler',
'version': '1.0.0',
'description': 'Main agent execution handler with full pipeline',
'pipeline_steps': [
'Input Guardrails',
'Profile Guardrails',
'Intent Classification',
'Agent Execution',
'Output Guardrails',
'Response Building'
]
}