ワンクリックで
config-auth
// 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.
// 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.
Create a pull request for Agent Health following all compliance requirements. Use after implementing a feature or fix. Handles SPDX headers, DCO signoff, CHANGELOG, and the PR template.
Diagnose and fix bugs in Agent Health. Use when a user reports a bug, failing test, or unexpected behavior. Follows a systematic diagnosis → fix → verify workflow.
Guided feature implementation for Agent Health. Use when a user wants to add a new capability, endpoint, CLI command, or UI component to the Agent Health project. Ensures correct architecture layer, coding conventions, test coverage, and PR readiness.
Add OpenTelemetry instrumentation to an AI agent for Agent Health observability. Use when a user wants to make their agent's traces visible in Agent Health dashboards, or when debugging why traces aren't appearing. Covers span structure, Gen AI semantic conventions, required attributes, and OTLP exporter setup.
Set up an OpenTelemetry collector or OSIS pipeline to route traces from an agent to OpenSearch for Agent Health consumption. Covers OSIS, OTel Collector, and direct export configurations.
Write tests for Agent Health following project conventions. Use when adding tests for new features, bug fixes, or improving coverage. Covers Jest setup, mocking patterns, path aliases, and coverage thresholds.
| 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. |
Agent Health uses two separate config systems for different purposes. Understanding when each applies prevents auth confusion when users have multiple AWS profiles.
| 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):
agent-health.config.ts (highest)agent-health.config.jsagent-health.config.mjsextends: false is NOT set)Why two systems?
Resolution order (server/middleware/dataSourceConfig.ts):
agent-health.config.json (file) — highest priorityOPENSEARCH_STORAGE_* / OPENSEARCH_LOGS_*) — fallbackJSON 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:
npx @opensearch-project/agent-health setup-telemetry (writes to JSON automatically)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 })
});
Resolution (server/services/bedrockService.ts):
AWS_PROFILE is set in the server's environmentprocess.env.AWS_REGION || 'us-west-2'process.env.BEDROCK_MODEL_ID || 'us.anthropic.claude-sonnet-4-5-20250929-v1:0'awsProfile field — relies on environmentResolution (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.
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:
AWS_PROFILE=Bedrock for the server (judge uses default chain)"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.
| 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 |
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
awsProfile in JSON config overrides ambient AWS_PROFILEsetup-telemetry writes JSON — it's the only automated way to populate credentials