fix: preserve parallel tool call setting#128
Conversation
Signed-off-by: harivilasp <harivilasp@gmail.com>
|
We need to handle cases where built-in tools are allowed/specified by the user, in which case |
|
Addressed in 9844bc3. Built-in/gateway-owned tools now force upstream Verified with:
|
Signed-off-by: harivilasp <harivilasp@gmail.com>
9844bc3 to
79059b5
Compare
|
@harivilasp could you please resolves merge conflict, thanks. |
|
…-tool-calls # Conflicts: # crates/agentic-server-core/benches/executor_throughput.rs # crates/agentic-server-core/src/executor/modes/conversation.rs # crates/agentic-server-core/src/executor/modes/response.rs # crates/agentic-server-core/src/types/request_response.rs # crates/agentic-server-core/tests/dispatch_loop_cassette_test.rs # crates/agentic-server-core/tests/support/mod.rs # crates/agentic-server-core/tests/web_search_tool_test.rs
|
resolved merge confilcts |
Signed-off-by: harivilasp <harivilasp@gmail.com>
58a57f2 to
cd11ad7
Compare
| | ResponsesTool::WebSearch(_) | ||
| | ResponsesTool::FileSearch(_) | ||
| | ResponsesTool::CodeInterpreter(_) | ||
| ) |
There was a problem hiding this comment.
declares_built_in_tool's matches!(Mcp | WebSearch | FileSearch | CodeInterpreter) is a hand-maintained copy of the logic in ToolType::is_gateway_owned (!matches!(Function | CodexNamespace)). When the next built-in variant lands, someone will update one and forget the other. another regression problem is codex read_mcp_resource from client owned is mapped to gateway owned. so would need a check like
matches!(tool, ResponsesTool::Function(p) if maybe_mcp_function(p).is_some())) to put everything together then a fix like below would resolve the issue:
impl ResponsesTool {
/// The `ToolType` the registry would assign this declaration; `None` for `Unknown`.
/// Mirrors the classification in `ToolRegistry::build_with_handlers`.
fn tool_type(&self) -> Option<ToolType> {
match self {
// read_mcp_resource functions with valid MCP metadata register as
// MCP entries (registry.rs), so classify them the same way here.
Self::Function(p) if maybe_mcp_function(p).is_some_and(|params| !params.is_empty()) => {
Some(ToolType::Mcp)
}
Self::Function(_) => Some(ToolType::Function),
Self::Namespace(_) => Some(ToolType::CodexNamespace),
Self::Mcp(_) => Some(ToolType::Mcp),
Self::WebSearch(_) => Some(ToolType::WebSearch),
Self::FileSearch(_) => Some(ToolType::FileSearch),
Self::CodeInterpreter(_) => Some(ToolType::CodeInterpreter),
Self::Unknown => None,
}
}
pub fn is_gateway_owned(&self) -> bool {
self.tool_type().is_some_and(ToolType::is_gateway_owned)
}
}Then declares_built_in_tool collapses to tools.iter().any(ResponsesTool::is_gateway_owned). One source of truth, no signature churn, and to_function_tools keeps its single job.
There was a problem hiding this comment.
agreed, on this note, perhaps the test can be made more comprehensive by randomly selecting a supported built-in tool in the request
There was a problem hiding this comment.
@harivilasp the test test_gateway_normalization_preserves_parallel_tool_calls covers only the happy path. as @jiahuei suggested, maybe could have a more comprehensive test? random selection of supported tools and both parallel bool type?
Signed-off-by: harivilasp <harivilasp@gmail.com>
3b64c53 to
ffc823a
Compare
Summary
parallel_tool_callson/v1/responsesrequestsRequestPayload::to_upstream_requestafter gateway tool normalizationparallel_tool_calls: falsereaches the mock vLLM requestCloses #127.
Why
The gateway already preserves several Responses API generation/control fields (
include,temperature,top_p,max_output_tokens,truncation,metadata) while normalizing tools for vLLM.parallel_tool_callswas missing from the typed request model, so clients that explicitly disabled parallel tool calls had that setting silently dropped on the executor path.Validation
cargo test -p agentic-server-corecargo test -p agentic-server --test responses_testcargo test --workspacecargo clippy --workspace --all-targets -- -D warningscargo fmt -- --checkFocused tests were written first and failed before the implementation because
parallel_tool_callsserialized as absent/null instead offalse.