AlexTrinityBlock commited on
Commit
01faebd
·
1 Parent(s): c82d598

feat(agent): add file URL support to agent query handling

Browse files

Add optional `file_url` parameter to `run()` and `BasicAgent.__call__()` methods. When a task_id is available, construct and pass the file URL to the agent alongside the question text, allowing the supervisor to access attached files during processing.

Files changed (5) hide show
  1. .gitignore +2 -0
  2. agent/agent.py +10 -4
  3. agent/tools/file_downloader.py +34 -0
  4. app.py +6 -3
  5. workspace/README.md +1 -0
.gitignore CHANGED
@@ -1,3 +1,5 @@
1
  .env
2
  *.pyc
3
  __pycache__/
 
 
 
1
  .env
2
  *.pyc
3
  __pycache__/
4
+ workspace/*
5
+ !workspace/README.md
agent/agent.py CHANGED
@@ -4,6 +4,7 @@ from colorama import Fore, Style # type: ignore[import]
4
  from langchain.agents import create_agent
5
  from langchain_core.messages import HumanMessage
6
  from agent.tools.math_solver import math_solver
 
7
 
8
  from agent.agents.websearchagents import web_search_agents
9
 
@@ -18,7 +19,7 @@ def supervisor_agent():
18
  return create_agent(
19
  model="google_genai:gemini-3-flash-preview",
20
  # tools=[math_solver, websearch_agent, web_search_agents],
21
- tools=[math_solver, web_search_agents],
22
  system_prompt=(
23
  f"You are a supervisor agent. "
24
  f"Current time is: {datetime.now(timezone.utc).isoformat()}. "
@@ -34,18 +35,23 @@ def supervisor_agent():
34
  )
35
 
36
 
37
- def run(query: str, max_retries: int = 3) -> str:
38
  """Entry point: let the supervisor agent finish the work."""
39
  last_error: str | None = None
40
 
 
 
 
 
 
41
  for attempt in range(1, max_retries + 1):
42
  print(
43
  f"{Fore.CYAN}[Supervisor] Processing query (attempt {attempt}/{max_retries})...\n"
44
- f"[Supervisor] Query: {query}{Style.RESET_ALL}"
45
  )
46
  agent = supervisor_agent()
47
 
48
- messages = [HumanMessage(content=query)]
49
  if last_error:
50
  messages.append(
51
  HumanMessage(
 
4
  from langchain.agents import create_agent
5
  from langchain_core.messages import HumanMessage
6
  from agent.tools.math_solver import math_solver
7
+ from agent.tools.file_downloader import file_downloader
8
 
9
  from agent.agents.websearchagents import web_search_agents
10
 
 
19
  return create_agent(
20
  model="google_genai:gemini-3-flash-preview",
21
  # tools=[math_solver, websearch_agent, web_search_agents],
22
+ tools=[math_solver, web_search_agents, file_downloader],
23
  system_prompt=(
24
  f"You are a supervisor agent. "
25
  f"Current time is: {datetime.now(timezone.utc).isoformat()}. "
 
35
  )
36
 
37
 
38
+ def run(query: str, file_url: str | None = None, max_retries: int = 3) -> str:
39
  """Entry point: let the supervisor agent finish the work."""
40
  last_error: str | None = None
41
 
42
+ # Append file URL info to the query if available
43
+ full_query = query
44
+ if file_url:
45
+ full_query += f"\n\nAttached file URL: {file_url}"
46
+
47
  for attempt in range(1, max_retries + 1):
48
  print(
49
  f"{Fore.CYAN}[Supervisor] Processing query (attempt {attempt}/{max_retries})...\n"
50
+ f"[Supervisor] Query: {full_query}{Style.RESET_ALL}"
51
  )
52
  agent = supervisor_agent()
53
 
54
+ messages = [HumanMessage(content=full_query)]
55
  if last_error:
56
  messages.append(
57
  HumanMessage(
agent/tools/file_downloader.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from pathlib import Path
3
+
4
+ import httpx
5
+ from colorama import Fore, Style # type: ignore[import]
6
+ from langchain_core.tools import tool
7
+
8
+ WORKSPACE_DIR = Path(__file__).resolve().parents[2] / "workspace"
9
+
10
+
11
+ @tool
12
+ def file_downloader(url: str) -> str:
13
+ """Download a file from a URL and save it to the workspace directory.
14
+
15
+ Args:
16
+ url: The URL of the file to download.
17
+
18
+ Returns:
19
+ The local file path of the downloaded file, or an error message.
20
+ """
21
+ try:
22
+ filename = url.rstrip("/").split("/")[-1].split("?")[0] or "downloaded_file"
23
+ dest = WORKSPACE_DIR / filename
24
+
25
+ with httpx.stream("GET", url, follow_redirects=True, timeout=60) as r:
26
+ r.raise_for_status()
27
+ with open(dest, "wb") as f:
28
+ for chunk in r.iter_bytes():
29
+ f.write(chunk)
30
+
31
+ print(f"{Fore.GREEN}[FileDownloader] Saved: {dest}{Style.RESET_ALL}")
32
+ return str(dest)
33
+ except Exception as e:
34
+ return f"Error downloading file: {e}"
app.py CHANGED
@@ -16,9 +16,11 @@ class BasicAgent:
16
  def __init__(self):
17
  print("BasicAgent initialized.")
18
 
19
- def __call__(self, question: str) -> str:
20
  print(f"Agent received question (first 50 chars): {question[:50]}...")
21
- answer = agent_run(question)
 
 
22
  print(f"Agent returning answer (first 50 chars): {answer[:50]}...")
23
  return answer
24
 
@@ -83,8 +85,9 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
83
  if not task_id or question_text is None:
84
  print(f"Skipping item with missing task_id or question: {item}")
85
  continue
 
86
  try:
87
- submitted_answer = agent(question_text)
88
  answers_payload.append(
89
  {"task_id": task_id, "submitted_answer": submitted_answer}
90
  )
 
16
  def __init__(self):
17
  print("BasicAgent initialized.")
18
 
19
+ def __call__(self, question: str, file_url: str | None = None) -> str:
20
  print(f"Agent received question (first 50 chars): {question[:50]}...")
21
+ if file_url:
22
+ print(f"Agent received file URL: {file_url}")
23
+ answer = agent_run(question, file_url=file_url)
24
  print(f"Agent returning answer (first 50 chars): {answer[:50]}...")
25
  return answer
26
 
 
85
  if not task_id or question_text is None:
86
  print(f"Skipping item with missing task_id or question: {item}")
87
  continue
88
+ file_url = f"{api_url}/files/{task_id}"
89
  try:
90
+ submitted_answer = agent(question_text, file_url=file_url)
91
  answers_payload.append(
92
  {"task_id": task_id, "submitted_answer": submitted_answer}
93
  )
workspace/README.md ADDED
@@ -0,0 +1 @@
 
 
1
+ Workspace directory for downloaded files.