[Inference] Fix ActionsClientLlm failing with EIS connector IDs#260268
[Inference] Fix ActionsClientLlm failing with EIS connector IDs#260268sphilipse merged 13 commits intoelastic:mainfrom
Conversation
After PR elastic#258530 consolidated connector listing, EIS connectors are returned with inference endpoint IDs (e.g. anthropic-claude-3.7-sonnet- chat_completion) as their connectorId rather than Kibana saved object IDs. Attack Discovery and Defend Insights passed these IDs to ActionsClientLlm which used actionsClient.execute(), failing with "Saved object [action/...] not found". Fix: Thread an InferenceClient from route handlers to ActionsClientLlm. When actionTypeId is .inference and an inference client is available, ActionsClientLlm uses its existing isInferenceEndpoint path which calls inferenceClient.chatComplete() instead of actionsClient.execute(), correctly handling inference endpoint IDs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ApprovabilityVerdict: Needs human review This PR changes how connector IDs are resolved from client-driven to server-driven across multiple security workflows (attack discovery, defend insights, scheduled tasks). The author does not own any of the 32 modified files, which span multiple team domains (@elastic/search-kibana, @elastic/security-generative-ai, @elastic/security-defend-workflows). Designated code owners should review these cross-cutting behavioral changes. You can customize Macroscope's approvability policy. Learn more. |
Move connector validation from client-side useLoadConnectors lookup to server-side resolution via inference.getConnectorById. The server now resolves the authoritative actionTypeId from the connector ID, so the client only needs to send the connectorId. This removes the useLoadConnectors dependency from useAttackDiscovery and ensures inference endpoint IDs (including EIS connectors) are resolved correctly regardless of what the client sends. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
...s/elastic_assistant/server/lib/attack_discovery/schedules/register_schedule/executor.test.ts
Show resolved
Hide resolved
3c628c7 to
8f38cbc
Compare
2478f50 to
e320a10
Compare
...urity/plugins/security_solution/public/attack_discovery/pages/use_attack_discovery/index.tsx
Show resolved
Hide resolved
eb2cc5c to
cc041bd
Compare
Add getConnectorByIdWithScopedServices to the inference plugin start contract, which accepts pre-scoped actionsClient and esClient instead of a KibanaRequest. This enables background tasks (like the attack discovery schedule executor) to resolve connector types without needing an HTTP request context. The executor now uses this API to resolve the authoritative actionTypeId for the connector, ensuring EIS inference endpoint IDs are handled correctly in scheduled attack discovery generation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2c5ec43 to
3a9852e
Compare
When fetchAttackDiscoveries is called with overrideConnectorId (from the settings flyout), look up the connector name via getConnectorNameFromId using the already-loaded aiConnectors list and pass it as overrideConnectorName. The toast now shows the correct connector name for both default and override cases. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
...urity/plugins/security_solution/public/attack_discovery/pages/use_attack_discovery/index.tsx
Show resolved
Hide resolved
e40pud
left a comment
There was a problem hiding this comment.
Tested locally and attack discovery schedules work with EIS models now. Thanks for the fix @sphilipse 🚀
...urity/plugins/security_solution/public/attack_discovery/pages/use_attack_discovery/index.tsx
Show resolved
Hide resolved
Replace hand-rolled inference mock with inferenceMock.createStartContract() which stays in sync with the InferenceServerStart interface. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
TattdCodeMonkey
left a comment
There was a problem hiding this comment.
Code review only.
| @@ -157,9 +163,15 @@ export function getAssistantToolParams({ | |||
| ], | |||
| }; | |||
|
|
|||
| const isInferenceEndpoint = | |||
| apiConfig.actionTypeId === ('.inference' as InferenceConnectorType.Inference) && | |||
There was a problem hiding this comment.
nit: we're doing '.inference' as InferenceConnectorType.Inference in a few places. would be nice to have a constant for this either in this file or somewhere sharable.
Extract createClientWithoutRequest into create_client.ts, encapsulating the ActionsPluginStart and KibanaRequest shims as an implementation detail. The plugin.ts getClientWithoutRequest now delegates cleanly without any type casts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The inference plugin only uses getActionsClientWithRequest from the actions plugin. Define a narrow ActionsClientProvider interface with just that method and use it throughout the internal implementation. This removes the `as unknown as ActionsPluginStart` cast in createClientWithoutRequest, since the wrapper object now directly satisfies the narrower type. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
paul-tavares
left a comment
There was a problem hiding this comment.
LGTM 👍 ( elastic/security-defend-workflows team
cc/ @joeypoon
💛 Build succeeded, but was flaky
Failed CI StepsMetrics [docs]Async chunks
History
|
…tic#260268) ## Summary After PR elastic#258530 consolidated connector listing, EIS connectors are returned with inference endpoint IDs (e.g. anthropic-claude-3.7-sonnet- chat_completion) as their connectorId rather than Kibana saved object IDs. Attack Discovery and Defend Insights passed these IDs to ActionsClientLlm which used actionsClient.execute(), failing with "Saved object [action/...] not found". This PR uses a new path when actionTypeId is .inference and an inference client is available. ActionsClientLlm uses its existing isInferenceEndpoint path which calls inferenceClient.chatComplete() instead of actionsClient.execute(). --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
) (#260345) ## Summary Cherry pick #260268 to `deploy-fix@1774851440` After PR #258530 consolidated connector listing, EIS connectors are returned with inference endpoint IDs (e.g. anthropic-claude-3.7-sonnet- chat_completion) as their connectorId rather than Kibana saved object IDs. Attack Discovery and Defend Insights passed these IDs to ActionsClientLlm which used actionsClient.execute(), failing with "Saved object [action/...] not found". This PR uses a new path when actionTypeId is .inference and an inference client is available. ActionsClientLlm uses its existing isInferenceEndpoint path which calls inferenceClient.chatComplete() instead of actionsClient.execute(). cc @sphilipse @pheyos Co-authored-by: Sander Philipse <94373878+sphilipse@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
…all code paths to fix EIS connectors After rebasing ff51c50 (Workflows Integration), the inferenceClient threading from PR elastic#260268 was lost. This restores it across all affected code paths so that EIS connectors (actionTypeId='.inference') use inferenceClient.chatComplete() instead of actionsClient.execute(), which fails with 'Saved object not found' for inference endpoint IDs. Gaps fixed: - Gap 1: Legacy public route handler (FF OFF) — adds inferenceClient to generateAndUpdateAttackDiscoveries call - Gap 2: Schedule executor (FF OFF, scheduled runs) — threads getInference lazy getter through definition and executor, uses getClientWithoutRequest/getConnectorByIdWithoutClientRequest for background context - Gap 3: Discoveries plugin inference dependency — adds InferenceServerStart to DiscoveriesPluginStartDeps and inference to optionalPlugins - Gap 4: invokeAttackDiscoveryGraphWithAlerts (FF ON) — adds inferenceClient param, computes isInferenceEndpoint, passes both to ActionsClientLlm - Gap 5: invokeGenerationGraph helper (FF ON) — forwards inferenceClient to invokeAttackDiscoveryGraphWithAlerts - Gap 6: Generate step handler (FF ON) — creates inferenceClient from pluginsStart.inference and passes to invokeGenerationGraph Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tic#260268) ## Summary After PR elastic#258530 consolidated connector listing, EIS connectors are returned with inference endpoint IDs (e.g. anthropic-claude-3.7-sonnet- chat_completion) as their connectorId rather than Kibana saved object IDs. Attack Discovery and Defend Insights passed these IDs to ActionsClientLlm which used actionsClient.execute(), failing with "Saved object [action/...] not found". This PR uses a new path when actionTypeId is .inference and an inference client is available. ActionsClientLlm uses its existing isInferenceEndpoint path which calls inferenceClient.chatComplete() instead of actionsClient.execute(). --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
…tic#260268) ## Summary After PR elastic#258530 consolidated connector listing, EIS connectors are returned with inference endpoint IDs (e.g. anthropic-claude-3.7-sonnet- chat_completion) as their connectorId rather than Kibana saved object IDs. Attack Discovery and Defend Insights passed these IDs to ActionsClientLlm which used actionsClient.execute(), failing with "Saved object [action/...] not found". This PR uses a new path when actionTypeId is .inference and an inference client is available. ActionsClientLlm uses its existing isInferenceEndpoint path which calls inferenceClient.chatComplete() instead of actionsClient.execute(). --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Summary
After PR #258530 consolidated connector listing, EIS connectors are returned with inference endpoint IDs (e.g. anthropic-claude-3.7-sonnet- chat_completion) as their connectorId rather than Kibana saved object IDs. Attack Discovery and Defend Insights passed these IDs to ActionsClientLlm which used actionsClient.execute(), failing with "Saved object [action/...] not found".
This PR uses a new path when actionTypeId is .inference and an inference client is available. ActionsClientLlm uses its existing isInferenceEndpoint path which calls inferenceClient.chatComplete() instead of actionsClient.execute().