Exa (tracing)
Exa provides search, contents, grounded-answer, tool, and Agent APIs. Respan’s native Exa instrumentations turn those SDK calls into connected OpenTelemetry spans with provider-neutral names and canonical Respan metadata.
Set up Respan
Create an account at platform.respan.ai and grab an API key.
Run npx @respan/cli setup to set up with your coding agent.
Package source and example projects
The first release of the Python respan-instrumentation-exa package is pending and is not currently available from PyPI. The Python installation steps below use a Respan source checkout. The JavaScript @respan/instrumentation-exa package is available from npm.
This is an SDK tracing integration, not a Respan Gateway provider route. Respan Gateway does not currently route Exa search, contents, answer, Agent, or Research APIs. EXA_API_KEY is used directly by the official Exa SDK; RESPAN_BASE_URL configures trace export only.
The Python package requires Python >=3.11,<3.14, supports exa-py>=2.20.0,<3.0.0, and is tested with exa-py==2.20.0. The JavaScript package requires Node.js 18 or newer, supports exa-js>=2.19.0 <3.0.0, and is tested with the npm-stable exa-js@2.19.0.
Setup
Python
JavaScript
Initialize Respan and call Exa
Initialize the explicit instrumentor before making Exa SDK calls, and shut Respan down when the application exits so pending spans are flushed.
View your trace
Open the Traces page and inspect the tool.search span, its input and output, status, timing, and Exa metadata.
Captured SDK surfaces
The integration is explicit-only: pass ExaInstrumentor in instrumentations as shown above. Exa can execute OpenAI or Anthropic tool adapters internally, so it is not enabled as direct-LLM auto-instrumentation.
Native SDK operation names, language, stream state, result counts, request IDs, resolved search type, cost, citations, and legacy Research markers are stored in the canonical respan.metadata JSON attribute. Successful and failed calls also retain their real status and error information. API keys and authorization-like fields are always redacted.
Streaming lifecycle
Streaming spans end when the iterator is exhausted, iteration raises an error, or the iterator is explicitly closed. JavaScript early exit from a for await loop calls the wrapped iterator’s return() and closes the span. Python exposes the SDK’s close behavior through the wrapped iterator, including the synchronous close() method on exa-py 2.20 async stream response objects.
If an application abandons a stream without exhausting or closing it, the instrumentation cannot record an exact completion timestamp. Always exhaust the stream or close it explicitly.
Content and privacy controls
Request and response content is captured by default. Disable it per instrumentor:
Or disable content capture for the process:
With content capture disabled, query, result, prompt, completion, citation, and stream payloads are omitted. Operation, stream state, status, timing, and other non-content metadata remain available.
Limitations
- Websets, Search Monitor CRUD, and beta Agent Monitor operations are not patched; they are long-lived control-plane APIs rather than in-process AI operations.
exa-js@2.19.0supports coregetContents(), but does not ship atools.getContents()helper. The Python 2.20 SDK does shiptools.get_contents().- Legacy Research remains instrumented for compatibility, but Exa recommends deep search (
type="deep-reasoning") for new research flows. - Helper calls are deduplicated against the core SDK methods they invoke; activating overlapping provider instrumentations may still add their own lower-level model spans.