diff --git a/README.md b/README.md index a1dc8ef..c5d9b77 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,7 @@ Access the UI at `http://localhost:5173` # TODO for this branch ## Agent - We'll have to figure out which matches are where. No use going to Manchester for a match that isn't there. +- The use of `###` in prompts I want excluded from the conversation history is a bit of a hack. ## Validator function - Probably keep data types, but move the activity and workflow code for the demo diff --git a/api/main.py b/api/main.py index 252b714..9dfff06 100644 --- a/api/main.py +++ b/api/main.py @@ -132,3 +132,26 @@ async def end_chat(): print(e) # Workflow not found; return an empty response return {} + + +@app.post("/start-workflow") +async def start_workflow(): + # Create combined input + combined_input = CombinedInput( + tool_params=ToolWorkflowParams(None, None), + agent_goal=goal_event_flight_invoice, + ) + + workflow_id = "agent-workflow" + + # Start the workflow with the starter prompt from the goal + await temporal_client.start_workflow( + ToolWorkflow.run, + combined_input, + id=workflow_id, + task_queue=TEMPORAL_TASK_QUEUE, + start_signal="user_prompt", + start_signal_args=["### " + goal_event_flight_invoice.starter_prompt], + ) + + return {"message": f"Workflow started with goal's starter prompt: {goal_event_flight_invoice.starter_prompt}."} diff --git a/frontend/src/pages/App.jsx b/frontend/src/pages/App.jsx index 94ef16a..4fde2ae 100644 --- a/frontend/src/pages/App.jsx +++ b/frontend/src/pages/App.jsx @@ -167,7 +167,7 @@ export default function App() { try { setError(INITIAL_ERROR_STATE); setLoading(true); - await apiService.sendMessage("I'd like to travel for an event."); + await apiService.startWorkflow(); setConversation([]); setLastMessage(null); } catch (err) { diff --git a/frontend/src/services/api.js b/frontend/src/services/api.js index af93d49..02bdd73 100644 --- a/frontend/src/services/api.js +++ b/frontend/src/services/api.js @@ -56,6 +56,26 @@ export const apiService = { } }, + async startWorkflow() { + try { + const res = await fetch( + `${API_BASE_URL}/start-workflow`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + } + } + ); + return handleResponse(res); + } catch (error) { + throw new ApiError( + 'Failed to start workflow', + error.status || 500 + ); + } + }, + async confirm() { try { const res = await fetch(`${API_BASE_URL}/confirm`, { diff --git a/models/tool_definitions.py b/models/tool_definitions.py index 6e711b5..d4b085f 100644 --- a/models/tool_definitions.py +++ b/models/tool_definitions.py @@ -20,6 +20,7 @@ class ToolDefinition: class AgentGoal: tools: List[ToolDefinition] description: str = "Description of the tools purpose and overall goal" + starter_prompt: str = "Initial prompt to start the conversation" example_conversation_history: str = ( "Example conversation history to help the AI agent understand the context of the conversation" ) diff --git a/tools/goal_registry.py b/tools/goal_registry.py index 51d117a..983afcc 100644 --- a/tools/goal_registry.py +++ b/tools/goal_registry.py @@ -11,6 +11,7 @@ goal_event_flight_invoice = AgentGoal( "1. FindFixtures: Find fixtures for a team in a given month " "2. SearchFlights: search for a flight around the event dates " "3. CreateInvoice: Create a simple invoice for the cost of that flight ", + starter_prompt="Welcome me, give me a description of what you can do, then ask me for the details you need to do your job", example_conversation_history="\n ".join( [ "user: I'd like to travel to a football match", diff --git a/workflows/tool_workflow.py b/workflows/tool_workflow.py index 93369d8..d321df3 100644 --- a/workflows/tool_workflow.py +++ b/workflows/tool_workflow.py @@ -150,24 +150,24 @@ class ToolWorkflow: prompt = self.prompt_queue.popleft() if not prompt.startswith("###"): self.add_message("user", prompt) + + # Validate the prompt before proceeding + validation_input = ValidationInput( + prompt=prompt, + conversation_history=self.conversation_history, + agent_goal=agent_goal, + ) + validation_result = await workflow.execute_activity( + ToolActivities.validate_llm_prompt, + args=[validation_input], + schedule_to_close_timeout=LLM_ACTIVITY_TIMEOUT, + retry_policy=RetryPolicy(initial_interval=timedelta(seconds=5)), + ) - # Validate the prompt before proceeding - validation_input = ValidationInput( - prompt=prompt, - conversation_history=self.conversation_history, - agent_goal=agent_goal, - ) - validation_result = await workflow.execute_activity( - ToolActivities.validate_llm_prompt, - args=[validation_input], - schedule_to_close_timeout=LLM_ACTIVITY_TIMEOUT, - retry_policy=RetryPolicy(initial_interval=timedelta(seconds=5)), - ) - - if not validation_result.validationResult: - # Handle validation failure - self.add_message("agent", validation_result.validationFailedReason) - continue # Skip to the next iteration + if not validation_result.validationResult: + # Handle validation failure + self.add_message("agent", validation_result.validationFailedReason) + continue # Skip to the next iteration # Proceed with generating the context and prompt