Skip to content

Ask AI

Ask AI answers questions about a resource using only what the asking user can see. It is read-only and off by default. You pick the provider: the Anthropic API, or AWS Bedrock, where data stays in your AWS account and region.

Full reference: docs/install.md, Ask AI in the repository.

How it works

  • The only tools are get_resource, get_events, search_resources and, if you enable it, get_logs. No write tool exists.
  • Every tool call runs as the asking user, through the same RBAC filtering as the UI. The output is redacted (tokens, keys, PEM blocks, URLs with passwords) before it reaches the model.
  • Cluster data is wrapped as untrusted content with a per-request random delimiter. Answers render without images or raw HTML, and suggested commands are copy-only.
  • Each ask is stored in a private thread, so people can come back to it. Press a on a selected resource to ask.

Option A: the Anthropic API

Resource summaries and redacted YAML go to Anthropic. The UI says which provider handles the data.

  1. Create an API key in the Anthropic console, and add it to eddy-credentials under the key ANTHROPIC_API_KEY, with the add-a-key command.
  2. Enable it in hub-values.yaml, then helm upgrade:
    credentialsSecret: eddy-credentialsconfig:ai:enabled: trueprovider: anthropicanthropic:model: claude-haiku-4-5-20251001

The key is read from the variable named by anthropic.apiKeyEnv (default ANTHROPIC_API_KEY). The model defaults to claude-haiku-4-5-20251001.

Option B: AWS Bedrock

Recommended on AWS: there are no static keys, and data stays in your account and region. The hub gets AWS credentials from an AWS IAM role, through IRSA or EKS Pod Identity.

That IAM role is unrelated to the Kubernetes eddy-viewer and eddy-operator roles. Ask AI needs no extra Kubernetes RBAC, because every tool call runs as the asking user.

  1. Check model access. Bedrock models are available by default. For Anthropic models, AWS asks once per account or organization for a use-case form (First Time Use): open the model in the Bedrock console's model catalog. The first call to a third-party model also subscribes the account through AWS Marketplace, which needs aws-marketplace:Subscribe, Unsubscribe and ViewSubscriptions. Make that first call yourself, for example in the playground, so the hub's role needs no Marketplace permissions.
  2. Create an AWS IAM role for the hub pod that the hub's ServiceAccount (eddy-hub in the eddy namespace) can assume. For IRSA, the trust policy is:
    {"Version": "2012-10-17","Statement": [{"Effect": "Allow","Principal": {"Federated": "arn:aws:iam::111122223333:oidc-provider/oidc.eks.eu-central-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE"},"Action": "sts:AssumeRoleWithWebIdentity","Condition": {"StringEquals": {"oidc.eks.eu-central-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": "system:serviceaccount:eddy:eddy-hub","oidc.eks.eu-central-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:aud": "sts.amazonaws.com"}}}]}
    For EKS Pod Identity (with the Pod Identity Agent add-on), trust the Pod Identity service instead, then associate the role with the ServiceAccount:
    {"Version": "2012-10-17","Statement": [{"Effect": "Allow","Principal": {"Service": "pods.eks.amazonaws.com"},"Action": ["sts:AssumeRole", "sts:TagSession"]}]}
    $ aws eks create-pod-identity-association --cluster-name <management-cluster> \--namespace eddy --service-account eddy-hub \--role-arn arn:aws:iam::111122223333:role/eddy-hub-bedrock
  3. Attach a permissions policy that allows bedrock:InvokeModel (it also covers the Converse API the hub uses) on only the inference profile and, through it, the foundation model. The region wildcard covers every region the profile routes to, and the condition keeps it usable only through that profile. An eu. profile stays inside Europe, while a global. profile can route anywhere, so pick a geo or single-region profile if data residency matters. Drop the last statement if you set no guardrail.
    {"Version": "2012-10-17","Statement": [{"Sid": "InvokeViaInferenceProfile","Effect": "Allow","Action": "bedrock:InvokeModel","Resource": "arn:aws:bedrock:eu-central-1:111122223333:inference-profile/eu.anthropic.claude-haiku-4-5-20251001-v1:0"},{"Sid": "InvokeUnderlyingModelOnlyViaThatProfile","Effect": "Allow","Action": "bedrock:InvokeModel","Resource": "arn:aws:bedrock:*::foundation-model/anthropic.claude-haiku-4-5-20251001-v1:0","Condition": {"StringLike": {"bedrock:InferenceProfileArn": "arn:aws:bedrock:eu-central-1:111122223333:inference-profile/eu.anthropic.claude-haiku-4-5-20251001-v1:0"}}},{"Sid": "ApplyGuardrail","Effect": "Allow","Action": "bedrock:ApplyGuardrail","Resource": "arn:aws:bedrock:eu-central-1:111122223333:guardrail/abc123xyz"}]}
    To list the regions explicitly instead, put the ARNs from this command in Resource. The list can change over time:
    $ aws bedrock get-inference-profile --region eu-central-1 \--inference-profile-identifier eu.anthropic.claude-haiku-4-5-20251001-v1:0 \--query 'models[].modelArn'
  4. Annotate the ServiceAccount and enable Bedrock in the hub values. With Pod Identity, leave out the annotation (the association from step 2 does that job):
    serviceAccount:annotations:eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/eddy-hub-bedrockconfig:ai:enabled: trueprovider: bedrockbedrock:region: eu-central-1modelId: eu.anthropic.claude-haiku-4-5-20251001-v1:0   # inference profile id or ARNguardrail: {id: "abc123xyz", version: "1", trace: false}   # optional

region and modelId are required with Bedrock. If Bedrock denies a call, compare the ARNs in the error with your policy, because the regions behind a profile can change.

Which model

Claude is the default and the tested choice. The hub talks to Bedrock through the Converse API with tool use, so other Converse models that support tool use, such as Amazon Nova, should work. They are not tested, so try one on a few real questions before you rely on it, and set modelId to its inference profile.

Guardrails and limits

  • Bedrock Guardrails. Set guardrail.id and version to apply one to each call. trace: true adds the guardrail trace to the response for debugging. The role needs bedrock:ApplyGuardrail on it (the last statement above).
  • Logs are off. config.ai.allowLogs defaults to false. Turn it on only if you want get_logs and log attachments to reach the model.
  • Per-ask limits. Defaults under config.ai.limits: maxRounds: 6 tool rounds, maxToolResultBytes: 24576, maxOutputTokens: 1024, timeout: 60s and perUserPerHour: 30. Over the hourly limit a user gets a rate-limit error.
  • Retention. Ask threads are kept 30 days by default (store.retention.askThreadsDays).

Kill switch

To turn Ask AI off without a restart, set runtimeFlags.aiEnabled: false in the hub values, or patch the flags.yaml key of the eddy-runtime ConfigMap for an immediate change. Ask AI then returns 503 and its button disappears. A flag can only turn a feature off, it cannot enable what config.ai.enabled disables. See Operations.

Verify

  1. Check the install notes. With AI enabled they say Ask AI is enabled with provider …:
    $ helm -n eddy get notes eddy-hub
  2. In the UI, select a resource and press a. Ask why is this not ready? You should get an answer with the tool steps it ran.
  3. The audit log shows the asks with via: askai.

Troubleshooting

  • The hub fails to start after enabling. With Bedrock both bedrock.region and bedrock.modelId are required. With Anthropic, check the Secret has ANTHROPIC_API_KEY.
  • Bedrock access denied. The Anthropic use-case form is missing, the first call could not subscribe the account in AWS Marketplace, the role is not attached to the ServiceAccount, or the policy ARNs do not match the profile. Compare the ARNs in the error with the policy.
  • No Ask AI button. It is off in config.ai.enabled or switched off in eddy-runtime.
  • Egress blocked. With networkPolicy on, the default egress allows HTTPS to anywhere. Tighten it only if you allow the provider's endpoints. Pod Identity also needs port 80 to the node-local agent:
    networkPolicy:egress:extra:- to: [{ipBlock: {cidr: 169.254.170.23/32}}]ports: [{port: 80, protocol: TCP}]