* refactor(ai): use responses API for OpenAI/Azure, create 'other' provider for completion endpoint - Created new 'other.rs' provider using the OpenAI-compatible completion endpoint - Refactored 'openai.rs' to use the Responses API for both text and image output - Updated query_builder to route OpenAI/AzureOpenAI to OpenAIQueryBuilder - All other providers (Mistral, DeepSeek, Groq, etc.) now use OtherQueryBuilder - Updated OpenRouter to delegate to OtherQueryBuilder instead of OpenAIQueryBuilder This prepares the codebase for adding websearch tool support using the Responses API. Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> * feat(ai): add websearch as AI agent tool type - Added WebsearchToolValue to ToolValue enum in flows.rs - Updated all pattern matches to handle websearch tool type - Added has_websearch parameter to run_agent function - Websearch tools don't require additional configuration This prepares the backend for provider-specific websearch implementations. Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> * feat(frontend): add websearch as tool option in AI agent UI - Added WebsearchTool type and utility functions to agentToolUtils.ts - Added "Web Search" option in tool insertion menu (InsertModuleInner) - Updated NewAIToolNode to handle pickWebsearchTool event - Updated AIToolNode to render websearch tools properly - Updated FlowModuleSchemaMap to create websearch tools Users can now add websearch tools to AI agents through the UI. Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> * feat(ai): implement websearch for OpenAI provider - Added has_websearch parameter to BuildRequestArgs - OpenAI provider now adds web_search tool to requests when enabled - Uses OpenAI Responses API web_search tool type - Websearch tool is added before other custom tools in the request Implements websearch functionality for OpenAI and Azure OpenAI providers. Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> * feat(ai): implement websearch for Anthropic provider - Created anthropic.rs provider with native Anthropic API format - Added web_search tool to Anthropic requests when enabled - Anthropic uses /messages endpoint with x-api-key authentication - Updated query_builder to route Anthropic to new provider Implements websearch functionality for Anthropic Claude models. Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> * feat(ai): implement websearch for Gemini/GoogleAI provider - GoogleAI now uses completion endpoint (other.rs) for text instead of responses API - Added Google Search grounding when websearch is enabled - Uses google_search_retrieval tool in request when has_websearch is true - Updated parse methods to use OtherQueryBuilder for completion endpoint Implements websearch functionality for Google Gemini models. Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> * fix frontend * fix anthropic and openai * better for gemini * structured output * cleaning * fix validate tool * fixes * cleaning * cleaning * fix for openai * no responses api for azure * fixes * fix * add tests for ai agent * avoid panic * better tests * test user images * fix tool choice * always use streaming backend side * big cleaning * show annotations plus agent action for open ai websearch use * show annotations plus agent action for anthropic websearch use * show annotations plus agent action for google websearch use * nit forntend * rm * fix * add test for image ouptut * fix for azure * add in openflow * fix * fix * nit tests * fixes --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> Co-authored-by: centdix <farhadg110@gmail.com>
149 lines
4.3 KiB
Python
149 lines
4.3 KiB
Python
"""
|
|
Tool calling tests for AI agents.
|
|
|
|
Tests AI agent tool calling with different tool types:
|
|
- Rawscript tools (inline Bun/TypeScript)
|
|
- MCP tools (external MCP servers)
|
|
- Websearch tools (built-in web search)
|
|
"""
|
|
|
|
import pytest
|
|
|
|
from .conftest import AIAgentTestClient, create_ai_agent_flow, create_rawscript_tool
|
|
from .providers import ALL_PROVIDERS, ANTHROPIC, GOOGLE_AI, OPENAI
|
|
|
|
|
|
def get_provider_ids(providers: list) -> list[str]:
|
|
"""Get provider names for pytest parametrization IDs."""
|
|
return [p["name"] for p in providers]
|
|
|
|
|
|
# Inline script for sum tool (Bun/TypeScript)
|
|
ADD_NUMBERS_SCRIPT = """
|
|
export function main(a: number, b: number): number {
|
|
return a + b;
|
|
}
|
|
"""
|
|
|
|
|
|
class TestToolCalling:
|
|
"""Test AI agent tool calling with different tool types."""
|
|
|
|
@pytest.mark.parametrize(
|
|
"provider_config",
|
|
ALL_PROVIDERS,
|
|
ids=get_provider_ids(ALL_PROVIDERS),
|
|
)
|
|
def test_sum_tool(
|
|
self,
|
|
client: AIAgentTestClient,
|
|
setup_providers,
|
|
provider_config,
|
|
):
|
|
"""
|
|
Test that an AI agent can call a rawscript tool to add numbers.
|
|
"""
|
|
tools = [
|
|
create_rawscript_tool(
|
|
tool_id="add_numbers",
|
|
content=ADD_NUMBERS_SCRIPT,
|
|
params=["a", "b"],
|
|
language="bun",
|
|
)
|
|
]
|
|
|
|
flow_value = create_ai_agent_flow(
|
|
provider_input_transform=provider_config["input_transform"],
|
|
system_prompt="You are a helpful assistant. Use the add_numbers tool to perform arithmetic.",
|
|
tools=tools,
|
|
)
|
|
|
|
result = client.run_preview_flow(
|
|
flow_value=flow_value,
|
|
args={"user_message": "What is 5 + 7? Use the add_numbers tool."},
|
|
)
|
|
|
|
assert result is not None
|
|
result_str = str(result)
|
|
assert "12" in result_str, f"Expected '12' in result: {result}"
|
|
print(f"Sum tool result from {provider_config['name']}: {result}")
|
|
|
|
@pytest.mark.parametrize(
|
|
"provider_config",
|
|
ALL_PROVIDERS,
|
|
ids=get_provider_ids(ALL_PROVIDERS),
|
|
)
|
|
def test_mcp_tool(
|
|
self,
|
|
client: AIAgentTestClient,
|
|
setup_providers,
|
|
provider_config,
|
|
):
|
|
"""
|
|
Test that an AI agent can call an MCP tool (DeepWiki).
|
|
"""
|
|
tools = [
|
|
{
|
|
"id": "deepwiki",
|
|
"value": {
|
|
"tool_type": "mcp",
|
|
"resource_path": "$res:u/admin/deepwiki",
|
|
},
|
|
}
|
|
]
|
|
|
|
flow_value = create_ai_agent_flow(
|
|
provider_input_transform=provider_config["input_transform"],
|
|
system_prompt="You are a helpful assistant. Use the available tools to answer questions.",
|
|
tools=tools,
|
|
)
|
|
|
|
result = client.run_preview_flow(
|
|
flow_value=flow_value,
|
|
args={"user_message": "Use the read_wiki_structure tool to get the structure of the sveltejs/svelte repository."},
|
|
)
|
|
|
|
assert result is not None
|
|
print(f"MCP tool result from {provider_config['name']}: {result}")
|
|
|
|
@pytest.mark.parametrize(
|
|
"provider_config",
|
|
[OPENAI, ANTHROPIC, GOOGLE_AI],
|
|
ids=get_provider_ids([OPENAI, ANTHROPIC, GOOGLE_AI]),
|
|
)
|
|
def test_websearch_tool(
|
|
self,
|
|
client: AIAgentTestClient,
|
|
setup_providers,
|
|
provider_config,
|
|
):
|
|
"""
|
|
Test that an AI agent can use the websearch tool.
|
|
"""
|
|
tools = [
|
|
{
|
|
"id": "websearch",
|
|
"value": {
|
|
"tool_type": "websearch",
|
|
},
|
|
}
|
|
]
|
|
|
|
flow_value = create_ai_agent_flow(
|
|
provider_input_transform=provider_config["input_transform"],
|
|
system_prompt="You are a helpful assistant. Use websearch to find current information.",
|
|
tools=tools,
|
|
)
|
|
|
|
result = client.run_preview_flow(
|
|
flow_value=flow_value,
|
|
args={"user_message": "What is the current version of Svelte? Use websearch."},
|
|
)
|
|
|
|
assert result is not None
|
|
print(f"Websearch tool result from {provider_config['name']}: {result}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
pytest.main([__file__, "-v", "-s"])
|