fix(ai): route xAI search through Responses API as native tools (#21037)

xAI deprecated Live Search, so the `searchParameters` provider option
now returns 410. This routes all xAI models through the Responses API
and binds web/X search as native agent tools, matching how
Anthropic/OpenAI expose search.

- xAI provider now uses `provider.responses()` — its
`webSearch()`/`xSearch()` tools only run against the Responses endpoint,
not chat completions
- web/X search migrated from the `provider-option` variant to `sdk-tool`
(`web_search`/`x_search`); deleted the dead `searchParameters` path, the
`provider-option` variant, and `providerOptions` on `NativeModelBinding`
- dropped a dead `rolePermissionConfig` param on `getAgentRoleId`, left
over from #20331

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Félix Malfait <FelixMalfait@users.noreply.github.com>
This commit is contained in:
nitin
2026-05-31 18:41:04 +05:30
committed by GitHub
parent b027e4bdb1
commit e430e4ea0a
11 changed files with 252 additions and 226 deletions
@@ -79,7 +79,7 @@ describe('AgentAsyncExecutorService — workflow agent role-scoped tool resoluti
{
provide: NativeToolBinderService,
useValue: {
bind: jest.fn().mockReturnValue({ tools: {}, providerOptions: {} }),
bind: jest.fn().mockReturnValue({}),
},
},
{
@@ -18,7 +18,6 @@ import { isUserAuthContext } from 'src/engine/core-modules/auth/guards/is-user-a
import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type';
import { BillingUsageService } from 'src/engine/core-modules/billing/services/billing-usage.service';
import { type ToolProviderContext } from 'src/engine/core-modules/tool-provider/interfaces/tool-provider-context.type';
import { NativeToolBinderService } from 'src/engine/metadata-modules/ai/ai-models/services/native-tool-binder.service';
import { ToolRegistryService } from 'src/engine/core-modules/tool-provider/services/tool-registry.service';
import { UsageOperationType } from 'src/engine/core-modules/usage/enums/usage-operation-type.enum';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
@@ -39,6 +38,7 @@ import { mergeLanguageModelUsage } from 'src/engine/metadata-modules/ai/ai-billi
import { AI_TELEMETRY_CONFIG } from 'src/engine/metadata-modules/ai/ai-models/constants/ai-telemetry.const';
import { AiModelConfigService } from 'src/engine/metadata-modules/ai/ai-models/services/ai-model-config.service';
import { AiModelRegistryService } from 'src/engine/metadata-modules/ai/ai-models/services/ai-model-registry.service';
import { NativeToolBinderService } from 'src/engine/metadata-modules/ai/ai-models/services/native-tool-binder.service';
import { type NativeModelToolOptions } from 'src/engine/metadata-modules/ai/ai-models/types/native-model-tool-options.type';
import {
AiException,
@@ -87,7 +87,6 @@ export class AgentAsyncExecutorService {
private async getAgentRoleId(
agentId: string,
workspaceId: string,
rolePermissionConfig?: RolePermissionConfig,
): Promise<string | undefined> {
const roleTarget = await this.roleTargetRepository.findOne(workspaceId, {
where: {
@@ -188,22 +187,20 @@ export class AgentAsyncExecutorService {
);
}
const nativeBinding = this.nativeToolBinder.bind(
const nativeTools = this.nativeToolBinder.bind(
registeredModel,
nativeModelToolOptions,
);
tools = {
...registryTools,
...nativeBinding.tools,
...nativeTools,
};
providerOptions = {
...nativeBinding.providerOptions,
...this.aiModelConfigService.getReasoningProviderOptions(
providerOptions =
this.aiModelConfigService.getReasoningProviderOptions(
registeredModel,
),
};
);
}
this.logger.log(`Generated ${Object.keys(tools).length} tools for agent`);