Add Exa search connector - #14245
Conversation
|
@microsoft-github-policy-service agree |
There was a problem hiding this comment.
Pull request overview
This PR adds a new Python TextSearch connector (ExaSearch) to Semantic Kernel, enabling agent/plugin scenarios to query Exa’s semantic search API alongside existing Brave and Google connectors.
Changes:
- Added
ExaSearchconnector implementation and result/settings models. - Wired Exa connector into the lazy connector exports (
search.py/search.pyi). - Added sample usage, environment variable template entry, and unit tests for the connector.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| python/semantic_kernel/connectors/exa.py | Implements the Exa /search connector, settings, and response/result models. |
| python/semantic_kernel/connectors/search.py | Adds lazy export mapping for Exa connector symbols. |
| python/semantic_kernel/connectors/search.pyi | Exposes Exa connector symbols in type stubs. |
| python/tests/unit/connectors/search/test_exa_search.py | Adds unit tests for ExaSearch behaviors and payload construction. |
| python/tests/unit/connectors/conftest.py | Adds exa_unit_test_env fixture to provide EXA_API_KEY during tests. |
| python/samples/concepts/search/exa_text_search_as_plugin.py | Adds a sample demonstrating ExaSearch as a Kernel plugin. |
| python/samples/concepts/README.md | Links the new Exa sample in the concepts README. |
| python/.env.example | Adds EXA_API_KEY to the example environment file. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Automated Code Review
Reviewers: 5 | Confidence: 70%
✓ Correctness
The new Exa search connector is well-structured and follows the existing patterns (Brave connector). One correctness issue found: the HTTP header for user agent uses an underscore (
user_agent) instead of a hyphen (User-Agent), which means the user-agent string won't be recognized by servers or proxies. Theskipparameter is accepted but silently ignored (Exa API has no offset), which matches other SK connectors. Tests are comprehensive and cover all major code paths.
✓ Security Reliability
The Exa search connector is well-structured from a security standpoint: it uses ast.parse (not eval) for filter lambda parsing, stores the API key as SecretStr, sets an HTTP timeout, and has comprehensive error handling. The only notable issue is the HTTP header name 'user_agent' (underscore) which should likely be 'User-Agent' (hyphen) to be recognized as the standard User-Agent header by servers and proxies. No injection risks, secret leaks, or resource leak concerns were identified.
✓ Test Coverage
The test suite covers the main happy paths and error handling well (init, three output types, HTTP/request/generic errors, validation, filters). However, there are a few notable coverage gaps: no test for empty search results, the
skipparameter is accepted but silently ignored without any test verifying the behavior,include_total_count=Falseis never explicitly asserted to yieldtotal_count=None, and the_get_optionsfallback path (returning defaultSearchOptions()onValidationError) is untested. Theapi_keyconstructor parameter path is also untested (only env-var path is covered).
✓ Failure Modes
The Exa connector has a few silent failure modes: the
skipparameter is accepted but silently ignored (callers get duplicate results instead of paginated ones), the User-Agent header uses an underscore instead of a hyphen so it won't be recognized by HTTP infrastructure, and_get_optionssilently swallows validation errors returning defaults. The error handling for HTTP failures is solid and well-tested.
✓ Design Approach
I found one design-level correctness issue: the new connector advertises paginated search via
skip, but the implementation never sends any offset/cursor information to Exa or rejects unsupported paging, so nonzeroskipsilently returns the first page again.
Automated review by kesku's agents
360adc3 to
242c7b5
Compare
242c7b5 to
7cc8881
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (3)
python/samples/concepts/search/exa_text_search_as_plugin.py:19
- Minor grammar issues in the sample docstring: “obtained by login to” should be “obtained by logging in to”, and “After that store it” should include a comma (“After that, …”).
To use Exa Search, you need an API key, which can be obtained by login to
https://dashboard.exa.ai/api-keys and creating a key.
After that store it under the name `EXA_API_KEY` in a .env file or your environment variables.
python/samples/concepts/search/exa_text_search_as_plugin.py:117
- The
printcall uses backslash-continued string literals with indentation. In Python, the indentation spaces become part of the string, so the output will include unexpected whitespace. Prefer normal string concatenation with explicit\n.
print(
"Welcome to the chat bot!\
\n Type 'exit' to exit.\
\n Try to find out more about the inner workings of Semantic Kernel."
)
python/semantic_kernel/connectors/exa.py:221
- The request header key
user_agentis not a standard HTTP header name; if the intent is to send a User-Agent, it should beUser-Agent(orsemantic_kernel.const.USER_AGENT). Using the wrong header name means the User-Agent may not be transmitted/recognized by Exa or proxies.
"user_agent": SEMANTIC_KERNEL_USER_AGENT,
Motivation and Context
Semantic Kernel already ships Python
TextSearchconnectors for Brave and Google. This PR adds Exa as another web search option for the same plugin/function calling scenarios, so agents can use Exa's semantic search API!Description
Adds a
ExaSearchTextSearchconnector that callsPOST https://api.exa.ai/search(type: "auto", highlights undercontents).python/semantic_kernel/connectors/exa.pysearch.py/search.pyi.env.exampleentry forEXA_API_KEYSet
EXA_API_KEYand you're good to go!Contribution Checklist