1313from agent_control_models .errors import ErrorCode , ValidationErrorItem
1414from fastapi import APIRouter , Depends , Request
1515from sqlalchemy import select
16- from sqlalchemy .ext .asyncio import AsyncSession
1716
1817from ..auth_framework import Operation , Principal , require_operation
19- from ..db import get_async_db
18+ from ..db import AsyncSessionLocal
2019from ..errors import APIValidationError , NotFoundError
2120from ..logging_utils import get_logger
2221from ..models import Agent
@@ -136,6 +135,41 @@ async def _evaluation_context(request: Request) -> dict[str, object]:
136135 return {"target_type" : target_type , "target_id" : target_id }
137136
138137
138+ async def _load_engine_controls (
139+ request : EvaluationRequest ,
140+ principal : Principal ,
141+ ) -> list [ControlAdapter ]:
142+ """Load and materialize controls before evaluator execution starts."""
143+ namespace_key = principal .namespace_key
144+
145+ async with AsyncSessionLocal () as db :
146+ agent_result = await db .execute (
147+ select (Agent ).where (
148+ Agent .name == request .agent_name ,
149+ Agent .namespace_key == namespace_key ,
150+ )
151+ )
152+ agent = agent_result .scalar_one_or_none ()
153+ if agent is None :
154+ raise NotFoundError (
155+ error_code = ErrorCode .AGENT_NOT_FOUND ,
156+ detail = f"Agent '{ request .agent_name } ' not found" ,
157+ resource = "Agent" ,
158+ resource_id = request .agent_name ,
159+ hint = "Register the agent via initAgent before evaluating." ,
160+ )
161+
162+ runtime_controls = await ControlService (db ).list_runtime_controls_for_agent (
163+ request .agent_name ,
164+ namespace_key = namespace_key ,
165+ target_type = request .target_type ,
166+ target_id = request .target_id ,
167+ allow_invalid_step_name_regex = True ,
168+ )
169+
170+ return [ControlAdapter (c .id , c .name , c .control ) for c in runtime_controls ]
171+
172+
139173@router .post (
140174 "" ,
141175 response_model = EvaluationResponse ,
@@ -144,7 +178,6 @@ async def _evaluation_context(request: Request) -> dict[str, object]:
144178)
145179async def evaluate (
146180 request : EvaluationRequest ,
147- db : AsyncSession = Depends (get_async_db ),
148181 principal : Principal = Depends (
149182 require_operation (Operation .RUNTIME_USE , context_builder = _evaluation_context )
150183 ),
@@ -163,34 +196,7 @@ async def evaluate(
163196 on the server; SDKs reconstruct and emit those events separately through
164197 the observability ingestion endpoint.
165198 """
166- namespace_key = principal .namespace_key
167-
168- agent_result = await db .execute (
169- select (Agent ).where (
170- Agent .name == request .agent_name ,
171- Agent .namespace_key == namespace_key ,
172- )
173- )
174- agent = agent_result .scalar_one_or_none ()
175- if agent is None :
176- raise NotFoundError (
177- error_code = ErrorCode .AGENT_NOT_FOUND ,
178- detail = f"Agent '{ request .agent_name } ' not found" ,
179- resource = "Agent" ,
180- resource_id = request .agent_name ,
181- hint = "Register the agent via initAgent before evaluating." ,
182- )
183-
184- runtime_controls = await ControlService (db ).list_runtime_controls_for_agent (
185- request .agent_name ,
186- namespace_key = namespace_key ,
187- target_type = request .target_type ,
188- target_id = request .target_id ,
189- allow_invalid_step_name_regex = True ,
190- )
191-
192- engine_controls = [ControlAdapter (c .id , c .name , c .control ) for c in runtime_controls ]
193-
199+ engine_controls = await _load_engine_controls (request , principal )
194200 engine = ControlEngine (engine_controls )
195201 try :
196202 raw_response = await engine .process (request )
0 commit comments