feat: add Exa AI-powered search tool#90
Open
tgonzalezc5 wants to merge 1 commit into1jehuang:masterfrom
Open
Conversation
Adds a dedicated `exa_search` tool that calls the Exa Search API and returns ranked results with optional highlights, page text, and LLM summaries. Sits alongside the existing DuckDuckGo `websearch` tool rather than replacing it, so neither path changes for users without an Exa key. Reads `EXA_API_KEY` from the environment at execute time and returns a clear error when it is missing, rather than failing at registration. Sets the `x-exa-integration: jcode` header on every request so usage can be attributed to this integration. Exposes the search-tuning surface as JSON-schema parameters: search type, category, include/exclude domains, published-date range, user location, and per-result content controls (text/highlights/summary). Snippet rendering cascades summary -> highlights -> truncated text so output is useful regardless of which contents flags the caller passes. Tests cover response parsing (full and minimal), the snippet fallback ladder, contents-builder defaults, and the missing-key error path.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
exa_searchtool backed by the Exa Search API, sitting alongside the existing DuckDuckGowebsearchtool.type,category,include_domains/exclude_domains, published-date range,user_location, and per-resultcontents(text / highlights / summary).EXA_API_KEYlazily at execute time so the tool registers unconditionally and returns a clear, actionable error when the key is unset.x-exa-integration: jcodeon every request so API usage can be attributed to this integration.Why a separate tool
websearchscrapes DuckDuckGo HTML and has no API key, no provider abstraction, and no per-result content control. Bolting Exa-specific knobs (search type, category, content modes) onto it would either dilute its parameter surface or create a hidden coupling between it and an unrelated provider. A dedicatedexa_searchtool keeps the existing tool unchanged and gives the agent a clear way to opt in when an Exa key is configured.Usage
The tool POSTs to
https://api.exa.ai/search, parses the response into typed Rust structs, and renders a numbered result list. Each rendered result picks the best available snippet via asummary -> highlights -> truncated textcascade, so the output stays useful regardless of whichcontentsflags the caller sets.Files changed
src/tool/exa_search.rs(new) — tool implementation, request/response types, formattersrc/tool/exa_search_tests.rs(new) — unit tests (response parsing, snippet fallback ladder, contents-builder defaults, missing-key error)src/tool/mod.rs— register the new tool inbase_toolsNo new crate dependencies; reuses
reqwest,serde,serde_json,async-trait, andcrate::provider::shared_http_client()already in the workspace.Test plan
cargo check --bin jcodepasses (no new warnings introduced)cargo test --lib --bin jcode exa_search— 14 / 14 passcargo test --lib --bin jcode tool::tests— 14 / 14 pass (registry sort and schema validators still green with the new tool registered)api.exa.aiwith a realEXA_API_KEY(not run in this PR; covered by parsing tests against a captured response shape)Notes / tradeoffs
contentsschema is permissive:textandsummaryaccept eithertrueor an object with extra knobs (max_characters,query). The serializer collapses empty/no-op shapes so we never send{}to the API.{ "query": "..." }call still returns useful, bounded output.websearch. Happy to wire Exa in as awebsearchbackend instead if you'd prefer a single tool surface — let me know.Need help on this PR? Tag
@codesmithwith what you need.