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
}' | Field | Purpose |
|---|---|
query | The natural-language query. The agent reformulates it; you do not pre-shape it into a route expression. |
vector | Optional. The embedding of query, used for the agent’s semantic recall leg. See Bring your own embedding. |
top_k | Rows 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" } } }
]
}
}
| Field | Meaning |
|---|---|
$agent.retrievalScore | The 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.relevanceScore | The model’s graded relevance for the row (the precision signal). |
$agent.query | The planned variant that first surfaced the row. |
$agent.queryIndex | Zero-based index of that planned variant in agent.queries. |
agent.turns | Model turns the call spent. |
agent.deadlineHit | True when the deadline ended the request early and returned the best ranking so far. |
agent.queries | The 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
| Condition | Status |
|---|---|
{name} is not a known, Ready agent | 404 |
The minted key lacks the agent.<name> entitlement | 403 |
| A bound index is outside the key’s namespace grant | 403 |
query is empty | 422 |
vector is present and its dimensionality does not match the bound indices’ vector schema | 422 |
Deadline hit with onDeadline: bestEffort | 200, best ranking so far, agent.deadlineHit: true |
Deadline hit with onDeadline: error | 504 |
| The provider is unreachable on both primary and fallback | 502 |