Observation & data

Semantic search over what you ingested

Embeds your question and returns the top-k most similar chunks from the content store, each with its source URL, title and similarity score.

etl_query

What it is

The job: Ask a question of the content you ingested, and get back the passages that answer it.

The read half of the ETL pipeline. Your query is embedded with the same model that embedded the chunks, and the top-k nearest are returned with the source url and title attached — so a citation is always available and you are never handed a passage you cannot trace.

Scope to a `collection` to search one corpus rather than everything you have ever ingested. k defaults to 8 and goes to 50.

It returns chunks, not an answer. Composing them into a response is your model’s job — which is the right split, because it keeps the retrieval step cheap, flat-priced and inspectable.

The call

Call it exactly like this.

Copied from the tool's registration and the route handler — not paraphrased.

MCPetl_query.mcp.jsonjson
// MCP tool call — server "twin-browser"
{
  "tool": "etl_query",
  "arguments": {
    "query": "how do I rotate an API key?",
    "collection": "example-docs",
    "k": 8
  }
}
POST /api/v1/etl/queryrequest.shbash
curl -X POST https://twin-browser.com/api/v1/etl/query \
  -H "Authorization: Bearer $TWIN_API_KEY" \
  -H "content-type: application/json" \
  -d '{"query":"how do I rotate an API key?","collection":"example-docs","k":8}'
Parameters accepted by etl_query
ParameterTypeWhat it does
query*stringThe natural-language query to match against stored content.
knumberNumber of chunks to return, 1–50. Default 8.
collectionstringCollection namespace to scope the search to.

Returns

response.jsonjson
{
  "matches": [
    { "content": "…", "url": "https://example.com/docs/keys", "title": "API keys",
      "similarity": 0.83, "document_id": "…", "chunk_index": 3 }
  ],
  "credits_charged": 1
}

What it costs

1 credit

Flat, regardless of k. Retrieval is an embedding plus a vector search — there is no generation step to meter, which is why the price does not move with the size of the result.

See the full rate card

Which one

When a different tool is the right call.

The honest answer is often the neighbouring tool. These are the trades.

search_library

Both are semantic searches and they search entirely different things: etl_query searches content you ingested, search_library searches the shared corpus of compiled automation skills.

search_library
search

search goes out to the live web. etl_query stays inside your own store. Use search to discover, etl_query to recall.

search

Questions

etl_query, answered.

Why does it return chunks instead of an answer?
Because retrieval and generation are different products and pricing them together hides both. You get the passages, their sources and their similarity scores; your own model composes the answer with whatever prompt and citation policy you already use.