From 975265e1bd7807633e02f9a0d4608051420d65e6 Mon Sep 17 00:00:00 2001 From: openhands Date: Sun, 1 Mar 2026 14:05:05 +0000 Subject: [PATCH 1/2] fix: add security_risk and summary to tool examples for non-native function calling This fixes issue #2175 where models using prompt-based function calling (native_tool_calling=False) would fail to provide the security_risk parameter because the examples in the system prompt didn't show it. Changes: - Add security_risk parameter to all tool examples in TOOL_EXAMPLES dict - Add summary parameter to all tool examples for transparency - Update in_context_learning_example.j2 template with the same parameters The security_risk parameter is required when LLMSecurityAnalyzer is active, and the summary parameter is always recommended for action transparency. Fixes: #2175 Co-authored-by: openhands --- .../prompts/in_context_learning_example.j2 | 53 ++++++++------- .../sdk/llm/mixins/fn_call_converter.py | 64 ++++++++++++------- 2 files changed, 69 insertions(+), 48 deletions(-) diff --git a/openhands-sdk/openhands/sdk/agent/prompts/in_context_learning_example.j2 b/openhands-sdk/openhands/sdk/agent/prompts/in_context_learning_example.j2 index 6aa67c053e..ab77164d6b 100644 --- a/openhands-sdk/openhands/sdk/agent/prompts/in_context_learning_example.j2 +++ b/openhands-sdk/openhands/sdk/agent/prompts/in_context_learning_example.j2 @@ -6,9 +6,9 @@ USER: Create a list of numbers from 1 to 10, and display them in a web page at p A: Sure! Let me first check the current directory: - -pwd && ls - +pwd && ls +LOW +Check current directory and list files USER: EXECUTION RESULT of [terminal]: @@ -31,6 +31,8 @@ def index(): if __name__ == '__main__': app.run(port=5000) +MEDIUM +Create Flask app.py with table display endpoint USER: EXECUTION RESULT of [str_replace_editor]: @@ -38,9 +40,9 @@ File created successfully at: /workspace/app.py A: I have created a Python file `app.py` that will display a list of numbers from 1 to 10 when you run it. Let me run the Python file for you: - -python3 app.py > server.log 2>&1 & - +python3 app.py > server.log 2>&1 & +MEDIUM +Start Flask server in background USER: EXECUTION RESULT of [terminal]: @@ -49,9 +51,9 @@ USER: EXECUTION RESULT of [terminal]: A: Looks like the server is running with PID 121 then crashed. Let me check the server log: - -cat server.log - +cat server.log +LOW +Read server log to diagnose crash USER: EXECUTION RESULT of [terminal]: @@ -62,9 +64,9 @@ ModuleNotFoundError: No module named 'flask' A: Looks like the server crashed because the `flask` module is not installed. Let me install the `flask` module for you: - -pip3 install flask - +pip3 install flask +MEDIUM +Install flask package via pip USER: EXECUTION RESULT of [terminal]: @@ -86,9 +88,9 @@ Successfully installed Werkzeug-3.0.2 blinker-1.7.0 click-8.1.7 flask-3.0.3 itsd A: The `flask` module is installed successfully. Let me run the Python file again: - -python3 app.py > server.log 2>&1 & - +python3 app.py > server.log 2>&1 & +MEDIUM +Restart Flask server after installing dependencies USER: EXECUTION RESULT of [terminal]: @@ -97,9 +99,9 @@ USER: EXECUTION RESULT of [terminal]: A: Let me check the server log again: - -cat server.log - +cat server.log +LOW +Verify server started successfully USER: EXECUTION RESULT of [terminal]: @@ -117,9 +119,9 @@ USER: Now kill the server, make it display the numbers in a table format. A: Sure! Let me stop the server first: - -kill 124 - +kill 124 +MEDIUM +Stop the Flask server process USER: EXECUTION RESULT of [terminal]: @@ -132,6 +134,8 @@ Now let me display the numbers in a table format: /workspace/app.py return '' + ''.join([f'' for i in numbers]) + '
{i}
' return '' + ''.join([f'' for i in numbers]) + '
{i}
' +MEDIUM +Update HTML table formatting USER: EXECUTION RESULT of [str_replace_editor]: @@ -149,9 +153,9 @@ Review the changes and make sure they are as expected. Edit the file again if ne A: Running the updated file: - -python3 app.py > server.log 2>&1 & - +python3 app.py > server.log 2>&1 & +MEDIUM +Start updated Flask server USER: EXECUTION RESULT of [terminal]: @@ -160,6 +164,7 @@ USER: EXECUTION RESULT of [terminal]: A: The server is running on port 5000 with PID 126. You can access the list of numbers in a table format by visiting http://127.0.0.1:5000. Let me know if you have any further requests! +Task complete - Flask server running with table display --------------------- END OF EXAMPLE --------------------- diff --git a/openhands-sdk/openhands/sdk/llm/mixins/fn_call_converter.py b/openhands-sdk/openhands/sdk/llm/mixins/fn_call_converter.py index 0a8767e3b7..cf29ec385f 100644 --- a/openhands-sdk/openhands/sdk/llm/mixins/fn_call_converter.py +++ b/openhands-sdk/openhands/sdk/llm/mixins/fn_call_converter.py @@ -85,14 +85,17 @@ def refine_prompt(prompt: str) -> str: # interface designed in openhands/agenthub/agent/function_calling.py # Example snippets for each tool +# Note: security_risk and summary parameters are included in examples to ensure +# models learn to provide them when using prompt-based function calling. +# These parameters are always added to tool schemas for security and transparency. TOOL_EXAMPLES = { "bash": { "check_dir": """ ASSISTANT: Sure! Let me first check the current directory: - -pwd && ls - +pwd && ls +LOW +Check current directory and list files USER: EXECUTION RESULT of [terminal]: @@ -103,9 +106,9 @@ def refine_prompt(prompt: str) -> str: ASSISTANT: Let me run the Python file for you: - -python3 app.py > server.log 2>&1 & - +python3 app.py > server.log 2>&1 & +MEDIUM +Start Flask server in background USER: EXECUTION RESULT of [terminal]: @@ -115,9 +118,9 @@ def refine_prompt(prompt: str) -> str: ASSISTANT: Looks like the server was running with PID 121 then crashed. Let me check the server log: - -cat server.log - +cat server.log +LOW +Read server log to diagnose crash USER: EXECUTION RESULT of [terminal]: @@ -129,9 +132,9 @@ def refine_prompt(prompt: str) -> str: ASSISTANT: Looks like the server crashed because the `flask` module is not installed. Let me install the `flask` module for you: - -pip3 install flask - +pip3 install flask +MEDIUM +Install flask package via pip USER: EXECUTION RESULT of [terminal]: @@ -154,9 +157,9 @@ def refine_prompt(prompt: str) -> str: ASSISTANT: The `flask` module is installed successfully. Let me run the Python file again: - -python3 app.py > server.log 2>&1 & - +python3 app.py > server.log 2>&1 & +MEDIUM +Restart Flask server after installing dependencies USER: EXECUTION RESULT of [terminal]: @@ -165,9 +168,9 @@ def refine_prompt(prompt: str) -> str: ASSISTANT: Let me check the server log again: - -cat server.log - +cat server.log +LOW +Verify server started successfully USER: EXECUTION RESULT of [terminal]: @@ -186,9 +189,9 @@ def refine_prompt(prompt: str) -> str: ASSISTANT: Sure! Let me stop the server first: - -kill 124 - +kill 124 +MEDIUM +Stop the Flask server process USER: EXECUTION RESULT of [terminal]: @@ -198,9 +201,9 @@ def refine_prompt(prompt: str) -> str: ASSISTANT: Running the updated file: - -python3 app.py > server.log 2>&1 & - +python3 app.py > server.log 2>&1 & +MEDIUM +Start updated Flask server USER: EXECUTION RESULT of [terminal]: @@ -229,6 +232,8 @@ def index(): if __name__ == '__main__': app.run(port=5000) +MEDIUM +Create Flask app.py with number list endpoint USER: EXECUTION RESULT of [str_replace_editor]: @@ -242,6 +247,8 @@ def index(): /workspace/app.py return str(numbers) return '' + ''.join([f'' for i in numbers]) + '
{i}
' +MEDIUM +Update return statement to render HTML table USER: EXECUTION RESULT of [str_replace_editor]: @@ -267,6 +274,8 @@ def index(): goto('http://127.0.0.1:5000') noop(1000) # Wait for page to load +LOW +Navigate to localhost to verify page display USER: EXECUTION RESULT of [browser]: @@ -292,6 +301,8 @@ def index(): if __name__ == '__main__': app.run(port=5000) +MEDIUM +Create Flask app.py with number list endpoint USER: EXECUTION RESULT of [edit_file]: @@ -310,6 +321,8 @@ def index(): # ... existing code ... if __name__ == '__main__': +MEDIUM +Update index function to render HTML table USER: EXECUTION RESULT of [edit_file]: @@ -331,6 +344,7 @@ def index(): The server is running on port 5000 with PID 126. You can access the list of numbers in a table format by visiting http://127.0.0.1:5000. Let me know if you have any further requests! The task has been completed. The web server is running and displaying numbers 1-10 in a table format at http://127.0.0.1:5000. +Task complete - Flask server running with table display """ # noqa: E501 }, @@ -340,6 +354,7 @@ def index(): Let me check the current task list first: view +View current task list status """, "plan": """ @@ -360,6 +375,7 @@ def index(): } ] +Update task plan with current progress """, }, From 037ba9310f303907baf7410d7ce78e4e95f0e167 Mon Sep 17 00:00:00 2001 From: openhands Date: Tue, 3 Mar 2026 07:12:38 +0000 Subject: [PATCH 2/2] fix: add security_risk to task_tracker examples and message to finish example Addresses review feedback: - Add security_risk parameter to task_tracker 'view' and 'plan' examples (task_tracker has readOnlyHint=False so requires security_risk) - Add required 'message' parameter to finish example in in_context_learning_example.j2 (FinishAction.message is a required field) Co-authored-by: openhands --- .../openhands/sdk/agent/prompts/in_context_learning_example.j2 | 1 + openhands-sdk/openhands/sdk/llm/mixins/fn_call_converter.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/openhands-sdk/openhands/sdk/agent/prompts/in_context_learning_example.j2 b/openhands-sdk/openhands/sdk/agent/prompts/in_context_learning_example.j2 index ab77164d6b..e35c2f7124 100644 --- a/openhands-sdk/openhands/sdk/agent/prompts/in_context_learning_example.j2 +++ b/openhands-sdk/openhands/sdk/agent/prompts/in_context_learning_example.j2 @@ -164,6 +164,7 @@ USER: EXECUTION RESULT of [terminal]: A: The server is running on port 5000 with PID 126. You can access the list of numbers in a table format by visiting http://127.0.0.1:5000. Let me know if you have any further requests! +The task has been completed. The web server is running and displaying numbers 1-10 in a table format at http://127.0.0.1:5000. Task complete - Flask server running with table display diff --git a/openhands-sdk/openhands/sdk/llm/mixins/fn_call_converter.py b/openhands-sdk/openhands/sdk/llm/mixins/fn_call_converter.py index cf29ec385f..e4a06380e9 100644 --- a/openhands-sdk/openhands/sdk/llm/mixins/fn_call_converter.py +++ b/openhands-sdk/openhands/sdk/llm/mixins/fn_call_converter.py @@ -354,6 +354,7 @@ def index(): Let me check the current task list first: view +LOW View current task list status """, @@ -375,6 +376,7 @@ def index(): } ] +LOW Update task plan with current progress """,