Operations

Agent CRD

An Agent is a saved agentic-search configuration as a resource. It binds an inference model, a turn budget, and a set of indices to a name, so a caller searches with POST /v2/agents/{name}/query and sends only a query string. Everything that decides what a call costs and what it can read lives on the resource, not in the request.

An agent adds no retrieval primitive. Its only tool is the federated query; it sits one level above the Auto router, using a model to reformulate the query, fan out for recall, and score the candidates for relevance. What it returns is the same row shape as every other search endpoint — a better-ranked result set, not a generated answer.

Like the other CRDs here, an Agent has two authoring surfaces that round-trip through one schema: kubectl get agent -o yaml and client.agent("support-search").apply() are two spellings of the same object.

apiVersion: hevlayer.com/v1alpha1
kind: Agent
metadata:
  name: support-search
  namespace: layer
spec:
  model:
    provider: openrouter
    name: anthropic/claude-haiku-4-5
    fallback: anthropic/claude-sonnet-4-6   # optional; used on primary timeout/error
    apiKeySecretRef:
      name: openrouter
      key: credential
  budget:
    deadlineMs: 60000
    onDeadline: bestEffort
  indices: [docs, tickets]
  retrieval:
    fanout: 8
    recallDepth: 50
    rankBy: auto
    relevanceWeight: 0.6
  output:
    provenance: false
    trace: false
status:
  phase: Ready
  conditions:
    - type: SecretResolved
      status: "True"
    - type: ModelReachable
      status: "True"
    - type: IndicesResolved
      status: "True"

Model

FieldPurpose
providerInference backend. openrouter.
nameModel id passed to the provider, e.g. anthropic/claude-haiku-4-5.
fallbackOptional model used when the primary times out or errors.
apiKeySecretRefSecret holding the provider credential (name, key). The token is never inline on the resource — the same rule the ApiKey and VectorStore CRDs follow.

Budget

FieldPurpose
deadlineMsWall-clock deadline for the whole request.
onDeadlinebestEffort (default) returns the best ranking the agent has when the deadline hits; error fails the request instead.

Indices

indices is the set of namespaces the agent searches, passed to the federated query as its namespaces. The operator checks that the list is present and every entry is a non-empty string, surfaced as the IndicesResolved condition; it does not currently confirm each entry names a namespace that exists. The agent reads each listed namespace under the caller’s credential, so a caller only reaches the namespaces its own key grants.

Retrieval

All retrieval behavior is expressed against the federated query — nothing new reaches the upstream.

FieldDefaultPurpose
fanout8Query reformulations the agent issues, run in parallel via layer’s scatter/gather and merged for recall. Higher fan-out trades latency for recall.
recallDepth50Candidates gathered for ranking before top_k, at least top_k. Bounds how much the model reads.
rankByautoDefault route per leg: auto, hybridText, or semantic. A semantic leg needs a query vector, which the caller supplies on the request (vector) — layer never embeds query text; see Agentic search. Without a supplied vector, semantic legs fall back to the lexical route.
relevanceWeight0.6Weight of the relevance score against the recall score in the final ranking.

Output

FieldPurpose
provenanceWhen true, each row carries a $agent field with its retrievalScore and relevanceScore, and the response gains a top-level agent echo.
traceWhen true, the agent echo also carries the full reasoning trace.

Default off, the response is byte-for-byte the federated query shape: a client cannot tell a reasoning loop produced it.

See Agentic search for the request and response contract.

Auth

Auth follows the same model as the other API endpoints; multi-namespace queries follow federated query auth behavior. Who may invoke an agent is an agent.<name> entitlement on the ApiKey.

Status

status carries health and validation only; latency, turn counts, and spend go to metrics and history, never into etcd.

ConditionMeaning
SecretResolvedmodel.apiKeySecretRef exists and is readable.
ModelReachablethe provider answered with the bound credential.
IndicesResolvedspec.indices is non-empty and every entry is a non-empty string. (It does not yet verify each entry is a known namespace.)
PhaseMeaning
ReadyResolvable and callable.
DegradedReachable but a condition is failing — calls may fall back or error.
InvalidA required field or reference does not resolve; calls are refused.

kubectl get agent print columns: MODEL, INDICES, PHASE.

Edits are picked up shortly after they apply: the gateway resolves agents — spec, provider credential, and per-index schema — into memory and refreshes on a periodic tick, so a kubectl apply lands within the refresh interval rather than instantly.

Naming

Agent names are cluster-unique at the gateway because callers address agents by name only. If two namespaces define the same Agent name, the gateway sorts by agent name and namespace, keeps the lexicographically later namespace, and logs a warning naming both namespaces. Keep Agent names unique across the cluster.

Observability

Deadline-hit rate, provider latency, and token usage per agent export as hevlayer_* metrics. Token counts come back on the inference response, so they cost no extra call; dollar cost is derived from them downstream rather than fetched in the request path. The reasoning trace is written to the search-history record alongside the query it belongs to, so agentic and plain searches share one history surface for evaluation.

esc