@@ -63,7 +63,8 @@ def _send_job_enter(
6363 group : int ,
6464 api_key : str | None ,
6565 taskset : str | None = None ,
66- ) -> None :
66+ tasks : list [dict [str , Any ]] | None = None ,
67+ ) -> list [str ] | None :
6768 """Send job enter payload (sync request before traces start)."""
6869 import httpx
6970
@@ -72,24 +73,35 @@ def _send_job_enter(
7273
7374 api_key = api_key or settings .api_key
7475 if not settings .telemetry_enabled or not api_key :
75- return
76+ return None
7677
7778 payload = JobEnterPayload (
7879 name = name ,
7980 variants = variants ,
8081 group = group ,
8182 taskset = taskset ,
83+ tasks = tasks if taskset else None , # only send tasks if taskset specified
8284 )
8385
8486 try :
85- httpx .post (
87+ resp = httpx .post (
8688 f"{ settings .hud_api_url } /trace/job/{ job_id } /enter" ,
8789 json = payload .model_dump (exclude_none = True ),
8890 headers = {"Authorization" : f"Bearer { api_key } " },
8991 timeout = 10.0 ,
9092 )
93+ if resp .is_success :
94+ try :
95+ data = resp .json ()
96+ except Exception :
97+ return None
98+ if isinstance (data , dict ):
99+ ids = data .get ("task_version_ids" )
100+ if isinstance (ids , list ) and all (isinstance (x , str ) for x in ids ):
101+ return ids
91102 except Exception as e :
92103 logger .warning ("Failed to send job enter: %s" , e )
104+ return None
93105
94106
95107@asynccontextmanager
@@ -276,14 +288,33 @@ async def run_eval(
276288 job_url = f"https://hud.ai/jobs/{ implicit_job_id } "
277289
278290 # Send job enter (sync request before traces start)
279- _send_job_enter (
291+ # Serialize tasks for auto-add to taskset (only tasks without existing backend id).
292+ # For v5 scenario tasks, the backend task_version_id is carried in Task.id.
293+ tasks_data = None
294+ tasks_to_create : list [Task ] = []
295+ if taskset and tasks :
296+ tasks_to_create = [t for t in tasks if not t .id ]
297+ tasks_data = [
298+ t .model_dump (mode = "json" , exclude_none = True )
299+ for t in tasks
300+ if not t .id # skip tasks that already exist in platform
301+ ]
302+ created_task_version_ids = _send_job_enter (
280303 job_id = implicit_job_id ,
281304 name = eval_name ,
282305 variants = variants ,
283306 group = group ,
284307 api_key = api_key ,
285308 taskset = taskset ,
309+ tasks = tasks_data ,
286310 )
311+ if created_task_version_ids and tasks_to_create :
312+ # Assign backend IDs back onto the in-memory tasks so trace enter includes
313+ # task_version_id.
314+ for task_obj , task_version_id in zip (
315+ tasks_to_create , created_task_version_ids , strict = False
316+ ):
317+ task_obj .id = task_version_id
287318
288319 # Print job URL (not individual trace URLs)
289320 if not quiet :
0 commit comments