config-auth

star 20

Use when working on config loading, authentication, AWS profiles, or data source resolution. Explains the two config systems (TS vs JSON), auth priority, and multi-profile setup.

opensearch-project By opensearch-project schedule Updated 6/2/2026

name: config-auth description: Use when working on config loading, authentication, AWS profiles, or data source resolution. Explains the two config systems (TS vs JSON), auth priority, and multi-profile setup.

Config & Auth Architecture

Agent Health uses two separate config systems for different purposes. Understanding when each applies prevents auth confusion when users have multiple AWS profiles.

Two Config Systems

System File Format Purpose Managed By
Agent/Model Config agent-health.config.ts TS/JS/MJS Agents, models, connectors, hooks, judge User edits manually
Data Source Config agent-health.config.json JSON only OpenSearch credentials (storage + observability) CLI setup-telemetry / Settings UI

Priority for TS/JS config loading (lib/config/loader.ts):

  1. agent-health.config.ts (highest)
  2. agent-health.config.js
  3. agent-health.config.mjs
  4. Built-in defaults — only merged when extends: false is NOT set; setting extends: false in your config disables default merging entirely

Why two systems?

  • TS config can contain executable code (hooks, dynamic values, custom connectors)
  • JSON config stores credentials that the server persists and the Settings UI manages
  • Browser never sees JSON credentials — the server only exposes metadata (endpoint, authType, hasPassword) to the browser; all authenticated requests are proxied server-side

Auth Resolution Per Service

OpenSearch (Storage & Observability)

Resolution order (server/middleware/dataSourceConfig.ts):

  1. agent-health.config.json (file) — highest priority
  2. Environment variables (OPENSEARCH_STORAGE_* / OPENSEARCH_LOGS_*) — fallback
  3. null — features degrade gracefully

JSON config structure:

{
  "storage": {
    "endpoint": "https://search-....es.amazonaws.com",
    "authType": "sigv4",
    "awsProfile": "default",
    "awsRegion": "us-west-2",
    "awsService": "es"
  },
  "observability": {
    "endpoint": "https://search-....es.amazonaws.com",
    "authType": "sigv4",
    "awsProfile": "default",
    "awsRegion": "us-west-2",
    "awsService": "es",
    "tracesIndex": "otel-v1-apm-span-*"
  }
}

Observability config is where Agent Health reads OTel traces from. This is configured by:

  1. npx @opensearch-project/agent-health setup-telemetry (writes to JSON automatically)
  2. Manual edit of agent-health.config.json (add observability block with endpoint + auth)

The tracesIndex field defaults to otel-v1-apm-span-* if omitted. See /instrument-otel skill for the full instrumentation flow.

Auth types (server/services/opensearchClientFactory.ts):

authType Fields needed How it works
none endpoint only No auth headers
basic endpoint, username, password HTTP Basic Auth
sigv4 endpoint, awsRegion, awsService, awsProfile (optional) AWS SigV4 credential chain

SigV4 credential resolution:

// If awsProfile specified → use that profile
// If omitted → use default AWS credential chain
const provider = fromNodeProviderChain({
  ...(config.awsProfile && { profile: config.awsProfile })
});

Bedrock Judge (LLM Evaluation)

Resolution (server/services/bedrockService.ts):

  • Uses AWS SDK default credential chain — picks up whatever AWS_PROFILE is set in the server's environment
  • Region: process.env.AWS_REGION || 'us-west-2'
  • Model: process.env.BEDROCK_MODEL_ID || 'us.anthropic.claude-sonnet-4-5-20250929-v1:0'
  • No explicit awsProfile field — relies on environment

Claude Code Agent (Subprocess)

Resolution (agent-health.config.ts → agent connectorConfig.env):

{
  key: "claude-code",
  connectorConfig: {
    env: {
      CLAUDE_CODE_USE_BEDROCK: "1",
      AWS_PROFILE: "Bedrock",     // ← explicit profile for Claude subprocess
      AWS_REGION: "us-west-2",
    },
  },
}

These env vars are set inside the spawned Claude Code process — isolated from the server's own credentials.


Multi-Profile Setup Pattern

A user with separate profiles for separate concerns:

Purpose AWS Profile Account Used By
OpenSearch reads default 651304888251 Server → agent-health.config.json (awsProfile: "default")
Bedrock judge Bedrock 070785328308 Server env: AWS_PROFILE=Bedrock
Claude Code agent Bedrock 070785328308 TS config: connectorConfig.env.AWS_PROFILE
Telemetry sending (none needed) API Gateway is public (no SigV4 on client)

Problem: The server process can only have ONE AWS_PROFILE env var. If Bedrock judge needs profile "Bedrock" but OpenSearch needs profile "default", you must:

  1. Set AWS_PROFILE=Bedrock for the server (judge uses default chain)
  2. Set "awsProfile": "default" in agent-health.config.json for OpenSearch (explicit override via fromNodeProviderChain({ profile }))

This works because OpenSearch SigV4 uses explicit profile from config, while Bedrock uses ambient credentials from environment.


Key Files

File Purpose
lib/config/loader.ts Load + merge TS/JS config with defaults
lib/config/types.ts AgentHealthConfig, UserAgentConfig, UserModelConfig
server/middleware/dataSourceConfig.ts Resolve OpenSearch config (file → env → null)
server/services/configService.ts Read/write agent-health.config.json
server/services/opensearchClientFactory.ts Build OpenSearch client with correct auth
server/services/bedrockService.ts Bedrock client init (uses ambient AWS creds)
server/config/index.ts Server environment variable defaults
agent-health.config.example.ts Reference TS config

Environment Variables Reference

OpenSearch Storage (fallback when not in JSON):

OPENSEARCH_STORAGE_ENDPOINT=https://...
OPENSEARCH_STORAGE_AUTH_TYPE=sigv4|basic|none
OPENSEARCH_STORAGE_USERNAME=admin
OPENSEARCH_STORAGE_PASSWORD=secret
OPENSEARCH_STORAGE_AWS_REGION=us-west-2
OPENSEARCH_STORAGE_AWS_PROFILE=default
OPENSEARCH_STORAGE_AWS_SERVICE=es|aoss

OpenSearch Observability (fallback when not in JSON):

OPENSEARCH_LOGS_ENDPOINT=https://...
OPENSEARCH_LOGS_AUTH_TYPE=sigv4|basic|none
OPENSEARCH_LOGS_AWS_REGION=us-west-2
OPENSEARCH_LOGS_AWS_PROFILE=default
OPENSEARCH_LOGS_AWS_SERVICE=es|aoss

Bedrock Judge:

AWS_PROFILE=Bedrock          # Profile with Bedrock access
AWS_REGION=us-west-2         # Bedrock region
BEDROCK_MODEL_ID=us.anthropic.claude-sonnet-4-5-20250929-v1:0

Telemetry (Client-side, in shell RC):

CLAUDE_CODE_ENABLE_TELEMETRY=1
OTEL_EXPORTER_OTLP_ENDPOINT=https://<api-gw>.execute-api.<region>.amazonaws.com
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_TRACES_EXPORTER=otlp
OTEL_LOGS_EXPORTER=otlp
OTEL_METRICS_EXPORTER=otlp

Design Principles

  1. JSON for credentials, TS for behavior — never put secrets in TS config (it's committed to git)
  2. Explicit profile winsawsProfile in JSON config overrides ambient AWS_PROFILE
  3. Each service resolves independently — OpenSearch can use profile A while Bedrock uses profile B
  4. Degrade gracefully — missing config means features are unavailable, not errors
  5. Browser never sees secrets — the server proxies all authenticated requests; the browser only receives safe metadata (endpoint URL, authType, hasPassword boolean), never raw credentials
  6. setup-telemetry writes JSON — it's the only automated way to populate credentials
  7. extends: false opts out of defaults — without this flag, built-in defaults are always merged into your config; with it, you take full control of every value
Install via CLI
npx skills add https://github.com/opensearch-project/agent-health --skill config-auth
Repository Details
star Stars 20
call_split Forks 23
navigation Branch main
article Path SKILL.md
More from Creator
opensearch-project
opensearch-project Explore all skills →