API

Agentic search

Agentic search runs a configured reasoning loop over one or more namespaces and returns the same row shape as every other search endpoint. A model reads the query, fans out diverse phrasings in parallel via layer’s scatter/gather, ranks the candidates for relevance, and returns a ranking fused from both signals. It is a better-ranked result set, not a generated answer — the response is the federated query shape, so any client that reads /v2/query reads this with no changes.

The endpoint names a configured Agent in the path. The model, the turn budget, the indices, and the output shaping are bound on that resource, so the request body is just a query, an optional query embedding, and a result count.

POST /v2/agents/{name}/query

Request

response = await client.agent("support-search").query({
    "query": "auth errors after the june upgrade",
    "top_k": 20,
})
response, err := client.Agent("support-search").Query(ctx, &hevlayer.AgentQueryRequest{
    Query: "auth errors after the june upgrade",
    TopK:  20,
})
const response = await client.agent("support-search").query({
  query: "auth errors after the june upgrade",
  top_k: 20,
});
curl -X POST "$LAYER_GATEWAY_URL/v2/agents/support-search/query" \
  -H "Authorization: Bearer $LAYER_GATEWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "auth errors after the june upgrade",
    "top_k": 20
  }'
FieldPurpose
queryThe natural-language query. The agent reformulates it; you do not pre-shape it into a route expression.
vectorOptional. The embedding of query, used for the agent’s semantic recall leg. See Bring your own embedding.
top_kRows to return after fusion.

The model, fan-out, fusion weighting, and output are bound on the Agent, which keeps the request trivial and makes the agent the single source of truth for what a call costs and what it can read. query and vector are the only request inputs, and they are data, not config — there are no per-request overrides of the agent’s configured behavior.

Bring your own embedding

The agent fans out for recall over both routes: a lexical leg on your query text and a semantic leg on a query vector. Layer never embeds query text — you supply the vector, the same bring-your-own-embedding contract as /v2/query. Pass it as vector:

curl -X POST "$LAYER_GATEWAY_URL/v2/agents/support-search/query" \
  -H "Authorization: Bearer $LAYER_GATEWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "auth errors after the june upgrade",
    "vector": [0.0123, -0.0456, 0.0789],
    "top_k": 20
  }'

vector is the embedding of query. The agent uses this one vector for every planned semantic leg — it does not embed the reformulated phrasings, so the vector carries the query’s semantic intent while the text reformulations broaden lexical recall. Embed query with the same model your indices were embedded with, and match their dimensionality.

Omit vector and the agent’s semantic legs fall back to the lexical route: recall runs on the reformulations alone, which is the right behavior when an index has no vector column or you have no embedder on the client.

Response

The response is the federated query shape: rows each carrying $namespace, $rank, and a native $score/$dist, plus a merge block and a namespaces block. The merge names the dual-score fusion.

{
  "rows": [
    { "id": "T-4821", "$namespace": "tickets", "$rank": 1, "$score": 9.7, "subject": "SSO login fails after upgrade" }
  ],
  "merge": { "method": "weighted-rrf", "route": "dual-score" },
  "namespaces": [
    { "namespace": "tickets", "stable_as_of": 1747300000123, "matched": 20 }
  ]
}

By default the response is byte-shape-identical to a federated query: a client cannot tell whether a reasoning loop produced it. Set output.provenance on the agent to surface the scores.

Provenance and trace

With provenance on, the response gains an agent echo and each row carries a $agent field with both scores:

{
  "rows": [
    { "id": "T-4821", "$namespace": "tickets", "$rank": 1, "$score": 9.7,
      "$agent": { "retrievalScore": 3, "relevanceScore": 0.92, "query": "authentication failure post-upgrade", "queryIndex": 0 } }
  ],
  "merge": { "method": "weighted-rrf", "route": "dual-score" },
  "namespaces": [
    { "namespace": "tickets", "stable_as_of": 1747300000123, "matched": 20 }
  ],
  "agent": {
    "turns": 2,
    "deadlineHit": false,
    "recallDepth": 50,
    "relevanceWeight": 0.6,
    "queries": [
      { "namespaces": ["tickets"], "rankBy": "hybridText",
        "query": "authentication failure post-upgrade",
        "filters": { "created_at": { "$gte": "2026-06-01" } } }
    ]
  }
}
FieldMeaning
$agent.retrievalScoreThe row’s rank within the leg that first surfaced it — the per-query position (1-based; lower is better), not the fused-pool rank. With fanout > 1 a row can appear in several legs; this records the first leg’s rank. The fused recall signal is computed separately (RRF over every leg the row appeared in).
$agent.relevanceScoreThe model’s graded relevance for the row (the precision signal).
$agent.queryThe planned variant that first surfaced the row.
$agent.queryIndexZero-based index of that planned variant in agent.queries.
agent.turnsModel turns the call spent.
agent.deadlineHitTrue when the deadline ended the request early and returned the best ranking so far.
agent.queriesThe planned variants: route, reformulated text, and inferred filters.

With output.trace the agent echo also carries the full reasoning trace. The trace is written to the search-history record whether or not it is echoed, so agentic and plain searches share one surface for evaluation.

Auth

Auth follows the same model as the other API endpoints; multi-namespace queries follow federated query auth behavior. A minted key additionally needs an agent.<name> entitlement on its ApiKey to invoke the agent.

Configuration

Everything the request omits is bound on the Agent resource: the model and its credential, the deadline, the indices, the fan-out and fusion weighting, and the output shaping. kubectl get agent -o yaml and client.agent("support-search").apply() are two spellings of the same object.

Validation

ConditionStatus
{name} is not a known, Ready agent404
The minted key lacks the agent.<name> entitlement403
A bound index is outside the key’s namespace grant403
query is empty422
vector is present and its dimensionality does not match the bound indices’ vector schema422
Deadline hit with onDeadline: bestEffort200, best ranking so far, agent.deadlineHit: true
Deadline hit with onDeadline: error504
The provider is unreachable on both primary and fallback502
esc