> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rootly.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Private Agent for Elasticsearch and OpenSearch (Early Access)

> Query private Elasticsearch and OpenSearch instances through bounded, read-only AI SRE tools.

<Warning>
  **Early Preview:** Rootly Private Agent is under active development and available only to approved customers. Features, configuration, limits, and APIs may change before general availability. Confirm the approved agent and backend versions with your Rootly representative before production use.
</Warning>

Rootly Private Agent connects AI SRE to private Elasticsearch and OpenSearch clusters without exposing those clusters publicly. The native adapter calls the configured REST endpoint from inside your network. It is a bounded diagnostic client, not a generic HTTP proxy.

Elasticsearch and OpenSearch are separate provider types. Configure each cluster as a separate instance with a stable ID that is unique across every provider in your Rootly account so AI SRE can route a query to the intended product and environment.

<Info>
  Search support requires matching early-access agent, Rootly backend, and Helm chart builds. Confirm availability with your Rootly representative before changing an existing installation.
</Info>

## Configure Elasticsearch

The following Helm values mount an existing Kubernetes Secret and configure one Elasticsearch instance. The Secret must contain an `api-key` key. Do not place the API key itself in Helm values.

```yaml theme={null}
providers:
  elasticsearch:
    - id: elastic-logs-production
      url: https://elasticsearch.production.internal
      api_key_file: /run/secrets/elasticsearch/api-key
      allowed_indices:
        - logs-production-*
        - traces-production-*
      excluded_source_fields:
        - authorization
        - http.request.headers.cookie
      timestamp_field: "@timestamp"
      query_language_enabled: false
      policy:
        maximum_concurrency: 2
        maximum_result_bytes: 262144
        maximum_documents: 100
        maximum_indices: 100
        maximum_shards: 200
        maximum_range_seconds: 3600
        maximum_timeout_seconds: 15
        maximum_query_bytes: 32768

extraVolumes:
  - name: elasticsearch-credentials
    secret:
      secretName: elasticsearch-credentials

extraVolumeMounts:
  - name: elasticsearch-credentials
    mountPath: /run/secrets/elasticsearch
    readOnly: true
```

Use `api_key_file`, `bearer_token_file`, or `username_file` together with `password_file`. Configure only one HTTP authentication method per instance. Credential files are read for each request, so projected Secret rotation does not require changing the YAML.

Credential and TLS paths must be absolute and resolve to regular files. Kubernetes projected-volume symlinks are supported when they resolve to regular files; named pipes, devices, and directories are rejected.

<Warning>
  The agent image runs as UID/GID `65532`. For Kubernetes Secret volumes using mode `0440`, set Pod-level `securityContext.fsGroup: 65532`. Give only the agent identity equivalent read access on other platforms; do not make secret files world-readable.
</Warning>

## Configure OpenSearch

Self-managed OpenSearch supports the same bearer, basic, custom-CA, and mTLS options. Amazon OpenSearch Service and OpenSearch Serverless can use the AWS SDK credential chain instead:

```yaml theme={null}
serviceAccount:
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/rootly-private-agent

providers:
  opensearch:
    - id: opensearch-logs-production
      url: https://search-production.us-west-2.es.amazonaws.com
      allowed_indices:
        - logs-production-*
      excluded_source_fields:
        - authorization
      timestamp_field: "@timestamp"
      query_language_enabled: false
      aws_sigv4:
        region: us-west-2
        service: es
```

Use AWS SigV4 service `es` for a managed domain and `aoss` for a Serverless collection. On EKS, the ServiceAccount annotation can supply short-lived credentials through IRSA. The default AWS credential chain also supports environment credentials, shared configuration, and ECS task roles. AWS credential-provider calls such as STS or SSO use standard AWS SDK proxy behavior; requests to the configured search endpoint require direct customer-network routing and do not inherit proxy settings. Do not combine SigV4 with HTTP authentication.

For a managed Amazon OpenSearch domain, configure both AWS authorization layers:

1. Grant the ECS task role or IRSA role the signed HTTP methods used by the adapter (`GET`, `HEAD`, and `POST`) on the intended domain.
2. In OpenSearch fine-grained access control, map that IAM role ARN as a backend role to a dedicated read-only OpenSearch role scoped to the same index patterns.

If either layer is missing, OpenSearch returns `403` even when SigV4 signing succeeds. Serverless collections use an AWS data access policy instead of the managed-domain backend-role mapping. Do not use the domain master user or map the agent to an administrative OpenSearch role.

Use an Elasticsearch, OpenSearch, or AWS role that can read only the intended indices. The agent's `allowed_indices` is defense in depth, not a replacement for upstream authorization.

## Set the local index boundary

Every instance requires one to 64 `allowed_indices` expressions with a 4 KiB combined expression budget. An invocation can request a concrete index matched by a configured wildcard. If it requests a wildcard, that wildcard must exactly match one configured locally. AI SRE cannot supply a new hostname, credential, timestamp field, or broader index scope. Before dispatching any capability, the agent resolves its authorized expression with `_search_shards` and rejects expansions beyond `maximum_indices` or `maximum_shards`; this also bounds metadata and health operations. Grant the agent's read-only search role access to that API. OpenSearch Serverless uses `_resolve/index` to enforce its advertised index ceiling because it does not expose a shard ceiling; its data access policy must grant equivalent index-description access. Do not configure `maximum_shards` for an `aoss` provider—the agent rejects that ineffective setting during startup.

`excluded_source_fields` removes fields from every Query DSL search response. A query, aggregation, or field selection that explicitly references an excluded field is rejected. Use it for credentials, cookies, request bodies, or other data that an investigation never needs. Field exclusion is not value redaction; do not grant an index when its remaining documents are too sensitive to enter AI context and investigation history.

URLs must use HTTPS and cannot contain credentials, query parameters, or fragments. `ca_bundle_file` extends system trust for a private CA. `client_certificate_file` and `client_key_file` enable mTLS. Certificate and hostname validation remain enabled. Plain HTTP requires `allow_insecure_http: true` and is intended only for isolated local testing.

## Tools and arguments

All search capabilities are version `1` sensitive reads and initially require a Rootly owner or admin.

| Capability           | Required arguments               | Optional arguments                                   |
| -------------------- | -------------------------------- | ---------------------------------------------------- |
| `list_indices`       | None                             | `index`, `limit`                                     |
| `list_data_streams`  | None                             | `index`, `limit`                                     |
| `get_mapping`        | `index`                          | None                                                 |
| `search`             | `index`, `query`, `start`, `end` | `aggregations`, `fields`, `limit`, `timeout_seconds` |
| `count`              | `index`, `query`, `start`, `end` | `timeout_seconds`                                    |
| `cluster_health`     | None                             | `index`                                              |
| `get_shards`         | None                             | `index`, `limit`                                     |
| `elasticsearch.esql` | `query`                          | `limit`, `timeout_seconds`                           |
| `opensearch.ppl`     | `query`                          | `limit`, `timeout_seconds`                           |

The two native-language rows are advertised only when `query_language_enabled: true`. The other suffixes use the configured provider's prefix. When `index` is omitted from `list_indices`, `list_data_streams`, `cluster_health`, or `get_shards`, the agent substitutes every locally configured allowlist expression; it never requests unscoped cluster-wide data.

For example, a bounded Elasticsearch document query uses `elasticsearch.search`:

```json theme={null}
{
  "index": "logs-production-*",
  "query": {
    "bool": {
      "filter": [
        { "term": { "service.name": "checkout" } }
      ],
      "must": [
        { "match": { "message": "timeout" } }
      ]
    }
  },
  "fields": ["@timestamp", "service.name", "message"],
  "start": "2026-09-19T10:00:00Z",
  "end": "2026-09-19T10:15:00Z",
  "limit": 50,
  "timeout_seconds": 15
}
```

The adapter adds a mandatory range filter using `timestamp_field`. A future start is rejected, a future end is capped to the current clock, and the requested range cannot exceed local policy. Search results are newest first. Timed-out, partial, truncated, or oversized responses fail instead of supplying incomplete evidence.

Scripts, script fields, runtime mappings, percolator, stored or secondary-source queries, `query_string`, `simple_query_string`, multi-search, explain, arbitrary REST requests, writes, deletes, and cluster administration are not available. The free-form query-string grammars are always rejected because the adapter does not parse their field and source references.

## Optional ES|QL and PPL

`query_language_enabled: true` advertises `elasticsearch.esql` or `opensearch.ppl`. It is disabled by default. The adapter requires the pipeline to begin with one locally allowed source, rejects joins and secondary sources, and enforces row, byte, timeout, and query-size limits. PPL accepts the standard `search source=<index>` form or the equivalent form with `search` omitted.

Native query languages cannot be enabled with `excluded_source_fields`, because enforcing field exclusions across their complete grammars requires a dialect parser. They also do not receive the Query DSL tool's mandatory timestamp filter. Enable them only when the additional expressiveness is required and the configured index boundary is sufficient.

## Health, routing, and compatibility

Readiness verifies the product identity and performs small `HEAD` access probes against locally allowed index patterns until one is accessible. The last successful expression is tried first; otherwise at most eight probes run concurrently so a long allowlist does not consume the readiness budget serially. It does not enumerate every matching index or spend the query result budget, but the configured identity must be able to perform that metadata request on at least one pattern. OpenSearch Serverless does not expose the same root product-identity response, so its readiness check instead validates `aoss` configuration, SigV4 authentication, and signed access to an allowed index. An Elasticsearch endpoint cannot be registered as OpenSearch or vice versa. If one instance becomes unhealthy, other provider instances remain independently routable.

The pull-request compatibility gate runs every capability against digest-pinned Elasticsearch 8.19 and 9.5 images and OpenSearch 2.19 and 3.8 images. A scheduled historical-edge matrix also exercises the shared REST tools against Elasticsearch 8.0 and 9.0 plus OpenSearch 2.0 and 3.0. Native ES|QL and PPL are not claimed for those historical edge versions because availability changed within major releases.

This matrix verifies API behavior, not production capacity. See [Private Agent Limits](/private-agent-limits#elasticsearch-and-opensearch) and test representative query latency and result cardinality before increasing local budgets.
