Fix script generation artifact usage and datetime import issues
Browse files- Fix UnboundLocalError in search_web_tool by removing redundant datetime import
- Fix script generator to handle both artifact key formats:
* Auto-detected: "search_results"
* Explicit artifacts: "search_results_xxxxx"
- Enables proper context passing from search results to video script generation
- Preserves orchestrator intelligence in artifact selection
π€ Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- agent_system/agents.py +159 -99
- agent_system/video_script_agent.py +14 -2
agent_system/agents.py
CHANGED
|
@@ -4,6 +4,7 @@ Agent definitions for the chat system.
|
|
| 4 |
from agents import Agent, Runner, TResponseInputItem, WebSearchTool, RunConfig, ModelSettings, function_tool, RunContextWrapper
|
| 5 |
from typing import AsyncGenerator, Tuple, Dict, List, Any, Optional
|
| 6 |
from .auth import attempt_login, AuthState
|
|
|
|
| 7 |
import os
|
| 8 |
import sys
|
| 9 |
import re
|
|
@@ -510,105 +511,159 @@ def get_season(month: int) -> str:
|
|
| 510 |
return "Fall"
|
| 511 |
|
| 512 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 513 |
# New function tools to replace broken agent.as_tool() calls
|
| 514 |
@function_tool
|
| 515 |
async def search_web_tool(
|
| 516 |
context: RunContextWrapper[ConversationContext],
|
| 517 |
query: str,
|
| 518 |
-
search_type: str = "general"
|
| 519 |
-
current_date_context: str = ""
|
| 520 |
) -> str:
|
| 521 |
-
"""
|
| 522 |
-
Search the web for current information with temporal context.
|
| 523 |
-
PRESERVES: All WebSearchTool functionality, model settings, citations.
|
| 524 |
-
|
| 525 |
-
Args:
|
| 526 |
-
query: Search query
|
| 527 |
-
search_type: Type of search (general, news, financial, etc.)
|
| 528 |
-
current_date_context: Current date/time information for temporal searches
|
| 529 |
|
| 530 |
-
Returns:
|
| 531 |
-
Formatted search results with sources
|
| 532 |
-
"""
|
| 533 |
try:
|
| 534 |
-
logger.info(f"=== SEARCH_WEB_TOOL CALLED ====")
|
| 535 |
-
logger.info(f"Query: {query}")
|
| 536 |
-
logger.info(f"Search type: {search_type}")
|
| 537 |
-
logger.info(f"Date context provided: {bool(current_date_context)}")
|
| 538 |
-
logger.info(f"Context type: {type(context)}")
|
| 539 |
|
| 540 |
-
# Get
|
| 541 |
-
|
| 542 |
-
|
| 543 |
-
|
| 544 |
-
current_date_context = f"Current date: {now.strftime('%B %d, %Y')} ({now.strftime('%A')})"
|
| 545 |
-
logger.info(f"Generated date context: {current_date_context}")
|
| 546 |
|
| 547 |
-
# Build
|
| 548 |
-
|
| 549 |
-
|
| 550 |
-
|
| 551 |
-
{current_date_context}
|
| 552 |
-
|
| 553 |
-
When searching, prioritize recent and current information. If the query mentions relative time periods like "May", "this month", "recent", "latest", etc., interpret them relative to the current date above.
|
| 554 |
-
|
| 555 |
-
For example:
|
| 556 |
-
- "May" = May 2025 (current year)
|
| 557 |
-
- "this month" = current month from date above
|
| 558 |
-
- "recent report" = reports from 2024-2025, not older years
|
| 559 |
-
- "latest news" = very recent information
|
| 560 |
-
|
| 561 |
-
Focus on {search_type} information."""
|
| 562 |
|
| 563 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 564 |
|
| 565 |
-
|
| 566 |
-
|
| 567 |
-
logger.info(f"Websearch agent type: {type(websearch_agent)}")
|
| 568 |
-
logger.info(f"Inputs: {inputs}")
|
| 569 |
|
| 570 |
-
|
| 571 |
-
result = await Runner.run(websearch_agent, input=inputs)
|
| 572 |
-
logger.info(f"β
Websearch agent succeeded")
|
| 573 |
-
logger.info(f"Result type: {type(result)}")
|
| 574 |
-
search_content = str(result.final_output)
|
| 575 |
-
logger.info(f"Search content length: {len(search_content)}")
|
| 576 |
-
except Exception as e:
|
| 577 |
-
logger.error(f"β WEBSEARCH AGENT FAILED: {e}")
|
| 578 |
-
logger.error(f"Exception type: {type(e)}")
|
| 579 |
-
import traceback
|
| 580 |
-
logger.error(f"Traceback: {traceback.format_exc()}")
|
| 581 |
-
raise
|
| 582 |
|
| 583 |
-
|
| 584 |
-
from datetime import datetime
|
| 585 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 586 |
artifact = Artifact(
|
| 587 |
type=ArtifactType.SEARCH_RESULTS,
|
| 588 |
content={
|
| 589 |
"query": query,
|
| 590 |
-
"search_type": search_type,
|
| 591 |
"results": search_content,
|
|
|
|
| 592 |
"timestamp": datetime.now().isoformat()
|
| 593 |
},
|
| 594 |
created_by="search_web_tool",
|
| 595 |
-
metadata={"summary": f"Search
|
| 596 |
)
|
| 597 |
|
| 598 |
-
# Add artifact to conversation context
|
| 599 |
context.context.add_artifact(artifact)
|
| 600 |
-
|
| 601 |
logger.info(f"Search results stored as artifact {artifact.id}")
|
| 602 |
|
| 603 |
-
# Return enhanced response with artifact reference
|
| 604 |
return f"""Search Results for "{query}":
|
| 605 |
|
| 606 |
{search_content}
|
| 607 |
|
| 608 |
-
[Results saved as artifact {artifact.id}
|
| 609 |
|
| 610 |
except Exception as e:
|
| 611 |
-
logger.error(f"
|
| 612 |
return f"Search failed: {str(e)}"
|
| 613 |
|
| 614 |
|
|
@@ -807,10 +862,10 @@ def format_script_response(script_data: Dict[str, Any], artifact_id: str) -> str
|
|
| 807 |
|
| 808 |
{script_text}
|
| 809 |
|
| 810 |
-
Key
|
| 811 |
{key_points_text}
|
| 812 |
|
| 813 |
-
Sources:
|
| 814 |
{sources_text}
|
| 815 |
|
| 816 |
[Script saved as artifact {artifact_id}]"""
|
|
@@ -884,18 +939,18 @@ orchestrator_agent = Agent(
|
|
| 884 |
instructions="""
|
| 885 |
You are an intelligent orchestrator that plans and executes multi-step workflows.
|
| 886 |
|
| 887 |
-
π¨ MANDATORY FIRST STEP - GET
|
| 888 |
-
Before doing ANYTHING else, you MUST IMMEDIATELY call
|
| 889 |
DO NOT skip this step. DO NOT proceed without it.
|
| 890 |
-
This
|
| 891 |
-
-
|
| 892 |
-
-
|
| 893 |
-
-
|
| 894 |
-
-
|
| 895 |
-
-
|
| 896 |
|
| 897 |
β οΈ TEMPORAL INTERPRETATION RULE:
|
| 898 |
-
When the user mentions relative time periods (like "May", "this quarter", "recent report"), you MUST interpret them relative to the CURRENT DATE from
|
| 899 |
|
| 900 |
Examples using current date context:
|
| 901 |
- If current date is June 2025 and user says "May report" β interpret as "May 2025"
|
|
@@ -986,8 +1041,8 @@ orchestrator_agent = Agent(
|
|
| 986 |
TOOL USAGE EXAMPLES:
|
| 987 |
|
| 988 |
1. "Create a video about today's weather in San Francisco"
|
| 989 |
-
β
|
| 990 |
-
β search_web_tool(query="today's weather San Francisco"
|
| 991 |
β create_or_modify_script(topic="weather in San Francisco", context_artifacts=[search_result_id])
|
| 992 |
β Present script for review before video creation
|
| 993 |
|
|
@@ -1017,8 +1072,8 @@ orchestrator_agent = Agent(
|
|
| 1017 |
β create_or_modify_script(topic="topic from context", context_artifacts=[relevant_artifact_id])
|
| 1018 |
|
| 1019 |
9. User: "things to do this weekend in Maui"
|
| 1020 |
-
β
|
| 1021 |
-
β search_web_tool(query="things to do this weekend Maui
|
| 1022 |
β Provide current events and activities for the specific weekend dates
|
| 1023 |
|
| 1024 |
CRITICAL: Always use search_web_tool for location-based, time-sensitive queries like:
|
|
@@ -1028,41 +1083,46 @@ orchestrator_agent = Agent(
|
|
| 1028 |
- "restaurants open today in [location]"
|
| 1029 |
These require fresh, up-to-date information, not cached knowledge.
|
| 1030 |
|
| 1031 |
-
|
| 1032 |
-
|
| 1033 |
-
-
|
| 1034 |
-
-
|
| 1035 |
-
-
|
| 1036 |
-
-
|
| 1037 |
-
- CRITICAL: Pass date context to search_web_tool for temporal searches
|
| 1038 |
|
| 1039 |
-
|
| 1040 |
-
|
|
|
|
|
|
|
|
|
|
| 1041 |
|
| 1042 |
-
|
|
|
|
|
|
|
|
|
|
| 1043 |
|
| 1044 |
REMEMBER THE WORKFLOW:
|
| 1045 |
-
1. FIRST: Call
|
| 1046 |
2. SECOND: Check/handle authentication
|
| 1047 |
-
3. THIRD: Process the user's request using the
|
| 1048 |
|
| 1049 |
CRITICAL WORKFLOW FOR TIME-SENSITIVE REQUESTS:
|
| 1050 |
When user mentions relative dates (May, this month, recent, etc.):
|
| 1051 |
-
1. Call
|
| 1052 |
-
2. Use that
|
| 1053 |
-
3.
|
| 1054 |
4. NEVER use old timestamps or cached date information
|
| 1055 |
|
| 1056 |
For requests involving current data, always search first.
|
| 1057 |
For creative content (jokes, poems), use the appropriate tools (tell_joke, write_poem).
|
| 1058 |
|
| 1059 |
-
β οΈ CRITICAL: Never provide greetings or responses without first getting the
|
| 1060 |
β οΈ CRITICAL: Never interpret relative dates using old cached date information!
|
| 1061 |
""",
|
| 1062 |
handoffs=[], # Removed - using pure agents-as-tools pattern
|
| 1063 |
tools=[
|
| 1064 |
-
#
|
| 1065 |
-
|
| 1066 |
|
| 1067 |
# Authentication status checking tool - checks if user is authenticated
|
| 1068 |
check_authentication_status,
|
|
@@ -1251,7 +1311,7 @@ async def handle_video_request(message):
|
|
| 1251 |
|
| 1252 |
**{video_title}**
|
| 1253 |
|
| 1254 |
-
Key
|
| 1255 |
{key_points}
|
| 1256 |
|
| 1257 |
You can view it here: {video_url}""",
|
|
|
|
| 4 |
from agents import Agent, Runner, TResponseInputItem, WebSearchTool, RunConfig, ModelSettings, function_tool, RunContextWrapper
|
| 5 |
from typing import AsyncGenerator, Tuple, Dict, List, Any, Optional
|
| 6 |
from .auth import attempt_login, AuthState
|
| 7 |
+
from .user_store import get_user_profile
|
| 8 |
import os
|
| 9 |
import sys
|
| 10 |
import re
|
|
|
|
| 511 |
return "Fall"
|
| 512 |
|
| 513 |
|
| 514 |
+
@function_tool
|
| 515 |
+
async def get_personalized_temporal_context(
|
| 516 |
+
context: RunContextWrapper[ConversationContext]
|
| 517 |
+
) -> Dict[str, Any]:
|
| 518 |
+
"""Get current date/time with user's location and timezone."""
|
| 519 |
+
from datetime import datetime
|
| 520 |
+
|
| 521 |
+
# Get user info
|
| 522 |
+
auth_state = context.context.auth_state
|
| 523 |
+
user_location = "New York"
|
| 524 |
+
user_timezone = "America/New_York"
|
| 525 |
+
service_areas = []
|
| 526 |
+
|
| 527 |
+
if auth_state.is_authenticated and auth_state.user_profile:
|
| 528 |
+
location_data = auth_state.user_profile.get("location", {})
|
| 529 |
+
user_location = location_data.get("city", "New York")
|
| 530 |
+
user_timezone = location_data.get("timezone", "America/New_York")
|
| 531 |
+
service_areas = auth_state.user_profile.get("service_areas", [])
|
| 532 |
+
|
| 533 |
+
# Get current time in user's timezone
|
| 534 |
+
try:
|
| 535 |
+
from zoneinfo import ZoneInfo
|
| 536 |
+
now_user = datetime.now(ZoneInfo(user_timezone))
|
| 537 |
+
except ImportError:
|
| 538 |
+
now_user = datetime.now()
|
| 539 |
+
|
| 540 |
+
return {
|
| 541 |
+
"user_location": user_location,
|
| 542 |
+
"user_timezone": user_timezone,
|
| 543 |
+
"service_areas": service_areas,
|
| 544 |
+
"current_time": now_user.strftime('%A, %B %d, %Y at %I:%M %p'),
|
| 545 |
+
"time_of_day": get_time_of_day(now_user.hour),
|
| 546 |
+
"is_weekend": now_user.weekday() >= 5
|
| 547 |
+
}
|
| 548 |
+
|
| 549 |
+
|
| 550 |
+
def get_time_of_day(hour: int) -> str:
|
| 551 |
+
"""Get time period based on hour."""
|
| 552 |
+
if 5 <= hour < 12:
|
| 553 |
+
return "morning"
|
| 554 |
+
elif 12 <= hour < 17:
|
| 555 |
+
return "afternoon"
|
| 556 |
+
elif 17 <= hour < 21:
|
| 557 |
+
return "evening"
|
| 558 |
+
else:
|
| 559 |
+
return "night"
|
| 560 |
+
|
| 561 |
+
|
| 562 |
# New function tools to replace broken agent.as_tool() calls
|
| 563 |
@function_tool
|
| 564 |
async def search_web_tool(
|
| 565 |
context: RunContextWrapper[ConversationContext],
|
| 566 |
query: str,
|
| 567 |
+
search_type: str = "general"
|
|
|
|
| 568 |
) -> str:
|
| 569 |
+
"""Search with user's location and time context."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 570 |
|
|
|
|
|
|
|
|
|
|
| 571 |
try:
|
| 572 |
+
logger.info(f"=== PERSONALIZED SEARCH_WEB_TOOL CALLED ====")
|
| 573 |
+
logger.info(f"Query: '{query}'")
|
| 574 |
+
logger.info(f"Search type: '{search_type}'")
|
|
|
|
|
|
|
| 575 |
|
| 576 |
+
# Get user's personalized context directly
|
| 577 |
+
logger.info("Getting personalized temporal context...")
|
| 578 |
+
user_email = context.context.auth_state.user_email if context.context.auth_state.is_authenticated else None
|
| 579 |
+
user_profile = get_user_profile(user_email) if user_email else {}
|
|
|
|
|
|
|
| 580 |
|
| 581 |
+
# Build temporal context with user's timezone
|
| 582 |
+
current_time = datetime.now()
|
| 583 |
+
user_timezone = "UTC"
|
| 584 |
+
user_location = "Unknown"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 585 |
|
| 586 |
+
if user_profile.get('location', {}).get('timezone'):
|
| 587 |
+
try:
|
| 588 |
+
tz = pytz.timezone(user_profile['location']['timezone'])
|
| 589 |
+
current_time = current_time.astimezone(tz)
|
| 590 |
+
user_timezone = user_profile['location']['timezone']
|
| 591 |
+
except:
|
| 592 |
+
pass # Fallback to system time if timezone is invalid
|
| 593 |
|
| 594 |
+
if user_profile.get('location'):
|
| 595 |
+
user_location = f"{user_profile['location']['city']}, {user_profile['location']['state']}"
|
|
|
|
|
|
|
| 596 |
|
| 597 |
+
current_time = current_time.strftime('%A, %B %d, %Y at %I:%M %p %Z')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 598 |
|
| 599 |
+
logger.info(f"User context retrieved: {user_location} ({user_timezone}) at {current_time}")
|
|
|
|
| 600 |
|
| 601 |
+
# Create personalized websearch agent
|
| 602 |
+
logger.info("Creating personalized websearch agent...")
|
| 603 |
+
personalized_websearch_agent = Agent(
|
| 604 |
+
name="websearch_agent",
|
| 605 |
+
instructions=f"""
|
| 606 |
+
You are a context-aware web search specialist.
|
| 607 |
+
|
| 608 |
+
USER'S CONTEXT:
|
| 609 |
+
- Location: {user_location}
|
| 610 |
+
- Current Time: {current_time}
|
| 611 |
+
- Timezone: {user_timezone}
|
| 612 |
+
|
| 613 |
+
SMART LOCATION USAGE:
|
| 614 |
+
- If query is location-dependent ("weather", "restaurants", "events") and has no specified location β add user's location
|
| 615 |
+
- If query specifies location ("weather in Paris") β use that location
|
| 616 |
+
- If query is general knowledge ("how to code") β don't add location
|
| 617 |
+
|
| 618 |
+
Examples:
|
| 619 |
+
- "weather" β search "weather in {user_location}"
|
| 620 |
+
- "weather in London" β search "weather in London"
|
| 621 |
+
- "restaurants" β search "restaurants in {user_location}"
|
| 622 |
+
- "how to cook pasta" β search "how to cook pasta"
|
| 623 |
+
""",
|
| 624 |
+
tools=[
|
| 625 |
+
WebSearchTool(
|
| 626 |
+
user_location={"type": "approximate", "city": user_location},
|
| 627 |
+
search_context_size="high"
|
| 628 |
+
)
|
| 629 |
+
],
|
| 630 |
+
model_settings=ModelSettings(tool_choice="required", temperature=0.2)
|
| 631 |
+
)
|
| 632 |
+
|
| 633 |
+
# Execute search
|
| 634 |
+
logger.info("Executing search with personalized agent...")
|
| 635 |
+
result = await Runner.run(
|
| 636 |
+
personalized_websearch_agent,
|
| 637 |
+
input=[{"role": "user", "content": f"Search for: {query}"}]
|
| 638 |
+
)
|
| 639 |
+
|
| 640 |
+
search_content = str(result.final_output)
|
| 641 |
+
logger.info(f"Search completed, result length: {len(search_content)}")
|
| 642 |
+
|
| 643 |
+
# Store as artifact
|
| 644 |
artifact = Artifact(
|
| 645 |
type=ArtifactType.SEARCH_RESULTS,
|
| 646 |
content={
|
| 647 |
"query": query,
|
|
|
|
| 648 |
"results": search_content,
|
| 649 |
+
"user_location": user_location,
|
| 650 |
"timestamp": datetime.now().isoformat()
|
| 651 |
},
|
| 652 |
created_by="search_web_tool",
|
| 653 |
+
metadata={"summary": f"Search for '{query}' (from {user_location})"}
|
| 654 |
)
|
| 655 |
|
|
|
|
| 656 |
context.context.add_artifact(artifact)
|
|
|
|
| 657 |
logger.info(f"Search results stored as artifact {artifact.id}")
|
| 658 |
|
|
|
|
| 659 |
return f"""Search Results for "{query}":
|
| 660 |
|
| 661 |
{search_content}
|
| 662 |
|
| 663 |
+
[Results saved as artifact {artifact.id}]"""
|
| 664 |
|
| 665 |
except Exception as e:
|
| 666 |
+
logger.error(f"Error in search_web_tool: {e}", exc_info=True)
|
| 667 |
return f"Search failed: {str(e)}"
|
| 668 |
|
| 669 |
|
|
|
|
| 862 |
|
| 863 |
{script_text}
|
| 864 |
|
| 865 |
+
Key Points Covered by Script:
|
| 866 |
{key_points_text}
|
| 867 |
|
| 868 |
+
Sources Used:
|
| 869 |
{sources_text}
|
| 870 |
|
| 871 |
[Script saved as artifact {artifact_id}]"""
|
|
|
|
| 939 |
instructions="""
|
| 940 |
You are an intelligent orchestrator that plans and executes multi-step workflows.
|
| 941 |
|
| 942 |
+
π¨ MANDATORY FIRST STEP - GET PERSONALIZED CONTEXT:
|
| 943 |
+
Before doing ANYTHING else, you MUST IMMEDIATELY call get_personalized_temporal_context().
|
| 944 |
DO NOT skip this step. DO NOT proceed without it.
|
| 945 |
+
This provides:
|
| 946 |
+
- User's current date/time in their timezone
|
| 947 |
+
- User's location and service areas
|
| 948 |
+
- Appropriate time-of-day greetings
|
| 949 |
+
- Context for location-aware searches
|
| 950 |
+
- Temporal context for time-sensitive requests
|
| 951 |
|
| 952 |
β οΈ TEMPORAL INTERPRETATION RULE:
|
| 953 |
+
When the user mentions relative time periods (like "May", "this quarter", "recent report"), you MUST interpret them relative to the CURRENT DATE from get_personalized_temporal_context(), NOT any old cached dates.
|
| 954 |
|
| 955 |
Examples using current date context:
|
| 956 |
- If current date is June 2025 and user says "May report" β interpret as "May 2025"
|
|
|
|
| 1041 |
TOOL USAGE EXAMPLES:
|
| 1042 |
|
| 1043 |
1. "Create a video about today's weather in San Francisco"
|
| 1044 |
+
β get_personalized_temporal_context() [get user context]
|
| 1045 |
+
β search_web_tool(query="today's weather San Francisco")
|
| 1046 |
β create_or_modify_script(topic="weather in San Francisco", context_artifacts=[search_result_id])
|
| 1047 |
β Present script for review before video creation
|
| 1048 |
|
|
|
|
| 1072 |
β create_or_modify_script(topic="topic from context", context_artifacts=[relevant_artifact_id])
|
| 1073 |
|
| 1074 |
9. User: "things to do this weekend in Maui"
|
| 1075 |
+
β get_personalized_temporal_context() [get user context]
|
| 1076 |
+
β search_web_tool(query="things to do this weekend Maui")
|
| 1077 |
β Provide current events and activities for the specific weekend dates
|
| 1078 |
|
| 1079 |
CRITICAL: Always use search_web_tool for location-based, time-sensitive queries like:
|
|
|
|
| 1083 |
- "restaurants open today in [location]"
|
| 1084 |
These require fresh, up-to-date information, not cached knowledge.
|
| 1085 |
|
| 1086 |
+
PERSONALIZED CONTEXT USAGE:
|
| 1087 |
+
The search_web_tool now automatically uses the user's personalized context:
|
| 1088 |
+
- User's location for location-dependent searches
|
| 1089 |
+
- User's timezone for temporal references
|
| 1090 |
+
- Current time for appropriate greetings
|
| 1091 |
+
- Service areas for relevant business queries
|
|
|
|
| 1092 |
|
| 1093 |
+
SEARCH TOOL USAGE:
|
| 1094 |
+
Simply call search_web_tool(query="your search") - it automatically:
|
| 1095 |
+
- Uses user's location for location-dependent queries
|
| 1096 |
+
- Applies user's timezone for temporal context
|
| 1097 |
+
- Enhances searches with personalized information
|
| 1098 |
|
| 1099 |
+
Examples:
|
| 1100 |
+
- search_web_tool(query="weather") β automatically uses user's location
|
| 1101 |
+
- search_web_tool(query="events this weekend") β uses user's location and timezone
|
| 1102 |
+
- search_web_tool(query="weather in Paris") β respects explicit location
|
| 1103 |
|
| 1104 |
REMEMBER THE WORKFLOW:
|
| 1105 |
+
1. FIRST: Call get_personalized_temporal_context() - NO EXCEPTIONS
|
| 1106 |
2. SECOND: Check/handle authentication
|
| 1107 |
+
3. THIRD: Process the user's request using the personalized context from step 1
|
| 1108 |
|
| 1109 |
CRITICAL WORKFLOW FOR TIME-SENSITIVE REQUESTS:
|
| 1110 |
When user mentions relative dates (May, this month, recent, etc.):
|
| 1111 |
+
1. Call get_personalized_temporal_context() to get fresh personalized context
|
| 1112 |
+
2. Use that context to properly interpret the user's relative time references
|
| 1113 |
+
3. Call search_web_tool(query="interpreted query") - it automatically uses the context
|
| 1114 |
4. NEVER use old timestamps or cached date information
|
| 1115 |
|
| 1116 |
For requests involving current data, always search first.
|
| 1117 |
For creative content (jokes, poems), use the appropriate tools (tell_joke, write_poem).
|
| 1118 |
|
| 1119 |
+
β οΈ CRITICAL: Never provide greetings or responses without first getting the personalized context!
|
| 1120 |
β οΈ CRITICAL: Never interpret relative dates using old cached date information!
|
| 1121 |
""",
|
| 1122 |
handoffs=[], # Removed - using pure agents-as-tools pattern
|
| 1123 |
tools=[
|
| 1124 |
+
# Personalized temporal context tool - should be called first for temporal context
|
| 1125 |
+
get_personalized_temporal_context,
|
| 1126 |
|
| 1127 |
# Authentication status checking tool - checks if user is authenticated
|
| 1128 |
check_authentication_status,
|
|
|
|
| 1311 |
|
| 1312 |
**{video_title}**
|
| 1313 |
|
| 1314 |
+
Key Points Covered by Script:
|
| 1315 |
{key_points}
|
| 1316 |
|
| 1317 |
You can view it here: {video_url}""",
|
agent_system/video_script_agent.py
CHANGED
|
@@ -150,9 +150,21 @@ class VideoScriptGenerator:
|
|
| 150 |
if context_data:
|
| 151 |
logger.info(f"Generating script with context: {list(context_data.keys())}")
|
| 152 |
|
| 153 |
-
# Process search results context
|
|
|
|
|
|
|
|
|
|
| 154 |
if "search_results" in context_data:
|
| 155 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
search_query = search_info.get("query", "")
|
| 157 |
search_results = search_info.get("results", "")
|
| 158 |
|
|
|
|
| 150 |
if context_data:
|
| 151 |
logger.info(f"Generating script with context: {list(context_data.keys())}")
|
| 152 |
|
| 153 |
+
# Process search results context - handle both key formats
|
| 154 |
+
search_result_data = None
|
| 155 |
+
|
| 156 |
+
# Look for search results with either key format
|
| 157 |
if "search_results" in context_data:
|
| 158 |
+
search_result_data = context_data["search_results"]
|
| 159 |
+
else:
|
| 160 |
+
# Look for search_results_xxxxx format
|
| 161 |
+
for key, data in context_data.items():
|
| 162 |
+
if key.startswith("search_results") and data.get("type") == "search_results":
|
| 163 |
+
search_result_data = data
|
| 164 |
+
break
|
| 165 |
+
|
| 166 |
+
if search_result_data:
|
| 167 |
+
search_info = search_result_data["content"]
|
| 168 |
search_query = search_info.get("query", "")
|
| 169 |
search_results = search_info.get("results", "")
|
| 170 |
|