Skip to content

fix(sdk): drop in-flight tool calls from ask_agent context - #4630

Open
all-hands-bot wants to merge 1 commit into
mainfrom
fix/ask-agent-inflight-tool-call
Open

fix(sdk): drop in-flight tool calls from ask_agent context#4630
all-hands-bot wants to merge 1 commit into
mainfrom
fix/ask-agent-inflight-tool-call

Conversation

@all-hands-bot

@all-hands-bot all-hands-bot commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Problem

The run-examples workflow was failing on examples/01_standalone_sdk/28_ask_agent_example.py. The example calls conversation.ask_agent() from a background thread while the main agent is mid-tool-call.

ask_agent() built its context with prepare_llm_messages(self.state.view, ...). The cached state.view is maintained incrementally (issue #3053) and skips enforce_properties on linear appends, so it can transiently contain an ActionEvent whose ObservationEvent has not landed yet. Anthropic rejects a tool_use with no following tool_result, so ask_agent() fails with a 400:

litellm.BadRequestError: ... messages.6: `tool_use` ids were found without `tool_result` blocks immediately after ...

That error then cascaded: the background run() thread hit the same malformed history and collapsed with RuntimeError: cannot schedule new futures after shutdown, failing the example.

Fix

Build the ask-agent context from a freshly property-enforced View.from_events(self._state.active_branch()) instead of the cached state.view. Property enforcement drops the orphaned in-flight action (its observation hasn't arrived yet), exactly matching what agent.step() already relies on via rebuild_view() on cold load / forks.

Test

Added test_ask_agent_drops_in_flight_action_without_observation asserting the orphaned tool_use is dropped from the context sent to the LLM.


This PR was created by an AI agent (OpenHands) on behalf of the user.


🐳 Agent Server images for this PR — GHCR package, pull/run commands, and all pushed tags (click to expand)

GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server

Variants & Base Images

Variant Architectures Base Image Docs / Tags
java amd64, arm64 eclipse-temurin:17-jdk Link
python amd64, arm64 nikolaik/python-nodejs:python3.13-nodejs22-slim Link
golang amd64, arm64 golang:1.21-bookworm Link

Pull (multi-arch manifest)

# Each variant is a multi-arch manifest supporting both amd64 and arm64
docker pull ghcr.io/openhands/agent-server:632d4fb-python

Run

docker run -it --rm \
  -p 8000:8000 \
  --name agent-server-632d4fb-python \
  ghcr.io/openhands/agent-server:632d4fb-python

All tags pushed for this build

ghcr.io/openhands/agent-server:632d4fb-golang-amd64
ghcr.io/openhands/agent-server:632d4fb6224b77a27cb1c3059fe2d1188d823f45-golang-amd64
ghcr.io/openhands/agent-server:fix-ask-agent-inflight-tool-call-golang-amd64
ghcr.io/openhands/agent-server:632d4fb-golang_tag_1.21-bookworm-amd64
ghcr.io/openhands/agent-server:632d4fb-golang-arm64
ghcr.io/openhands/agent-server:632d4fb6224b77a27cb1c3059fe2d1188d823f45-golang-arm64
ghcr.io/openhands/agent-server:fix-ask-agent-inflight-tool-call-golang-arm64
ghcr.io/openhands/agent-server:632d4fb-golang_tag_1.21-bookworm-arm64
ghcr.io/openhands/agent-server:632d4fb-java-amd64
ghcr.io/openhands/agent-server:632d4fb6224b77a27cb1c3059fe2d1188d823f45-java-amd64
ghcr.io/openhands/agent-server:fix-ask-agent-inflight-tool-call-java-amd64
ghcr.io/openhands/agent-server:632d4fb-eclipse-temurin_tag_17-jdk-amd64
ghcr.io/openhands/agent-server:632d4fb-java-arm64
ghcr.io/openhands/agent-server:632d4fb6224b77a27cb1c3059fe2d1188d823f45-java-arm64
ghcr.io/openhands/agent-server:fix-ask-agent-inflight-tool-call-java-arm64
ghcr.io/openhands/agent-server:632d4fb-eclipse-temurin_tag_17-jdk-arm64
ghcr.io/openhands/agent-server:632d4fb-python-amd64
ghcr.io/openhands/agent-server:632d4fb6224b77a27cb1c3059fe2d1188d823f45-python-amd64
ghcr.io/openhands/agent-server:fix-ask-agent-inflight-tool-call-python-amd64
ghcr.io/openhands/agent-server:632d4fb-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim-amd64
ghcr.io/openhands/agent-server:632d4fb-python-arm64
ghcr.io/openhands/agent-server:632d4fb6224b77a27cb1c3059fe2d1188d823f45-python-arm64
ghcr.io/openhands/agent-server:fix-ask-agent-inflight-tool-call-python-arm64
ghcr.io/openhands/agent-server:632d4fb-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim-arm64
ghcr.io/openhands/agent-server:632d4fb-golang
ghcr.io/openhands/agent-server:632d4fb6224b77a27cb1c3059fe2d1188d823f45-golang
ghcr.io/openhands/agent-server:fix-ask-agent-inflight-tool-call-golang
ghcr.io/openhands/agent-server:632d4fb-golang_tag_1.21-bookworm
ghcr.io/openhands/agent-server:632d4fb-java
ghcr.io/openhands/agent-server:632d4fb6224b77a27cb1c3059fe2d1188d823f45-java
ghcr.io/openhands/agent-server:fix-ask-agent-inflight-tool-call-java
ghcr.io/openhands/agent-server:632d4fb-eclipse-temurin_tag_17-jdk
ghcr.io/openhands/agent-server:632d4fb-python
ghcr.io/openhands/agent-server:632d4fb6224b77a27cb1c3059fe2d1188d823f45-python
ghcr.io/openhands/agent-server:fix-ask-agent-inflight-tool-call-python
ghcr.io/openhands/agent-server:632d4fb-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim

About Multi-Architecture Support

  • Each variant tag (e.g., 632d4fb-python) is a multi-arch manifest supporting both amd64 and arm64
  • Docker automatically pulls the correct architecture for your platform
  • Individual architecture tags (e.g., 632d4fb-python-amd64) are also available if needed

ask_agent built its context from the cached state.view, which is
maintained incrementally and skips enforce_properties on linear appends.
When ask_agent runs while the main agent is mid tool-call, the cached
view can contain an ActionEvent whose ObservationEvent has not landed
yet. Anthropic rejects a tool_use with no following tool_result, so the
ask_agent call failed with a 400 (and the run then collapsed with a
shutdown'd executor). Build the context from a freshly property-enforced
view of the active branch so orphaned actions are dropped.

Co-authored-by: openhands <openhands@all-hands.dev>
@all-hands-bot

Copy link
Copy Markdown
Collaborator Author

👋 This PR needs a couple of things fixed before OpenHands can review it:

  • the PR description's HUMAN: section needs at least 20 characters describing what you tested, not just the template placeholder

Push an update once this is addressed and this check re-runs automatically.

This is an automated check - no AI was used to generate this comment.

@all-hands-bot all-hands-bot added the test-examples Run all applicable "examples/" files. Expensive operation. label Aug 25, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Python API breakage checks — ✅ PASSED

Result:PASSED

Action log

@github-actions

Copy link
Copy Markdown
Contributor

REST API breakage checks (OpenAPI) — ✅ PASSED

Result:PASSED

Action log

@github-actions

Copy link
Copy Markdown
Contributor

Coverage

Coverage Report •
FileStmtsMissCoverMissing
openhands-sdk/openhands/sdk/conversation/impl
   local_conversation.py10878892%167, 340, 406, 658–659, 692, 734, 1062, 1086–1087, 1092, 1107, 1109, 1213, 1229, 1277, 1303, 1383, 1387–1393, 1458, 1478–1480, 1529, 1548–1550, 1873–1874, 1889, 2112, 2115–2116, 2141, 2172, 2178, 2259, 2266, 2269, 2272, 2276–2277, 2281–2282, 2285, 2292, 2317, 2321, 2324, 2343, 2395, 2398, 2437, 2444–2445, 2453, 2457–2459, 2466, 2503–2509, 2512, 2515, 2522, 2614, 2619, 2739–2740, 2758–2759, 2792, 3006, 3010, 3080, 3087–3088
TOTAL409671146972% 

@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

🔄 Running Examples with openhands/claude-haiku-4-5-20251001

Generated: 2026-08-25 16:55:55 UTC

Example Status Duration Cost
01_standalone_sdk/02_custom_tools.py ✅ PASS 24.0s $0.03
01_standalone_sdk/03_activate_skill.py ✅ PASS 23.8s $0.03
01_standalone_sdk/05_use_llm_registry.py ✅ PASS 11.7s $0.01
01_standalone_sdk/07_mcp_integration.py ✅ PASS 46.9s $0.04
01_standalone_sdk/09_pause_example.py ✅ PASS 13.8s $0.01
01_standalone_sdk/10_persistence.py ✅ PASS 26.6s $0.03
01_standalone_sdk/11_async.py ✅ PASS 35.4s $0.04
01_standalone_sdk/12_custom_secrets.py ✅ PASS 13.4s $0.01
01_standalone_sdk/13_get_llm_metrics.py ✅ PASS 38.5s $0.05
01_standalone_sdk/14_context_condenser.py ✅ PASS 2m 48s $0.18
01_standalone_sdk/17_image_input.py ✅ PASS 22.7s $0.02
01_standalone_sdk/18_send_message_while_processing.py ✅ PASS 21.3s $0.02
01_standalone_sdk/19_llm_routing.py ✅ PASS 17.9s $0.02
01_standalone_sdk/20_stuck_detector.py ✅ PASS 15.8s $0.02
01_standalone_sdk/21_generate_extraneous_conversation_costs.py ✅ PASS 11.1s $0.00
01_standalone_sdk/22_anthropic_thinking.py ✅ PASS 14.7s $0.01
01_standalone_sdk/23_responses_reasoning.py ✅ PASS 59.3s $0.01
01_standalone_sdk/24_planning_agent_workflow.py ✅ PASS 3m 7s $0.23
01_standalone_sdk/25_agent_delegation.py ✅ PASS 54.0s $0.06
01_standalone_sdk/26_custom_visualizer.py ✅ PASS 19.2s $0.02
01_standalone_sdk/28_ask_agent_example.py ✅ PASS 41.1s $0.03
01_standalone_sdk/29_llm_streaming.py ✅ PASS 40.5s $0.02
01_standalone_sdk/30_tom_agent.py ✅ PASS 11.4s $0.01
01_standalone_sdk/31_iterative_refinement.py ✅ PASS 1m 22s $0.07
01_standalone_sdk/32_configurable_security_policy.py ✅ PASS 19.6s $0.02
01_standalone_sdk/33_hooks/main.py ✅ PASS 36.8s $0.04
01_standalone_sdk/34_critic_example.py ✅ PASS 1m 31s $0.10
01_standalone_sdk/36_event_json_to_openai_messages.py ✅ PASS 11.6s $0.00
01_standalone_sdk/37_llm_profile_store/main.py ✅ PASS 9.0s $0.00
01_standalone_sdk/38_browser_session_recording.py ✅ PASS 38.1s $0.04
01_standalone_sdk/39_llm_fallback.py ✅ PASS 12.4s $0.01
01_standalone_sdk/40_acp_agent_example.py ✅ PASS 60.0s $0.41
01_standalone_sdk/41_task_tool_set.py ✅ PASS 30.3s $0.03
01_standalone_sdk/42_file_based_subagents.py ✅ PASS 56.2s $0.06
01_standalone_sdk/44_model_switching_in_convo.py ✅ PASS 11.0s $0.01
01_standalone_sdk/45_parallel_tool_execution.py ✅ PASS 4m 46s $0.54
01_standalone_sdk/46_agent_settings.py ✅ PASS 12.1s $0.01
01_standalone_sdk/47_defense_in_depth_security.py ✅ PASS 4.1s $0.00
01_standalone_sdk/48_conversation_fork.py ✅ PASS 23.1s $0.01
01_standalone_sdk/49_switch_llm_tool.py ✅ PASS 8.5s $0.04
01_standalone_sdk/50_async_cancellation.py ✅ PASS 14.9s $0.00
01_standalone_sdk/51_agent_hooks/main.py ✅ PASS 37.2s $0.04
01_standalone_sdk/52_dynamic_workflow.py ✅ PASS 4m 29s $0.15
01_standalone_sdk/53_client_defined_tools.py ✅ PASS 12.0s $0.01
01_standalone_sdk/54_goal_completion_loop.py ✅ PASS 33.7s $0.03
01_standalone_sdk/55_persistent_memory.py ✅ PASS 22.3s $0.02
01_standalone_sdk/56_structured_output.py ✅ PASS 48.6s $0.07
01_standalone_sdk/57_prompt_hooks/main.py ✅ PASS 27.1s $0.00
02_remote_agent_server/01_convo_with_local_agent_server.py ✅ PASS 34.3s $0.02
02_remote_agent_server/02_convo_with_docker_sandboxed_server.py ✅ PASS 1m 40s $0.03
02_remote_agent_server/03_browser_use_with_docker_sandboxed_server.py ✅ PASS 1m 48s $0.12
02_remote_agent_server/04_convo_with_api_sandboxed_server.py ✅ PASS 1m 49s $0.04
02_remote_agent_server/06_custom_tool/main.py ✅ PASS 6m 42s $0.07
02_remote_agent_server/07_convo_with_cloud_workspace.py ✅ PASS 45.4s $0.03
02_remote_agent_server/08_convo_with_apptainer_sandboxed_server.py ✅ PASS 5m 51s $0.04
02_remote_agent_server/09_acp_agent_with_remote_runtime.py ✅ PASS 1m 4s $0.37
02_remote_agent_server/10_cloud_workspace_share_credentials.py ✅ PASS 32.8s $0.04
02_remote_agent_server/11_conversation_fork.py ✅ PASS 40.3s $0.00
02_remote_agent_server/12_settings_and_secrets_api.py ✅ PASS 2m 22s $0.01
02_remote_agent_server/13_workspace_get_llm.py ✅ PASS 25.0s $0.01
02_remote_agent_server/14_client_defined_tools.py ✅ PASS 26.9s $0.02
02_remote_agent_server/15_openai_compatible_gateway.py ✅ PASS 22.5s $0.02
02_remote_agent_server/16_deferred_init.py ✅ PASS 46.6s $0.01
04_llm_specific_tools/01_gpt5_apply_patch_preset.py ✅ PASS 32.8s $0.03
04_llm_specific_tools/02_gemini_file_tools.py ✅ PASS 54.5s $0.09
05_skills_and_plugins/01_loading_agentskills/main.py ✅ PASS 15.2s $0.02
05_skills_and_plugins/02_loading_plugins/main.py ✅ PASS 45.9s $0.03
05_skills_and_plugins/04_mixed_marketplace_skills/main.py ✅ PASS 17.4s $0.00

✅ All tests passed!

Total: 68 | Passed: 68 | Failed: 0 | Total Cost: $3.62

View full workflow run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test-examples Run all applicable "examples/" files. Expensive operation.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants