Skip to content

feat(opencode): route websearch Exa through Kilo proxy - #12470

Merged
marius-kilocode merged 1 commit into
Kilo-Org:mainfrom
IamCoder18:feat/kilo-exa-websearch
Jul 29, 2026
Merged

feat(opencode): route websearch Exa through Kilo proxy#12470
marius-kilocode merged 1 commit into
Kilo-Org:mainfrom
IamCoder18:feat/kilo-exa-websearch

Conversation

@IamCoder18

Copy link
Copy Markdown
Contributor

Issue

Closes #12469

Context

The websearch tool currently has no integration with Kilo auth. When the session routes to the Exa provider, requests fall through to the public https://mcp.exa.ai/mcp endpoint, unauthenticated by default, or via EXA_API_KEY query-param BYOK if the user set it. Kilo-authenticated users have no way to route web searches through their Kilo account, and there's no env override to force a Kilo-billed transport.

This adds a third transport: kilo-rest, that POSTs to https://app.kilo.ai/api/exa/search with the user's Kilo API key as a Bearer token. The cloud proxy injects its own Exa API key server-side. Result clamping at 10 is added across all Exa transports to keep cost predictable (Exa's first 10 results are $0.007 flat).

Implementation

callKiloExa lives in packages/opencode/src/kilocode/tool/websearch-kilo-exa.ts. It posts a small JSON body with the query, type, numResults, and a highlights-only contents field to Exa's REST search endpoint via the supplied HTTP client, decodes the response into a numbered title/url/date/highlight block, clamps numResults at 10, and dies on 401/403/5xx/timeout with actionable messages.

The upstream change to packages/opencode/src/tool/websearch.ts is small. Add kilo-exa to the provider enum so the env override is routable, yield Auth.Service to source the Kilo bearer, compute a transport with the precedence below, and dispatch to callKiloExa when transport is kilo-rest, otherwise the existing callProvider runs unchanged. mcp-websearch.ts and websearch.txt are not touched.

  • Transport precedence, highest first: kilo-exa forces kilo-rest (auth required); parallel forces mcp-parallel; exa plus EXA_API_KEY forces mcp-exa-byok so BYOK wins; exa plus a Kilo token uses kilo-rest; exa with no auth falls back to mcp-exa-unauth.
  • MCP-Exa numResults is clamped at 10, default stays 8. The transport value is added to tool-part metadata.

Screenshots / Video

image

Full conversation:
https://app.kilo.ai/s/a7257bae-8a45-48ac-a916-ce55c2a30779

How to Test

  1. Sign in with kilo auth login.
  2. Start a session and call the websearch tool with any query.
  3. Confirm the agent calls Exa, gets highlights (at no cost), and has a maximum allowed 10 request count.

Checklist

  • Issue linked above, or exception explained
  • Tests/verification described
  • Screenshots/video included for visual changes, or marked N/A
  • Changeset considered for user-facing changes
  • I personally reviewed the diff and can explain the changes, including any AI-assisted work.

Get in Touch

Discord: @IamCoder18

Add a new Kilo-REST Exa transport alongside the existing MCP-Exa
and MCP-Parallel transports. When the websearch tool picks the Exa
provider and the user is signed into Kilo, requests go to
https://app.kilo.ai/api/exa/search with the user's Kilo bearer.
The cloud proxy injects its own Exa API key; the client sends the
user's Kilo API key as a Bearer token. The MCP-BYOK path (EXA_API_KEY)
and MCP-unauthed fallback are preserved unchanged.

Changes:
* New `packages/opencode/src/kilocode/tool/websearch-kilo-exa.ts`
  implements `callKiloExa` against the Exa REST API
  (`POST /search`) with `{ highlights: true }` contents and clamps
  numResults at 10 (Exa's first-10-results flat $0.007 tier).
* `packages/opencode/src/tool/websearch.ts` adds a `"kilo-exa"`
  provider variant (selected only via `KILO_WEBSEARCH_PROVIDER`
  override), an Auth.Service yield to source the Kilo bearer, a
  transport-dispatch block that prefers Kilo-REST over MCP when
  auth is available and EXA_API_KEY is unset, and `transport`
  metadata on the tool part. MCP-Exa numResults is now clamped
  at 10 (default stays 8).
* 13 unit tests in
  `packages/opencode/test/kilocode/tool/websearch-kilo-exa.test.ts`
  cover request shape, response formatting, error handling, and
  the costDollars ignore case.
* Parameters snapshot updated for the new numResults description
  string.
* Patch-level changeset added.

@marius-kilocode marius-kilocode left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested end to end against the live backend: unit tests and typecheck pass, direct client calls to api.kilo.ai/api/exa/search return highlighted results with the numResults clamp working, and a full kilo run session routes Exa search through the Kilo proxy with the stored oauth token. Cloud side has been live with auth, free allowance, and credit billing for months. LGTM.

@marius-kilocode
marius-kilocode merged commit c0ebf98 into Kilo-Org:main Jul 29, 2026
29 checks passed
@marius-kilocode

marius-kilocode commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Thanks for this one @IamCoder18

unixcrh pushed a commit to unixcrh/kilocode that referenced this pull request Aug 1, 2026
t7tran pushed a commit to t7tran/kilocode that referenced this pull request Aug 14, 2026
t7tran pushed a commit to t7tran/kilocode that referenced this pull request Aug 14, 2026
Add a new Kilo-REST Exa transport alongside the existing MCP-Exa
and MCP-Parallel transports. When the websearch tool picks the Exa
provider and the user is signed into Kilo, requests go to
https://app.kilo.ai/api/exa/search with the user's Kilo bearer.
The cloud proxy injects its own Exa API key; the client sends the
user's Kilo API key as a Bearer token. The MCP-BYOK path (EXA_API_KEY)
and MCP-unauthed fallback are preserved unchanged.

Changes:
* New `packages/opencode/src/kilocode/tool/websearch-kilo-exa.ts`
  implements `callKiloExa` against the Exa REST API
  (`POST /search`) with `{ highlights: true }` contents and clamps
  numResults at 10 (Exa's first-10-results flat $0.007 tier).
* `packages/opencode/src/tool/websearch.ts` adds a `"kilo-exa"`
  provider variant (selected only via `KILO_WEBSEARCH_PROVIDER`
  override), an Auth.Service yield to source the Kilo bearer, a
  transport-dispatch block that prefers Kilo-REST over MCP when
  auth is available and EXA_API_KEY is unset, and `transport`
  metadata on the tool part. MCP-Exa numResults is now clamped
  at 10 (default stays 8).
* 13 unit tests in
  `packages/opencode/test/kilocode/tool/websearch-kilo-exa.test.ts`
  cover request shape, response formatting, error handling, and
  the costDollars ignore case.
* Parameters snapshot updated for the new numResults description
  string.
* Patch-level changeset added.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Web search tool silently bypasses Kilo auth, hitting public Exa MCP unauthenticated

2 participants