@@ -158,11 +158,56 @@ def _build_agent_snapshot(self, agent: AgentDefinition) -> dict[str, Any]:
158158 "name" : agent .name ,
159159 "description" : agent .description ,
160160 "system_prompt" : agent .system_prompt ,
161+ "requires_input" : agent .requires_input ,
162+ "required_input_description" : agent .required_input_description ,
161163 "tool_names" : list (agent .tool_names ),
162164 "success_criteria" : [criteria .model_dump () for criteria in agent .success_criteria ],
163165 "captured_at" : datetime .now ().isoformat (),
164166 }
165167
168+ def _normalize_input_contract (
169+ self ,
170+ requires_input : bool ,
171+ required_input_description : str ,
172+ ) -> tuple [bool , str ]:
173+ normalized_description = (required_input_description or "" ).strip ()
174+ if requires_input and not normalized_description :
175+ raise ValueError (
176+ "required_input_description must be provided when requires_input is true"
177+ )
178+ if not requires_input :
179+ normalized_description = ""
180+ return requires_input , normalized_description
181+
182+ def _build_run_user_message (
183+ self ,
184+ agent_def : AgentDefinition ,
185+ run_request : AgentRunCreate ,
186+ ) -> tuple [str , str ]:
187+ run_prompt = (run_request .input_prompt or "" ).strip ()
188+ required_input_value = (run_request .required_input_value or "" ).strip ()
189+ message_parts : list [str ] = []
190+
191+ if run_prompt :
192+ message_parts .append (run_prompt )
193+
194+ if agent_def .requires_input :
195+ if not required_input_value :
196+ raise ValueError (
197+ "Missing required_input_value for this agent. "
198+ f"Expected: { agent_def .required_input_description } "
199+ )
200+ message_parts .append (
201+ f"Required input ({ agent_def .required_input_description } ): { required_input_value } "
202+ )
203+ elif required_input_value :
204+ message_parts .append (f"Additional input: { required_input_value } " )
205+
206+ if not message_parts :
207+ message_parts .append ("Proceed with the configured system instructions and tools." )
208+
209+ return "\n \n " .join (message_parts ), required_input_value
210+
166211 def _criteria_from_run_snapshot (self , run : AgentRun ) -> list [SuccessCriteria ]:
167212 snapshot = run .agent_snapshot
168213 raw = snapshot .get ("success_criteria" )
@@ -184,10 +229,16 @@ def _criteria_from_run_snapshot(self, run: AgentRun) -> list[SuccessCriteria]:
184229
185230 def create_agent (self , data : AgentDefinitionCreate ) -> AgentDefinition :
186231 validated_tool_names = self ._validate_tool_names (data .tool_names )
232+ requires_input , required_input_description = self ._normalize_input_contract (
233+ data .requires_input ,
234+ data .required_input_description ,
235+ )
187236 agent = AgentDefinition (
188237 name = data .name ,
189238 description = data .description ,
190239 system_prompt = data .system_prompt ,
240+ requires_input = requires_input ,
241+ required_input_description = required_input_description ,
191242 )
192243 agent .tool_names = validated_tool_names
193244 agent .success_criteria = data .success_criteria
@@ -218,6 +269,19 @@ def update_agent(
218269 agent .description = data .description
219270 if data .system_prompt is not None :
220271 agent .system_prompt = data .system_prompt
272+ next_requires_input = agent .requires_input if data .requires_input is None else data .requires_input
273+ next_required_input_description = (
274+ agent .required_input_description
275+ if data .required_input_description is None
276+ else data .required_input_description
277+ )
278+ (
279+ agent .requires_input ,
280+ agent .required_input_description ,
281+ ) = self ._normalize_input_contract (
282+ next_requires_input ,
283+ next_required_input_description ,
284+ )
221285 if data .tool_names is not None :
222286 agent .tool_names = self ._validate_tool_names (data .tool_names )
223287 if data .success_criteria is not None :
@@ -279,11 +343,16 @@ async def run_agent(
279343
280344 validated_tool_names = self ._validate_tool_names (agent_def .tool_names )
281345 agent_snapshot = self ._build_agent_snapshot (agent_def )
346+ user_message , normalized_required_input = self ._build_run_user_message (agent_def , run_request )
347+ normalized_prompt = (run_request .input_prompt or "" ).strip ()
348+ agent_snapshot ["input_prompt" ] = normalized_prompt
349+ agent_snapshot ["required_input_value" ] = normalized_required_input
350+ agent_snapshot ["composed_user_message" ] = user_message
282351
283352 # -- Persist a PENDING run --
284353 run = AgentRun (
285354 agent_id = agent_id ,
286- input_prompt = run_request . input_prompt ,
355+ input_prompt = normalized_prompt ,
287356 status = RunStatus .RUNNING .value ,
288357 )
289358 run .agent_snapshot = agent_snapshot
@@ -300,7 +369,7 @@ async def run_agent(
300369 react = _build_react_agent (self .llm , tools , agent_def .system_prompt )
301370
302371 result = await react .ainvoke (
303- {"messages" : [("user" , run_request . input_prompt )]},
372+ {"messages" : [("user" , user_message )]},
304373 config = {"recursion_limit" : self ._recursion_limit },
305374 )
306375
0 commit comments