Turning on optional features
Three features reach outside your cluster, so each is off until you turn it on. All of them use services in your own accounts: your cloud’s model service and your own Slack. Nothing goes through awzy.
Each is a variable in the cluster layer’s Terraform (deploy/terraform/bootstrap), applied as in
Installing awzy, step 5.
Awzy Bot and investigations: a model of your choosing
Section titled “Awzy Bot and investigations: a model of your choosing”Both work with any model you can reach: your cloud’s own model service, in the install’s account, with the permissions the cloud layer already gives awzy’s workloads, or another service you add, such as a model you host. On your cloud’s own service, prompts and answers stay in your account.
Set the model in the API it speaks, in that API’s own terms, with llm_model:
On AWS: any model on Amazon Bedrock, through Bedrock’s Converse API. First request access to
the model in the install account’s Bedrock console, in the install’s region. Some models are
reached through a cross-region inference profile, an ID starting us.. Bedrock serves those
from other regions, so if a service control policy denies requests outside the install’s region,
exempt calls through such a profile: add "ArnNotLike": { "bedrock:InferenceProfileArn": "arn:aws:bedrock:*:*:inference-profile/us.*" } to the deny statement’s conditions.
llm_model = { api = "converse", model_id = "us.anthropic.claude-opus-5-5", cache_points = true }On Google Cloud: Gemini needs nothing beyond what the cloud layer sets up (it turns on the
Vertex AI API and lets awzy’s workloads call it). Claude, or another partner model, is enabled
first in the project’s Vertex AI Model Garden. Requests go to Vertex AI’s global endpoint; to
keep them in one region, set the cloud layer’s model_region (for example us-east5).
llm_model = { api = "gemini", model = "gemini-2.5-pro" }# orllm_model = { api = "anthropic_messages", model = "claude-opus-5-5" }Another service: add it with llm_connections and describe its models with llm_routing.
Anything that speaks OpenAI’s chat completions works (vLLM, Ollama, Azure OpenAI), as does
Anthropic’s API, and Vertex AI from another cloud. An API key goes in llm_api_keys, which
bootstrap keeps in a Secret, or comes from a Secret you manage, through llm_api_key_secrets:
llm_connections = { vllm = { kind = "openai", url = "http://vllm.models.svc:8000/v1", api_key_env = "AWZY_LLM_KEY_VLLM" } }llm_api_key_secrets = { AWZY_LLM_KEY_VLLM = { secret = "vllm-key" } }llm_routing = { models = [ { name = "gemini", connection = "cloud", spec = { api = "gemini", model = "gemini-2.5-pro" } }, { name = "llama", connection = "vllm", spec = { api = "openai_chat", model = "meta-llama/Llama-4-Maverick" } }, ] routes = { awzy_bot = { targets = [{ model = "gemini", weight = 9 }, { model = "llama", weight = 1 }], fallback = ["llama"] } investigations = { targets = [{ model = "gemini" }] } }}Vertex AI from outside Google Cloud takes an API key bound to a service account that may call
models (roles/aiplatform.user), made with gcloud services api-keys create --service-account=…:
llm_connections = { vertex = { kind = "vertex", project = "your-project", api_key_env = "AWZY_LLM_KEY_VERTEX" } }llm_api_keys = { AWZY_LLM_KEY_VERTEX = var.vertex_api_key }A route splits a feature’s conversations between models by weight, so you can try a model on a share of them, and falls back in order when a model is busy or down. A routing can only use the connections the install has, so it never sends prompts anywhere you didn’t set up.
Awzy Bot
Section titled “Awzy Bot”The assistant on the client portal’s Policies page, which explains decisions and drafts policies. It only ever drafts: a person publishes.
awzy_bot = trueInvestigations
Section titled “Investigations”A model looks into the principals awzy-reasoner flags. See Investigations.
investigations = trueTwo limits tune them:
investigation_budget = { monthly_tokens = 2000000 privileged_groups = ["it", "security"]}monthly_tokens(2,000,000 by default): the most a calendar month spends. When it’s spent, no new investigation starts until the next month.privileged_groups(itandsecurityby default): members of these groups are only ever proposed for containment, never contained automatically. Name the groups as your IdP sends them.
Turn on automated containments separately, on the Enforcement page, once you trust what they’d do. Until then, a containment an investigation recommends is only recorded.
Slack notifications
Section titled “Slack notifications”People get a direct message when something waits for them: a reason or a security key to give, or an approval to make. Requesters hear when their request is decided. Your security team’s channel hears about approvals, containments, and every break-glass rollback. Messages link into the client portal, and never include document contents or the evidence behind a containment.
-
Create a Slack app in your workspace (api.slack.com/apps). Give its bot token the
chat:writeandusers:read.emailscopes, install it, and copy the bot token (xoxb-…). -
Pick the security team’s channel, invite the app to it, and copy its channel ID (from the channel’s details).
-
Set the variable:
slack = {token = "xoxb-…"security_channel = "C0123ABCD"}Keep the token out of version control, for example in a
.tfvarsfile you don’t commit. It’s stored as a Kubernetes Secret in theawzy-systemnamespace.
awzy finds people in Slack by email: the primary email your IdP provisions for them over SCIM (else their work email), or their user name when it is an email address. Someone with neither doesn’t get direct messages; the security team’s channel still does. Links use the client portal’s public URL, so set its hostname first.