# Nirmata AIControls — Full Documentation > Complete content of the AIControls documentation in Markdown, one file, optimized for AI-tool ingestion (IDE agents, RAG pipelines). Curated page index: https://docs.aicontrols.dev/llms.txt --- ## Nirmata AIControls Source: https://docs.aicontrols.dev/docs > Nirmata AIControls — governance for every AI call your team makes. AIControls is a governance layer that sits between your developers and their AI tools — visibility, cost control, and policy enforcement on every AI call, without changing how developers work. ### What it does AIControls intercepts two types of traffic from AI coding tools (Claude Code, Cursor, Codex, Copilot): **LLM calls** to model APIs (Anthropic, OpenAI, Azure OpenAI, Bedrock) and **MCP tool calls** to backend servers (bash, file system, kubectl, databases, and any custom MCP server). Both pass through the same governance pipeline before reaching their destination: - **Identity** — every request is authenticated and attributed to a developer or agent via your IdP or workspace tokens. - **Policy enforcement** — CEL-based rules allow, deny, mutate, or route requests for human approval, evaluated inline. - **Content safety** — PII, secrets, and prompt injection patterns are detected before tokens are sent. - **Budgets** — spend limits per organization, team, or developer, enforced at request time. - **Audit log** — every prompt, tool call, response, model, token count, and policy decision recorded. - **Intelligence** — session summaries, behavioral baselines, anomaly detection, risk scores, and context optimization that reduces token waste. ### How it works Your workspace comes with a proxy endpoint. You configure each AI tool to route through that endpoint instead of calling the provider directly. AIControls holds your API keys — developers use workspace-issued credentials, so provider keys never live on developer machines. No agents to install. No SDKs to integrate. One endpoint, all tools. [Get started →](https://docs.aicontrols.dev/docs/getting-started) ### Explore the docs ⚡ Getting Started Connect your team — cloud-hosted SaaS or self-hosted in your own Kubernetes cluster. Start here → 📖 Concepts How AIControls works — upstreams, identity, cost governance, security, policies, and MCP. Read concepts → 🛠 Tasks Step-by-step instructions for connecting tools and configuring governance. Read tasks → 📋 Reference Field tables, enumerations, and tool catalogs. Read reference → --- ## Prerequisites Source: https://docs.aicontrols.dev/docs/getting-started/prerequisites > What you need before connecting a provider to AIControls — API keys, permissions, and account access. What you need before connecting a provider. Requirements vary by provider — select yours below. ### Workspace access Before anything else, make sure you can log in to your AIControls workspace. Your administrator will have sent an invite email — use it to set your password and access `https://YOUR_ORG.aicontrols.dev`. If you haven't received an invite, ask the person who manages AIControls for your organization to send one from **Settings → Users → Invite**. ### Provider credentials :::tip **Using Passthrough mode?** No provider credentials are needed in AIControls — developers supply their own API keys directly. Passthrough mode is supported for **Anthropic** (Claude Code) and **OpenAI** (Codex). Skip to [Step 3 — Generate a Personal Access Token](https://docs.aicontrols.dev/docs/getting-started/manual#create-token). ::: If you're using **Proxy mode**, select your provider to see what credentials you'll need to enter in AIControls: **Anthropic:** #### Anthropic - An Anthropic API key — create one at [console.anthropic.com → API Keys](https://console.anthropic.com/settings/keys) - The default key scope is sufficient — no special permissions are required - Note your API key's usage tier; higher tiers unlock higher rate limits :::tip Anthropic is the recommended starting point. AIControls supports all Claude models with full prompt caching, extended thinking, and tool-use governance. ::: #### What you'll enter in AIControls | Field | Where to find it | |---|---| | API Key | console.anthropic.com → Settings → API Keys | **OpenAI:** #### OpenAI - An OpenAI API key — create one at [platform.openai.com → API Keys](https://platform.openai.com/api-keys) - A paid OpenAI account — free-tier keys cannot access GPT-4o and newer models - Your Organization ID — only needed if your account belongs to multiple OpenAI organizations #### What you'll enter in AIControls | Field | Where to find it | |---|---| | API Key | platform.openai.com → API Keys | | Organization ID (optional) | platform.openai.com → Settings → Organization | **Azure OpenAI:** #### Azure OpenAI - An Azure subscription with Azure OpenAI access — request it at [aka.ms/oai/access](https://aka.ms/oai/access) if not already approved (approval can take 1–3 business days) - An Azure OpenAI resource created in the [Azure Portal](https://portal.azure.com) - At least one model deployed in that resource via [Azure AI Foundry](https://oai.azure.com) — note the **deployment name** you chose - The resource's endpoint URL and one of its API keys :::note If your organization uses Azure AD / Entra ID authentication for Azure OpenAI (managed identity), contact your AIControls administrator — this requires additional workspace-level configuration beyond API keys. ::: #### What you'll enter in AIControls | Field | Where to find it | |---|---| | Endpoint | Azure Portal → your OpenAI resource → Keys and Endpoint | | API Key | Azure Portal → your OpenAI resource → Keys and Endpoint (Key1 or Key2) | | Deployment name | Azure AI Foundry → Deployments → the name you chose | | API version | Use `2024-10-21` unless your deployment requires a specific version | **Amazon Bedrock:** #### Amazon Bedrock - An AWS account with Amazon Bedrock enabled in your target region - Model access explicitly granted — go to the [Bedrock console](https://console.aws.amazon.com/bedrock) → Model access and enable each model you want to use - An IAM user or role with `bedrock:InvokeModel` permission scoped to your chosen model ARNs - AWS Access Key ID and Secret Access Key for that IAM identity, *or* a Role ARN if AIControls should assume a role :::warning Model access in Bedrock is opt-in per region. If you see "Access denied" errors after setup, check that the specific model is enabled in the correct region in the Bedrock console. ::: #### Recommended IAM policy ```json { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": "bedrock:InvokeModel", "Resource": [ "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-*", "arn:aws:bedrock:us-east-1::foundation-model/amazon.nova-*" ] }] } ``` #### What you'll enter in AIControls | Field | Where to find it | |---|---| | Region | The AWS region where your Bedrock models are enabled, e.g. `us-east-1` | | Access Key ID | IAM → Users → your user → Security credentials | | Secret Access Key | Shown once when you create the access key — store it securely | | Role ARN (optional) | IAM → Roles → your role → ARN (use instead of static keys if preferred) | ### Next steps Once you have your credentials, continue to one of the setup paths: - [Onboarding Wizard](https://docs.aicontrols.dev/docs/getting-started/wizard) — guided setup in the dashboard - [Manual Setup](https://docs.aicontrols.dev/docs/getting-started/manual) — step-by-step configuration --- ## Onboarding Wizard Source: https://docs.aicontrols.dev/docs/getting-started/wizard > Use the built-in wizard to connect AIControls to your LLM provider and AI tools in minutes. The wizard walks you through four steps — deployment mode, spend cap, user auth, and a summary. Most teams finish in under 10 minutes. ### Starting the wizard Log in to your workspace at `https://YOUR_ORG.aicontrols.dev`. If this is your first login, the wizard launches automatically. Otherwise, go to **Settings → Onboarding** and click **Run wizard**. The wizard shows you what's ahead before asking any questions: 1 Deployment mode Proxy or passthrough → 2 Set spend cap Org-wide budget → 3 User auth Access Token or SSO → 4 Summary Review & invite ### Step 1 — Deployment mode The wizard asks two questions to determine the right mode for your team: **Step 1.** **What AI product are you governing?** — Select from Claude Code / Anthropic, OpenAI, Azure OpenAI, or GitHub Copilot. **Step 2.** **How do your developers access it?** — For Claude, choose between subscription-based (Claude Pro, Max, Team) or API plan. For OpenAI, between ChatGPT Plus/Pro, individual API key, or org-managed key. Based on your answers, the wizard derives and highlights the appropriate mode: | Mode | Who holds the API key | Developer experience | |---|---|---| | **Proxy** | AIControls workspace | Developers authenticate with a workspace access token — no provider credentials on their machines. | | **Passthrough** | Each developer | Developers use their own credentials alongside a workspace token for identity. | :::note Budgets, policies, MCP governance, and audit logging work identically in both modes. The only difference is where upstream credentials live. ::: #### Proxy mode — enter your API key If the wizard recommends (or you select) Proxy mode, it shows a form to enter your organization's LLM API key. You can test the key before saving — the wizard validates it against the provider and reports any permission or quota issues immediately. :::tip Keys are encrypted at rest. Developers receive scoped access tokens and never see the underlying provider credential. ::: #### Passthrough mode — no credentials needed If the wizard recommends Passthrough mode (for example, Claude Pro/Max subscriptions or Codex OAuth), no API key entry is required. The wizard proceeds directly to the spend cap step. Passthrough is supported for **Anthropic** (Claude Code) and **OpenAI** (Codex). See [Prerequisites](https://docs.aicontrols.dev/docs/getting-started/prerequisites) for details on which plans support each mode. ### Step 2 — Set spend cap Set an org-wide monthly spend cap. When the cap is hit, new LLM calls are blocked with a clear error — in-flight requests complete normally. The wizard includes a spend calculator: enter your approximate number of AI users and usage intensity (light / moderate / heavy), and it suggests a monthly cap with a 20% buffer. You can accept the suggestion or enter your own value. :::note You'll receive a Slack or email alert when spend reaches 80% of the cap. Per-team sub-limits and model-downgrade fallback can be configured via policy after setup. ::: This step is skippable — you can set or change the cap later from **Settings → Budgets**. ### Step 3 — User auth Choose how developers will authenticate their requests to AIControls: Access Token Self-service, no IT involvement. The wizard generates a token for you right now. Developers copy it and add one environment variable to their AI tool. - Token is generated immediately and shown once — copy it before proceeding - Developers get their own tokens from **Settings → Access Tokens** - Each token is scoped to one identity — audit entries are attributed per person OIDC / SSO Users sign in via Google, Okta, or Azure AD. Requires IT coordination to register AIControls as an OAuth app in your IdP. - Groups and roles flow automatically — no per-person token management - IT admin must register the app and share Client ID + Secret with your platform team before this can complete - Recommended: start with Access Tokens today and migrate to OIDC in Settings → Identity when IT is ready #### Configure your client (Access Token path) After the wizard generates your token, it shows a configuration snippet tailored to your AI tool and mode — copy it and follow the inline instructions. For the full per-tool details (including troubleshooting), see [Claude Code](https://docs.aicontrols.dev/docs/tasks/connect-claude-code), [Cursor](https://docs.aicontrols.dev/docs/tasks/connect-cursor), [OpenAI Codex](https://docs.aicontrols.dev/docs/tasks/connect-codex), and [GitHub Copilot](https://docs.aicontrols.dev/docs/tasks/connect-copilot). ### Step 4 — Summary The final screen shows the configuration you chose — mode, provider, budget, and auth method — plus a concrete next-action plan for your first day, week, and month. From here you can invite team members by email; they receive setup instructions for the AI tool you configured. ### After the wizard Governance is active. When you're ready to go further: - [Budgets](https://docs.aicontrols.dev/docs/concepts/cost-governance) — per-developer and team-wide spend limits - [Policies](https://docs.aicontrols.dev/docs/concepts/policies) — enforce rules on tool calls and model usage - [Upstreams](https://docs.aicontrols.dev/docs/concepts/upstreams) — add more providers or adjust your existing upstream - [MCP governance](https://docs.aicontrols.dev/docs/concepts/mcp-governance) — control which MCP tools agents can call --- ## Manual Setup Source: https://docs.aicontrols.dev/docs/getting-started/manual > Step-by-step guide to connecting AIControls — provider, mode, upstream, access token, and tool configuration. Full control over every configuration decision — provider, mode, upstream credentials, and per-tool setup. Follow the steps in order. :::note Have your provider credentials ready before starting. See [Prerequisites](https://docs.aicontrols.dev/docs/getting-started/prerequisites) for what each provider requires. ::: ### Step 1 — Choose your mode The first decision shapes how developers authenticate and where API keys live: | Mode | Who holds the API key | Developer experience | When to use | |---|---|---|---| | **Proxy** | AIControls workspace | Developers use a workspace-issued access token. No provider credentials on their machine. | Most teams. Centralized credential management, full cost attribution, no per-developer API accounts needed. | | **Passthrough** | Each developer | Developers use their own provider API key alongside a workspace token for identity. | Teams with existing per-developer accounts, or regulated environments where centralizing credentials is restricted. | :::note Budgets, policies, MCP governance, and audit logging all work identically in both modes. The only difference is where upstream credentials live. ::: ### Step 2 — Create an upstream Go to **Settings → Upstreams → Add upstream** and select your provider. In **proxy mode**, enter your organization's API key and any provider-specific fields. AIControls will use this key for all developer requests routed to this upstream. In **passthrough mode**, create the upstream with provider and region settings but leave the API key empty. Developers supply their own credentials at request time. For full field reference by provider, see [Configuring Upstreams →](https://docs.aicontrols.dev/docs/concepts/upstreams) ### Step 3 — Generate a Personal Access Token Each developer needs their own token. Go to **Settings → Access Tokens → New token**, give it a name that identifies the device or purpose (e.g. `cursor-macbook-pro`), and set an expiry. Copy the token value immediately — it's only shown once. :::warning Do not share tokens between developers. Every audit log entry is attributed to the token's owner — shared tokens make cost attribution and audit trails unreliable. ::: In **passthrough mode**, developers configure two credentials in their tool: the workspace token (for identity) and their own provider API key (for the upstream call). ### Step 4 — Configure your AI tool Most tools route through the workspace proxy endpoint with your personal access token as the API key; GitHub Copilot instead uses a dedicated VS Code extension. The exact steps differ by tool: | Tool | Configuration | Guide | |---|---|---| | Claude Code | Proxy endpoint `https://YOUR_ORG.aicontrols.dev/proxy` + access token | [Setup guide →](https://docs.aicontrols.dev/docs/tasks/connect-claude-code) | | Cursor | Proxy endpoint `https://YOUR_ORG.aicontrols.dev/proxy/v1` + access token | [Setup guide →](https://docs.aicontrols.dev/docs/tasks/connect-cursor) | | OpenAI Codex | Proxy endpoint `https://YOUR_ORG.aicontrols.dev/proxy/v1` + access token | [Setup guide →](https://docs.aicontrols.dev/docs/tasks/connect-codex) | | GitHub Copilot | AIControls VS Code extension, connected via your GitHub account | [Setup guide →](https://docs.aicontrols.dev/docs/tasks/connect-copilot) | ### Step 5 — Send a test request Make any request in your configured AI tool — ask it to explain a file, write a function, anything. The request should complete normally; AIControls is transparent to the developer. ### Step 6 — Verify in the Audit Log In your workspace dashboard, go to **Audit Log**. Your request should appear within a few seconds, showing: - Your identity — the developer name associated with the token you used - The AI tool that made the request - Model used, input and output token counts, estimated cost - Policy decisions — which policies evaluated and whether any triggered - Content safety findings, if any - MCP tool calls made during the session, if applicable :::tip If your request appears in the Audit Log, setup is complete. Your organization's policies, budgets, and content safety rules are enforced for all subsequent requests from this tool. ::: ### What's next - [Set up budgets](https://docs.aicontrols.dev/docs/concepts/cost-governance) — control spend per developer or team - [Write policies](https://docs.aicontrols.dev/docs/concepts/policies) — enforce rules on tool calls and models - [MCP governance](https://docs.aicontrols.dev/docs/concepts/mcp-governance) — govern tool calls from Claude Code and other MCP agents - [Optimization](https://docs.aicontrols.dev/docs/concepts/cost-governance) — reduce costs with caching and model routing --- ## Upstreams Source: https://docs.aicontrols.dev/docs/concepts/upstreams > How AIControls routes requests to Anthropic, OpenAI, Azure OpenAI, and Amazon Bedrock. An upstream is an LLM provider that AIControls routes traffic to on behalf of your developers. You configure API keys once — developers never touch them directly. ### How upstreams work When a developer's AI tool makes a request, AIControls: 1. Authenticates the developer using their personal access token 2. Evaluates policies against the request 3. Forwards the request to the matching upstream using the upstream's API key 4. Returns the response and logs the full audit event Developers connect with workspace credentials — they don't need Anthropic or OpenAI accounts. ### Supported providers AIControls can route to four classes of upstream provider, each with its own identity and authentication model: - **Anthropic** — authenticated with a single `sk-ant-...` API key. AIControls supports all Claude models, including claude-opus-4-8, claude-sonnet-4-6, and claude-haiku-4-5. New models appear automatically as Anthropic releases them, so you don't need to update an upstream definition when a new model ships. - **OpenAI** — authenticated with a single `sk-...` API key. An OpenAI account can have multiple organizations, so an upstream optionally carries an organization ID to disambiguate which org's models and billing a request should use. - **Azure OpenAI** — identity is resource-based rather than account-based: a request targets a specific Azure resource endpoint and a named deployment within it (rather than a model ID directly), and every request is versioned against a specific Azure API version. - **Amazon Bedrock** — authenticated with AWS credentials (an access key/secret pair, or an assumed role) rather than a vendor-issued API key, and scoped by AWS region. Because Bedrock authentication is just AWS IAM, you can scope a credential tightly — for example, a dedicated IAM user with `bedrock:InvokeModel` permission limited to specific model ARNs — instead of using a single all-or-nothing key. For the exact fields, console steps, and config values needed to add each provider, see [Configure an Upstream](https://docs.aicontrols.dev/docs/tasks/configure-an-upstream). ### Routing between upstreams When you configure multiple upstreams, AIControls uses static routing — each upstream declares which requests it should receive, and the first match wins. There is no policy-based or dynamic routing; routing decisions are fixed at configuration time. Each upstream can match on any combination of three signals (all are AND-ed): | Signal | Field | How it works | |---|---|---| | **OIDC groups** | `groups` | Routes requests from members of specific IdP groups. Use `["*"]` as a catch-all that matches any caller. | | **Model globs** | `match.models` | Routes by the model name in the request. Supports prefix, suffix, and substring wildcards — e.g. `claude-*`, `*gpt-4*`. | | **Identity labels** | `match.labels` | Routes by identity source set server-side during token resolution. Common key: `source` with values `pat`, `github`, or `passthrough`. Cannot be forged by clients. | #### Selection order Upstreams are evaluated in order of specificity — more specific predicates always beat catch-alls, regardless of the order you define them in settings: - **Identity labels present** — highest priority - **Model globs present** - **Non-wildcard groups present** - **Catch-all** (`groups: ["*"]` or no predicates) — lowest priority Among upstreams with equal specificity, use the `priority` field as a numeric tiebreaker — lower value is evaluated first. :::note Routing rules are configured per upstream in **Settings → Upstreams → Edit upstream**. Use the **Priority** field as a numeric tiebreaker when two upstreams have the same specificity — lower value is evaluated first. ::: ### See also For step-by-step setup instructions for each provider, see [Configure an Upstream](https://docs.aicontrols.dev/docs/tasks/configure-an-upstream). --- ## Identities & Risk Scores Source: https://docs.aicontrols.dev/docs/concepts/identities-and-risk > Understand who is using AI in your organization — developers, agents, and their risk profiles. Every developer and agent that connects through AIControls becomes a tracked identity. The Identities page shows who is active, their behavioral baseline, risk score, and token usage — giving you a clear picture of your AI estate. ### Identity types AIControls recognizes two identity types: | Type | Description | | --- | --- | | **Developer** | A human using an AI coding tool (Claude Code, Cursor, Copilot). Identified by email address from the OIDC token or PAT. Grouped by team. | | **Agent** | An automated agent or CI pipeline. Identified by SPIFFE SVID, Kubernetes service account, or a named PAT. Labeled with the agent type (e.g. `claude-code`). | Identities are created automatically on first request — no manual enrollment required. ### Risk scores Each identity carries a continuously updated risk score (0–100). The score reflects four signals over the last 7 days: | Signal | Weight | | --- | --- | | Violation rate — requests denied or flagged by policy | High | | HITL rate — requests routed for human approval | High | | Blast radius — breadth of resources accessed (files, repos, namespaces) | Medium | | Write-tool breadth — variety of write/mutate tools used | Medium | Identities are ranked on the Security Posture page. A rising score triggers an admin alert; a score above the configured threshold can trigger auto-pause when anomaly detection is enabled. ### Behavioral baselines AIControls builds a per-identity baseline over 7 days of observed activity: typical call rate, token volume, tool mix, and active hours. Once a baseline is established, deviations appear in the Anomalies feed and raise the identity's risk score. A new identity shows **Learning** status until enough activity is observed. Established identities show **Stable**. Identities with recent significant deviations show **Drifting**. ### Developer detail view Click any identity to open its detail panel: token usage and cost, active sessions, recent audit events, the risk score trend, team membership, and issued PATs. Admins can set a per-developer budget override and add or revoke PATs directly from the panel. --- ## Sessions Source: https://docs.aicontrols.dev/docs/concepts/sessions > Track active and historical AI coding sessions — cost, duration, tools used, and governance decisions. A session is a continuous period of AI activity from a single identity — typically one Claude Code or Cursor workspace. Sessions give you a per-task view of cost, tool calls, and governance decisions. ### What is a session Sessions are created automatically when a developer or agent begins sending requests through the proxy. A session ends when it is idle for longer than the inactivity timeout (default: 30 minutes) or when the developer explicitly disconnects. Each session captures: - The identity (developer email or agent ID) and the tool they were using - A declared **purpose** — optionally set by the developer or inferred from the first request - Total token usage, estimated cost, and model mix for the session - Every tool call and LLM request made during the session, with governance decisions ### Session list Navigate to **Identity → Sessions** to see all sessions, filterable by developer, status (active, ended, budget exceeded, paused), and purpose. An admin can pause or resume an active session from the list without affecting the developer's connection. ### Session detail Click any session to open the detail panel. It shows: - **Summary** — AI-generated description of what the session accomplished, which tools were used, and key outcomes - **Cost breakdown** — input tokens, output tokens, cache hits, and estimated cost by model - **Governance timeline** — every allow, deny, warn, and approval decision in chronological order - **Tool calls** — the full list of MCP tool calls with arguments and outcomes ### Session budgets Sessions inherit the default session cap set in **Settings → Budgets → Limits**. When a session hits its cap, further requests are blocked until the session ends or an admin resets the budget from the session detail panel. Individual developers can request a higher cap for a specific session by setting it in their PAT. Admins can override any session cap from the detail panel. --- ## Audit Log Source: https://docs.aicontrols.dev/docs/concepts/audit-log > A tamper-evident record of every AI tool call and LLM request, with governance decisions and identity attribution. Every request that passes through AIControls is recorded — the identity, the tool or model, the governance decision, and the outcome. The Audit Log is your authoritative trail for security review, incident investigation, and compliance evidence. ### What is logged Every event in the audit log captures: | Field | Description | | --- | --- | | **Timestamp** | UTC time of the request | | **Identity** | Developer email or agent ID, plus team membership at the time of the request | | **Request type** | MCP tool call or LLM request | | **Tool / Model** | The MCP tool name (e.g. `bash`, `read_file`) or model identifier (e.g. `claude-sonnet-4-6`) | | **Decision** | Allow, Deny, Audit, Warn, or Held (awaiting HITL approval) | | **Policy** | The policy rule that produced the decision, if any | | **Resource** | File path, repository, namespace, or other resource accessed | | **Tokens / Cost** | Token count and estimated cost for LLM requests | | **Session** | The session this request belongs to | MCP tool calls and LLM requests are stored in the same log. The Audit Log page (**Security → Audit**) filters by identity, decision, tool or model, request type, and time range; clicking any row opens the full event detail, including request arguments and the policy evaluation trace. ### Decisions Each event records a **decision** — the outcome of evaluating the request against your policies, such as Allow, Deny, Audit, Warn, or Held. The decision is what turns a raw log line into a governance record: it tells you not just that a request happened, but whether it was permitted, blocked, flagged for review, or routed to a human approver, and which policy rule produced that outcome. See [Decision Types](https://docs.aicontrols.dev/docs/reference/decision-types) for the full set of decisions and their meanings. ### Retention and export Audit events are stored in your workspace's SQLite database. The default retention window is 90 days; older events are purged automatically. To extend retention, configure an S3-compatible object store in **Settings → Integrations** — events are streamed there in real time and retained indefinitely. Export the current filtered view to CSV from the Audit Log toolbar. The export includes all fields in the table view and can be used directly for compliance reporting. ### See also - [Decision Types](https://docs.aicontrols.dev/docs/reference/decision-types) --- ## Cost Governance Source: https://docs.aicontrols.dev/docs/concepts/cost-governance > How budgets, rules, limits, alerts, and context/compression optimization work together to control AI spend. Cap AI spend per model family, per team, or per user, and reduce the token usage behind that spend. Budget rules are enforced at request time against a rolling time window; optimization techniques reduce the tokens each request consumes in the first place. ### Overview The **Cost → Budgets** page has four tabs — **Overview**, **Rules**, **Limits**, and **Alerts**. Overview summarizes spend for the selected month: total spend against your global limit, projected month-end spend at the current burn rate, rules approaching their limit, and a feed of every request a budget rule denied, warned on, or audited. ### Rules Rules define spend caps. Each rule matches a *scope* (organization, team, or individual) and a *model glob*, and caps spend within a rolling time window: | Field | Description | | --- | --- | | **Scope** | `Global` (all identities), `Team` (a named group), or `User` (a specific identity) | | **Target** | The team name or user email when scope is Team or User; `*` for Global | | **Model match** | Glob pattern — e.g. `claude-opus*`, `gpt-4o`, or `*` for all models. First-match within each scope. | | **Limit** | Maximum spend in USD for the window | | **Window** | Rolling window: `1h`, `24h`, `7d`, or `30d` | | **When limit is reached** | See enforcement modes below | | **Warn at** | Percentage at which a `budget_warning` notification fires (once per window). Default: 80%. | #### Enforcement modes | Mode | What happens when the limit is hit | | --- | --- | | **Deny** | Requests are blocked until the window resets. The caller receives a clear error with the reset time. | | **Audit** | Requests are allowed, but would-have-blocked amounts are tracked so you can preview a rule's impact. Promotes to Deny in one click. | | **Warn** | Requests are allowed with a budget-exceeded warning appended to each response. Useful for awareness without blocking. | | **Require approval** | Requests are held for a manager to approve or deny in the Approvals queue. | :::note Rules are AND-enforced: a request must pass the first matching rule in every applicable scope (global, team, user). If multiple rules match a request, all of them apply. ::: The **Effective budget** inspector on the Rules tab answers "what would happen to the next request" — type any identity and model to see which rules bind, the remaining headroom, and the resulting decision. For step-by-step instructions on creating a rule, see [Set a Budget](https://docs.aicontrols.dev/docs/tasks/set-a-budget). ### Limits Independent of rolling-window rules, a **default session cap** sets the maximum spend (USD) for any single session. When a session hits the cap, further requests are blocked until the session ends or an admin resets it. Individual sessions can override the default via their PAT settings. ### Alerts Alerts notify without blocking: - **Budget warning thresholds** — each percentage threshold (e.g. 75, 90) fires a `budget_warning` notification at most once per window per rule, delivered to the affected developer, administrators, and any configured Slack or Teams channel. - **Session spend alert** — a USD threshold that fires an in-app notification the first time a session's spend crosses it. Separate from the session cap — it only notifies. :::note For conditional enforcement near a budget threshold — for example, requiring a ticket ID once spend exceeds 80% — use a [CEL policy](https://docs.aicontrols.dev/docs/concepts/policies) with `object.modelBudget.team.pctUsed`. ::: ### Context Optimization Preview AIControls intercepts every tool response before it reaches the LLM and applies techniques that reduce token usage at the source: | Technique | What it does | | --- | --- | | **Noise filtering** | Strips ANSI escape codes, progress bars, and terminal noise from shell tool responses before they are forwarded to the LLM. | | **Response deduplication** | Suppresses exact duplicate tool responses within a session using a content-hash cache — repeated results are replaced with a short reference instead of the full text. | | **Brevity injection** | Appends a conciseness directive to requests. Three modes: **Off**, **Auto** (applied when context pressure is detected), **Always**. A custom prompt can override the built-in instruction. | Brevity injection is typically the highest-leverage technique — a single setting that reduces output tokens on every request it applies to. ### Compression Preview Compression reduces the size of tool responses before they enter the LLM context window, independent of the techniques above. Model-based (ML) compression summarizes content semantically; an optional code-aware (AST) pass compresses source code by stripping function bodies while retaining signatures, imports, and structure. A size threshold keeps small responses untouched. :::note Compression is a preview feature. Results vary by tool and content type — monitor the Context Savings dashboard after enabling to confirm the savings. ::: For configuration steps for both features, see [Optimize Cost](https://docs.aicontrols.dev/docs/tasks/optimize-cost). ### Context Savings dashboard **Cost → Context Savings** shows what the active optimization techniques are actually saving: the token reduction rate across sessions, estimated cost saved, a breakdown of savings by technique, and the sessions that benefit most. Use it to verify a newly enabled technique is working and to find workflows where further tuning would pay off. ### See also - [Set a Budget](https://docs.aicontrols.dev/docs/tasks/set-a-budget) - [Optimize Cost](https://docs.aicontrols.dev/docs/tasks/optimize-cost) --- ## Security Posture Source: https://docs.aicontrols.dev/docs/concepts/security-posture > Org-wide risk summary, compliance mapping, exception workflow, and human-in-the-loop approvals for AI activity. AIControls provides a real-time view of risk across your AI estate — computed risk scores per identity, NIST AI RMF compliance mapping, a policy exception workflow, and a human-in-the-loop approval queue. ### Risk scores Navigate to **Security → Posture** for an org-wide risk summary. The page shows computed risk scores per agent and developer, derived from violation rate, HITL rate, blast radius, and write-tool breadth over the last 7 days. Use it to identify which identities warrant closer review and to track posture trends over time. Posture is informed by behavioral baselines. AIControls builds a per-identity baseline (normal call rate, typical token volume, common tools) over time. Deviations from that baseline surface in the **Detections** feed and raise the identity's risk score. ### Detections Navigate to **Security → Detections** to view session anomalies and baseline alerts in one place. Session anomalies are fired when a behavioral threshold (call rate, token spike, repeated prompts) is crossed. Baseline alerts are generated by policy violations, budget threshold crossings, and HITL events. Detections is covered in depth on its own page — session anomaly detection, thresholds, auto-pause, tuning for agentic workloads, baseline alerts, and delivery channels. ### Compliance The Compliance page maps your active policies and capabilities to the NIST AI Risk Management Framework (AI RMF), reporting covered, partial, and missing controls in real time. Export an audit-ready report for security reviews and regulatory submissions. ### Exceptions Navigate to **Security → Exceptions** to manage temporary policy overrides. An exception allows a specific identity or group to bypass one or more policies for a defined period — useful for contractor onboarding, one-off experiments, or incident response. Each exception records who granted it, the justification, and an expiry time. Expired exceptions are automatically revoked and appear in the audit log. Active exceptions are visible to all admins on the Exceptions page. ### Approvals Navigate to **Security → Approvals** for the human-in-the-loop (HITL) queue. When a policy routes a request for approval rather than denying it outright, the request lands here. Admins can approve or deny each request; the developer's session is held until a decision is made or the request times out. HITL is configured per policy rule — set the enforcement mode to `approval` in any [ValidatingPolicy](https://docs.aicontrols.dev/docs/concepts/policies) to route matching requests here instead of blocking them outright. This is useful for high-risk but infrequent operations (production deployments, credential access) where context matters. :::note Approval requests expire after a configurable timeout (default: 30 minutes). If no admin acts within the window, the request is auto-denied and the developer receives a timeout message. ::: ### See also - [Detections](https://docs.aicontrols.dev/docs/concepts/detections) - [Compliance](https://docs.aicontrols.dev/docs/concepts/compliance) --- ## Detections Source: https://docs.aicontrols.dev/docs/concepts/detections > Session anomaly detection and baseline alerts — behavioral thresholds, auto-pause, and the alert inbox. AIControls surfaces two categories of security signals: session anomalies (behavioral thresholds exceeded by a running session) and baseline alerts (notifications generated by policy violations, budget crossings, and HITL events). Both appear in **Security → Detections**. ### Session anomalies Anomaly detection runs inline on every request — no background job, no batch window. Each check evaluates the current session's recent activity against the configured threshold. When a check fires: - An anomaly event is recorded in the audit log with the triggering metric and observed value. - A baseline alert is created and delivered to configured channels (Slack, email, in-app). - If auto-pause is enabled and the cumulative anomaly count for the session exceeds the pause threshold, the session is paused and the developer receives a clear message with a contact-admin prompt. Anomalies do not block requests by themselves — only auto-pause does. Run detection in observation mode and tune thresholds before committing to enforcement. The **Session Anomalies** tab shows all detected anomaly events ordered by recency. Filter by identity, threshold type, and time range. Each entry links to the full session and shows the exact metric value that triggered the anomaly. Anomaly events also feed into each identity's risk score — repeated anomalies from the same developer or agent raise their score on the **Security Posture** page. ### Detection thresholds AIControls evaluates every session against three independent behavioral thresholds — call rate, token spike, and repeated-prompt count. Each threshold targets a different failure mode: - **Max calls per minute** guards against runaway call volume — a session issuing far more MCP tool calls or LLM requests than normal in a short window. - **Token spike threshold** guards against unexpectedly large context payloads, such as a `read_file` on a multi-megabyte binary piped into a prompt. - **Max repeated prompts** guards against prompt-loop behavior — an agent stuck retrying the same request, or runaway retry logic. The thresholds are independent: any one of them can fire an anomaly event without the others being crossed. Because default values are calibrated for interactive developer use rather than automated or multi-agent workloads, thresholds usually need tuning before enforcement (auto-pause) is turned on — see [Configure Detection Thresholds](https://docs.aicontrols.dev/docs/tasks/configure-detection-thresholds) for the concrete settings and steps. ### Auto-pause By default, anomalies create alerts but never block developers. With auto-pause enabled, a session is paused once its cumulative anomaly count crosses a configurable threshold — the count requirement guards against pausing on a single transient spike. For the concrete settings and steps, see [Configure Detection Thresholds](https://docs.aicontrols.dev/docs/tasks/configure-detection-thresholds#auto-pause). When a session is paused, the developer's next request returns a `session_paused` error with instructions to contact their admin. Admins can resume the session from **Identity → Sessions** or from the alert detail in **Security → Detections**. :::warning Enable auto-pause only after observing anomaly patterns in the feed for at least a week. Premature enablement with default thresholds can pause legitimate agentic workloads during normal operation. ::: ### Tuning for agentic workloads Default thresholds are calibrated for interactive developer use, not for automated agents. Agentic workloads — particularly Claude Code running in multi-agent mode, bulk file indexing, or iterative code-generation loops — routinely produce call rates, context sizes, and retry patterns that would look anomalous for a human developer but are normal for the workload. Without adjustment, these patterns trip the default thresholds and generate noisy alerts or, if auto-pause is enabled, pause sessions that are behaving correctly. The fix is to raise the relevant threshold(s) to match the workload's real behavior rather than to disable detection outright — see [Configure Detection Thresholds](https://docs.aicontrols.dev/docs/tasks/configure-detection-thresholds) for recommended adjustments per workload pattern. ### Baseline alerts The **Baseline Alerts** tab is the security alert inbox for your workspace. Alerts are generated by four sources: | Source | Example | |---|---| | **Anomaly detection** | A session exceeded the max calls-per-minute threshold | | **Policy violations** | A `deny`-mode policy blocked a high-risk tool call | | **Budget crossings** | A developer reached 90% of their monthly token budget | | **HITL events** | An approval request timed out without a decision | Each alert shows the triggering identity, event type, severity, and a link to the relevant audit entry. Alerts are ordered by recency and the full history is always available regardless of delivery channel configuration. :::note The Baseline Alerts tab in **Security → Detections** always shows the complete alert history. Channel delivery is best-effort and does not affect what appears in the product. ::: ### See also - [Configure Detection Thresholds](https://docs.aicontrols.dev/docs/tasks/configure-detection-thresholds) --- ## Compliance Source: https://docs.aicontrols.dev/docs/concepts/compliance > Map your AIControls configuration to the NIST AI Risk Management Framework and generate audit-ready reports. AIControls maps your active policies and enabled capabilities to the NIST AI Risk Management Framework (AI RMF). The Compliance page shows which controls are covered, which are partial, and which are missing — giving you an actionable gap list for security reviews and audits. ### NIST AI RMF The [NIST AI Risk Management Framework](https://www.nist.gov/artificial-intelligence) is the leading US standard for managing risk in AI systems. It organizes controls across four core functions — **Govern**, **Map**, **Measure**, and **Manage** — covering everything from policy documentation to incident response. AIControls evaluates your workspace configuration against the AI RMF controls that are relevant to AI agent and LLM deployment: access control, monitoring, content safety, human oversight, auditability, and supply chain integrity. ### Coverage status Navigate to **Security → Compliance** to see your current coverage. Each control is reported as one of three states: | Status | Meaning | |---|---| | **Covered** | One or more active policies or enabled capabilities directly address this control. No action required. | | **Partial** | The relevant capability is enabled but not all risk vectors within the control are addressed by a policy. The detail panel shows what is missing. | | **Missing** | No active policy or capability addresses this control. A suggested policy or configuration change is shown. | Coverage is computed in real time from your loaded policies and current settings — it updates automatically when you add or modify a policy. ### Control categories The controls assessed by AIControls span seven AI RMF categories, grouped under the framework's **Govern**, **Map**, **Measure**, and **Manage** functions: - **Govern** covers the governance foundations — whether your policies are documented, approval workflows exist, exceptions are tracked, and audit logs are retained. - **Map — Risk Identification** covers how well you can attribute actions to identities, classify the tools and models in use, understand blast radius, and detect anomalies. - **Measure — Monitoring** covers continuous audit logging, behavioral baselines, token spike detection, and violation rate tracking. - **Measure — Content Safety** covers protections against unsafe content, including PII detection, prompt injection scanning, and output filtering. - **Manage — Human Oversight** covers human-in-the-loop controls — approval rules for high-risk operations, auto-pause configuration, and session review. - **Manage — Access Control** covers identity-scoped budget rules, tool-level allow/deny policies, and PAT scope restrictions. - **Manage — Incident Response** covers your ability to respond to incidents — alert routing, anomaly escalation, session pause capability, and audit export for investigation. For the full list of assessed controls and what AIControls checks for each, see [Compliance Controls](https://docs.aicontrols.dev/docs/reference/compliance-controls). ### Improving coverage Each missing or partial control on the Compliance page includes a targeted recommendation, since gaps are typically specific to a single AI RMF category — for example, a missing human oversight policy or disabled anomaly detection. Working through these recommendations is the fastest way to raise coverage, and revisiting them periodically (or after adding new policies) keeps coverage current as your configuration evolves. Note that enabling a capability in audit mode (rather than enforce mode) still counts as coverage for monitoring-class controls, but not for enforcement-class controls — the detail panel distinguishes between the two. For step-by-step guidance on closing specific gaps and exporting a coverage report, see [Generate a Compliance Report](https://docs.aicontrols.dev/docs/tasks/generate-a-compliance-report). ### See also - [Compliance Controls](https://docs.aicontrols.dev/docs/reference/compliance-controls) - [Generate a Compliance Report](https://docs.aicontrols.dev/docs/tasks/generate-a-compliance-report) --- ## Policies Source: https://docs.aicontrols.dev/docs/concepts/policies > Write CEL policies to govern AI tool calls and LLM requests across your team. Policies are CEL-based rules that decide what happens to every AI request — allow, deny, audit, mutate, or route for human approval. They run in real time before the request reaches the model. ### Policy anatomy Policies are Kyverno CEL YAML documents. Each policy has optional match conditions and one or more validation expressions: ```yaml apiVersion: policies.kyverno.io/v1 kind: ValidatingPolicy metadata: name: block-prod-kubectl annotations: proxy.nirmata.io/enforcement-mode: require-approval spec: matchConditions: - expression: 'object.mcp.tool == "kubectl"' - expression: 'object.agent.namespace == "production"' validations: - expression: | now.getHours() >= 8 && now.getHours() < 18 && now.getDayOfWeek() in [1, 2, 3, 4, 5] message: "Production kubectl outside business hours requires approval" validationActions: [Deny] ``` Use `MutatingPolicy` to rewrite arguments before the request is forwarded (for example, redirecting a disallowed model to an approved one). ### Enforcement modes Set via `validationActions` or the annotation `proxy.nirmata.io/enforcement-mode`. The annotation takes priority. | Mode | Blocks? | Effect | |---|---|---| | `Deny` | Yes | Request blocked immediately; developer sees the denial message. | | `require-approval` | Yes (held) | Request is queued for human review. Session resumes on approval or times out on denial. | | `Warn` | No | Request proceeds; a warning is appended to the response. | | `Audit` | No | Request proceeds; violation is logged. Use to test a policy before enforcing it. | Add a cooldown period to suppress repeated alerts from the same session: ```yaml annotations: proxy.nirmata.io/cooldown-period-minutes: "15" ``` ### Matching: tools vs LLM calls Every request is either a tool call (MCP) or an LLM call. Use these expressions to target the right type: | What to match | Expression | |---|---| | Any MCP tool call | `object.mcp.tool != ""` | | A specific tool | `object.mcp.tool == "bash"` | | Any LLM call | `object.llm.model != ""` | | A specific model | `object.llm.model == "claude-opus-4-8"` | ### Content safety policies AIControls scans every LLM prompt and tool call inline before forwarding it. Content safety enforcement is done through policies — you choose whether to block, warn, or audit depending on your team's risk tolerance. The `Warn` enforcement mode is particularly useful for content safety: the request is allowed through, but a warning is appended to the model's response. The AI tool (e.g. Claude Code) sees the warning in its next context window and surfaces it to the developer, who can then decide whether to continue. This gives you a soft interrupt without hard-blocking legitimate workflows. :::tip Start with `Audit` mode for all content safety policies to measure false-positive rates against your team's real workload. Graduate to `Warn`, then `Deny`, once you have confidence in the patterns. ::: For worked content-safety examples (PII warnings, prompt injection blocking, credential-file access warnings, secret exfiltration blocking), see [Write a Policy](https://docs.aicontrols.dev/docs/tasks/write-a-policy#content-safety). ### Built-in policy library AIControls ships with a curated library of policies covering common governance scenarios, grouped into four categories — security, cost, compliance, and operations. Security policies cover things like blocking credential patterns in prompts and denying requests with PII in tool arguments. Cost policies enforce model tiers by developer group and can block premium models for non-engineering roles. Compliance policies require audit mode for regulated data namespaces and can block data export tools. Operations policies rate-limit bash calls per session and require HITL approval for infrastructure mutations. Enable library policies from **Policies → Library**. For the full enumerated list of built-in policies, see [Policy Context](https://docs.aicontrols.dev/docs/reference/policy-context#library). ### Human-in-the-loop Set `proxy.nirmata.io/enforcement-mode: require-approval` on any policy to route matching requests to the approval queue instead of blocking them outright. The developer's session is held; they see a pending state in their AI tool. Admins approve or deny in **Security → Approvals** — the session resumes immediately on approval or receives an error on denial. Approval requests expire after a configurable timeout (default: 30 minutes). If no admin acts within the window, the request is auto-denied. Configure who receives approval notifications in **Settings → Notifications**. ### See also - [Write a Policy](https://docs.aicontrols.dev/docs/tasks/write-a-policy) - [Policy Context](https://docs.aicontrols.dev/docs/reference/policy-context) --- ## MCP Governance Source: https://docs.aicontrols.dev/docs/concepts/mcp-governance > How MCP tool-call proxying, logging, and authorization work. AIControls intercepts every MCP tool call from Claude Code and other MCP-enabled agents — applying policies, logging arguments and results, and routing high-risk operations for human approval. ### How MCP proxying works When Claude Code (or another MCP client) connects through the AIControls proxy, MCP tool calls are intercepted at the protocol layer before being forwarded to the upstream MCP server. The proxy evaluates policies against the tool name and arguments, then either allows, denies, or holds the call for approval. No changes are needed on the MCP server side — the proxy is transparent to both the agent and the server. ### What gets logged Every MCP tool call produces an audit event containing: | Field | Description | |---|---| | Tool name | e.g. `bash`, `read_file`, `write_file`, `kubectl` | | Arguments | Full argument map passed to the tool | | Result | Tool output (configurable — can be redacted for sensitive tools) | | Decision | Allow, deny, or require-approval — and which policy triggered | | Duration | Time from call to response | | Resource | File path, URL, or resource identifier extracted from arguments | ### Policy-based tool authorization MCP tool calls are governed the same way as any other request: a policy declares a `matchCondition` that scopes it to specific tools or servers, and one or more validation rules that inspect the tool name and arguments to decide whether the call is allowed, denied, audited, or held for approval. From the **MCP Servers** page, you can create these governance policies scoped to a specific server directly from the server list. Click the action menu (**⋮**) on any server to see two options: | Action | What it does | |---|---| | **Create a policy** | Opens the policy editor pre-populated with a `matchCondition` scoped to this server's tool namespace. Add your validation logic and save — the policy applies immediately. | | **Add to existing policy** | Adds a new rule to an existing policy, pre-scoped to this server. Use this to consolidate related rules into a single policy rather than creating many single-rule policies. | This is the recommended starting point for governing a newly registered server. A typical workflow: 1. Register the MCP server and confirm it appears in the server list. 2. Use **Create a policy** to add an Audit rule that logs all tool calls from this server. Observe the audit log for a few days to understand usage patterns. 3. Use **Add to existing policy** to layer in Deny or require-approval rules for specific high-risk tools, using the argument patterns you observed. Policies generated this way are full CEL `ValidatingPolicy` documents — you can edit them freely in **Policies** after creation. The server-scoped match condition is a starting point, not a constraint. ### See also - [Connect an MCP Server](https://docs.aicontrols.dev/docs/tasks/connect-an-mcp-server) - [Admin MCP Server](https://docs.aicontrols.dev/docs/reference/admin-mcp-server) --- ## Builder Portal Source: https://docs.aicontrols.dev/docs/concepts/builder-portal > The Builder Portal gives developers visibility into their own AI usage, budgets, access tokens, and session history — no admin access required. A self-service dashboard for developers. View your budgets, efficiency and safety scores, session history, projects, and manage your own access tokens — without needing admin access. ### Overview — budgets and scores The **Overview** tab shows your current session status and spend against your configured limits. #### Budget Three budget tiers are shown as progress bars: - **Developer budget** — your individual daily or monthly spend limit. - **Team budget** — shared limit across your team; your share of the pool is shown. - **Total budget** — combined view of developer + team spend. If your budget is running low, click **Request more budget** to submit a budget increase request to your admin. You'll see estimated time until exhaustion based on your current spend velocity. #### Efficiency score AIControls grades your AI usage across four dimensions: | Signal | What it measures | |---|---| | Cache hit rate | How often your prompts hit the provider's prompt cache | | Context efficiency | How much of your context window is productive content vs. noise | | Model appropriateness | Whether you're using a heavier model than the task requires | | Prompt repetition | Whether you're re-sending the same content across turns | A letter grade (A–F) summarises the four signals. Lower grades surface specific recommendations to reduce token waste. #### Safety score Tracks policy denials in your recent sessions. A high score means your requests are consistently within policy. Repeated denials on the same tool or operation appear as actionable items — click through to see which policy is firing and why. #### Context health A breakdown of your active session's context window: fill percentage, loop score, latency rot, verbosity, and repeat reads. High loop scores or verbosity suggest starting a new session or compressing context. ### Access tokens The **Access Tokens** tab is where you create and manage Personal Access Tokens (PATs). PATs are how your AI tools authenticate to the AIControls proxy — they replace direct API keys on your machine. Each token has a name identifying the tool or machine it's used from, an expiry (30 to 365 days), and a status — tokens marked **new** have never been used. The token value is only shown once, at creation time. After creating a token, the tab shows ready-to-paste shell commands for your tool and shell (bash, zsh, fish), covering two connection modes: | Mode | How it works | |---|---| | **Proxy mode** | Your AI tool routes all LLM and MCP traffic through the AIControls proxy endpoint. Full governance coverage. | | **Passthrough mode** | Your AI tool keeps its existing upstream configuration; AIControls intercepts via a lightweight observer. Lower setup friction. | See the [Claude Code](https://docs.aicontrols.dev/docs/tasks/connect-claude-code), [Cursor](https://docs.aicontrols.dev/docs/tasks/connect-cursor), [Codex](https://docs.aicontrols.dev/docs/tasks/connect-codex), or [GitHub Copilot](https://docs.aicontrols.dev/docs/tasks/connect-copilot) pages for tool-specific connection details. ### Sessions The **Sessions** tab lists all sessions associated with your developer identity — status, purpose, spend, and call counts. Each row opens a session detail drawer: an AI-generated summary of what was worked on, spend against budget, and a full call log. ### Projects The **Projects** tab aggregates your session history by project (repository path), with per-project cost, token usage, and activity trends. It's populated automatically from Claude Code session metadata — no manual tagging required. :::note Project data appears after your first Claude Code session. If the table is empty, complete a session and refresh. ::: ### User profile and activity The **User** tab shows your profile (display name, password, role — role changes require an admin) and work patterns derived automatically from your session history: commit cadence, work area focus, language breakdown, and tool usage. ### Connected accounts The **Connected Accounts** tab manages per-developer credentials for upstream datasources (databases, APIs, internal services) that your AI tools access via MCP. Two types are listed: - **Stored credentials** — OAuth tokens or API keys you've connected. Shows status (Connected, Expired, Disconnected), token prefix, and expiry. - **Client-configured** — credentials passed as custom headers from your AI tool. AIControls doesn't store these; the card shows the expected header name and setup instructions. ### Policy exceptions The **Policy Exceptions** tab shows exceptions that have been granted for your identity — operations that would normally be denied by policy but have been explicitly approved. Exceptions are granted by admins and have an expiry date. You cannot create exceptions yourself; they're requested via the HITL approval flow or directly from your admin. ### See also - [Manage Builder Portal Access](https://docs.aicontrols.dev/docs/tasks/manage-builder-portal-access) --- ## Claude Code Source: https://docs.aicontrols.dev/docs/tasks/connect-claude-code > Connect Claude Code to AIControls in proxy or passthrough mode — full governance on every API call and MCP tool invocation. Route Claude Code traffic through AIControls to get full audit coverage and policy enforcement. Two modes are supported — your administrator selects one during onboarding. ### Prerequisites - Claude Code installed — `npm install -g @anthropic-ai/claude-code` - Your workspace proxy URL — find it in **Settings → Integrations** - A personal access token — create one in **Settings → Access Tokens** ### Proxy vs Passthrough **Proxy mode:** AIControls holds your organization's Anthropic API key. You authenticate with your personal access token — no Anthropic credentials on your machine. #### Step 1 — Remove existing Anthropic credentials If you've previously authenticated with an Anthropic API key, clear it so Claude Code doesn't prefer saved credentials over the proxy: ```bash claude auth logout 2>/dev/null || true ``` #### Step 2 — Configure `~/.claude/settings.json` Open or create `~/.claude/settings.json` and add: ```json { "env": { "ANTHROPIC_BASE_URL": "https://YOUR_ORG.aicontrols.dev", "ANTHROPIC_AUTH_TOKEN": "YOUR_ACCESS_TOKEN" } } ``` Replace `YOUR_ORG` with your workspace subdomain and `YOUR_ACCESS_TOKEN` with your personal access token. :::note Use `ANTHROPIC_AUTH_TOKEN`, not `ANTHROPIC_API_KEY`. Claude Code treats these differently — `ANTHROPIC_AUTH_TOKEN` signals a virtual token and prevents Claude Code from validating the format against Anthropic's key schema. ::: :::tip Your virtual token is scoped to your identity. It cannot be used to extract the organization's API key — you authenticate to AIControls, which then forwards requests to Anthropic using the org credential. ::: **Passthrough mode:** You keep your own Anthropic credentials. AIControls adds a governance layer — all traffic is audited and policy-checked before reaching Anthropic, but billing stays on your account. :::note **Required for Claude Team plan.** Claude Team (and Max/Pro subscriptions) don't issue API keys — access is subscription-based. Because there's no API key to configure as an upstream in AIControls, passthrough is the only supported mode. Your subscription credentials are forwarded; AIControls provides governance on top. ::: #### Step 1 — Create a passthrough upstream An administrator must first create an Anthropic upstream in **Settings → Upstreams → Add upstream**. For passthrough mode, leave the API Key field blank — AIControls uses the developer's own credentials rather than a stored key. #### Step 2 — Configure `~/.claude/settings.json` Open or create `~/.claude/settings.json` and add: ```json { "env": { "ANTHROPIC_BASE_URL": "https://YOUR_ORG.aicontrols.dev", "ANTHROPIC_CUSTOM_HEADERS": "X-AIControls-Token: YOUR_ACCESS_TOKEN" } } ``` Replace `YOUR_ORG` with your workspace subdomain and `YOUR_ACCESS_TOKEN` with your personal access token. Keep your existing Anthropic credentials — they are still used for billing. :::note Do not remove or change `ANTHROPIC_API_KEY`. The `X-AIControls-Token` header is added alongside it — AIControls uses the header to identify you, then forwards your request to Anthropic with your key. ::: ### Claude for Work If your team uses **Claude for Work** (the claude.ai web or desktop app on Enterprise or Team plans), an administrator can configure AIControls as the AI Gateway for your whole organization. When set up, all claude.ai traffic from your workspace routes through AIControls automatically — no per-developer configuration required. #### Admin configuration - In your claude.ai Enterprise admin settings, open **Workspace settings → AI Gateway**. - Enable the third-party AI gateway option. - Set the gateway URL to your workspace proxy endpoint: `https://YOUR_ORG.aicontrols.dev` - Save. Traffic from all claude.ai users in your organization immediately routes through AIControls. :::note Claude for Work traffic appears in your Audit Log under **Source: Claude for Work**. Governance uses the organization token, not personal access tokens — attribution is by claude.ai user identity. ::: ### MCP tool governance If you use Claude Code with MCP servers, AIControls intercepts every tool call — no additional configuration needed. MCP traffic flows through the same proxy endpoint as LLM requests. To see which MCP tools are being called and what policies apply, go to **Audit Log** and filter by **Type: Tool call**. ### Verify the connection Start Claude Code and make any request — ask it to read a file or summarize a function. Then check your workspace **Audit Log**. Within a few seconds you should see the request with your identity and model details. ### Troubleshooting #### Requests not appearing in Audit Log - Confirm `ANTHROPIC_BASE_URL` is set in `~/.claude/settings.json` (no trailing slash) - Restart Claude Code after editing settings — env vars from settings.json take effect on startup - Check that your access token is valid — try regenerating it in **Settings → Access Tokens** #### Authentication errors (proxy mode) - Ensure you're using `ANTHROPIC_AUTH_TOKEN`, not `ANTHROPIC_API_KEY` - Run `claude auth logout` to clear any cached Anthropic credentials that may take precedence - Confirm your workspace URL matches the one in **Settings → Integrations** #### Authentication errors (passthrough mode) - Check that `ANTHROPIC_CUSTOM_HEADERS` is set to exactly `X-AIControls-Token: YOUR_ACCESS_TOKEN` (no extra spaces) - Confirm your personal access token hasn't expired — regenerate it in **Settings → Access Tokens** if needed #### Requests denied by policy If a request is blocked, Claude Code shows an error. Check **Audit Log → Denied** for the policy that triggered and the denial reason. Contact your administrator to adjust the policy or get an exemption. --- ## Cursor Source: https://docs.aicontrols.dev/docs/tasks/connect-cursor > Connect Cursor to AIControls — all AI features governed through the workspace proxy. Configuration is UI-only, no code changes needed. Route Cursor's AI features through AIControls for full audit coverage and policy enforcement on all chat, Composer, and background agent calls. Configuration is done in Cursor's settings UI — no code or config files to edit. ### Prerequisites - Cursor installed and open - Your workspace proxy URL — find it in **Settings → Integrations** - A personal access token — create one in **Settings → Access Tokens** ### Configure Cursor Open Cursor settings (`Cmd/Ctrl + ,`) and navigate to **Models**. Scroll to the **OpenAI API Key** section and configure as follows: | Setting | Value | |---|---| | Override OpenAI Base URL | `https://YOUR_ORG.aicontrols.dev/cursor/v1` | | OpenAI API Key | Your AIControls personal access token | Enable the override toggle and save. All Cursor AI features — chat, Composer, Tab, and background agents — now route through AIControls. :::note AIControls exposes a Cursor-specific OpenAI-compatible endpoint at `/cursor/v1`. Both Anthropic (Claude) and OpenAI (GPT, o-series) models are supported — Cursor sends all requests in OpenAI format and AIControls routes to the correct upstream based on the model name. ::: ### Adding models Cursor does not automatically discover models from a custom base URL. You need to add each model you want to use manually in **Cursor Settings → Models → Add model**. Enter the model name exactly as it appears in your AIControls upstream configuration. Both Anthropic and OpenAI model IDs are supported: | Provider | Example model names to add in Cursor | |---|---| | Anthropic | `claude-opus-4-8`, `claude-sonnet-4-6`, `claude-haiku-4-5` | | OpenAI | `gpt-4o`, `gpt-4o-mini`, `o3` | #### Model aliases Cursor reserves some model names (e.g. `claude-3-5-sonnet`) for its own built-in routing. If the name you want conflicts with a Cursor built-in, use an alias instead. In **Settings → Upstreams → Edit upstream**, your administrator can configure a model alias mapping — for example, mapping `my-claude-sonnet` to `claude-sonnet-4-6`. Add the alias name in Cursor; AIControls resolves it to the actual model before forwarding the request. :::tip If a model you add in Cursor shows "unknown model" errors, ask your administrator to verify the model ID or alias is configured correctly in the upstream settings. ::: ### Verify the connection Open a Cursor chat, select one of the models you added, and ask anything. Check your workspace **Audit Log** — the request should appear with your identity within seconds. ### Troubleshooting #### Cursor shows "invalid API key" - Confirm the base URL is `https://YOUR_ORG.aicontrols.dev/cursor/v1` (no trailing slash) - Regenerate your access token in **Settings → Access Tokens** and paste it again - Make sure the override toggle is enabled and saved #### Model not found or unknown model errors - Confirm you added the model name manually in Cursor — models are not auto-discovered from a custom base URL - Check that the model name matches exactly what's configured in your AIControls upstream (or a configured alias) - Ask your administrator to verify the upstream has the model enabled in **Settings → Upstreams** #### Requests not appearing in Audit Log If Cursor is using its built-in model routing rather than your custom base URL, traffic won't route through AIControls. Confirm "Override OpenAI Base URL" is enabled and the API key field is not empty. --- ## OpenAI Codex Source: https://docs.aicontrols.dev/docs/tasks/connect-codex > Connect OpenAI Codex CLI to AIControls in proxy (API key) or passthrough (ChatGPT OAuth) mode. Route Codex CLI traffic through AIControls to audit and govern every code generation request. Two modes are available depending on whether your team holds a shared OpenAI API key or developers use their own ChatGPT accounts. ### Prerequisites - Codex CLI installed — `npm install -g @openai/codex` - Your workspace proxy URL — find it in **Settings → Integrations** - A personal access token — create one in **Settings → Access Tokens** ### Proxy vs ChatGPT OAuth **Proxy (API key):** AIControls holds your organization's OpenAI API key. Developers authenticate with their personal access token — no OpenAI credentials on their machines. #### Set environment variables Set these before running Codex, or add them permanently to your shell profile (`~/.zshrc`, `~/.bashrc`, etc.): ```bash export OPENAI_BASE_URL="https://YOUR_ORG.aicontrols.dev/v1" export OPENAI_API_KEY="YOUR_ACCESS_TOKEN" ``` :::note `OPENAI_API_KEY` here is your AIControls personal access token, not an OpenAI API key. AIControls authenticates you with this token and uses the organization's OpenAI credential to reach the API. ::: #### Run Codex ```bash codex "refactor the auth module to use JWT" ``` **Passthrough (ChatGPT OAuth):** Developers use their own ChatGPT Plus or Pro accounts. Their ChatGPT JWT is forwarded automatically — AIControls adds governance without replacing their credentials. #### Step 1 — Log in with ChatGPT Run `codex login` to authenticate and store your ChatGPT JWT locally: ```bash codex login ``` This opens a browser window. Complete the login and return to the terminal. Your JWT is saved to `~/.codex/auth.json`. #### Step 2 — Configure `~/.codex/config.toml` Create or edit `~/.codex/config.toml`: ```toml # ~/.codex/config.toml model_provider = "aicontrols" [model_providers.aicontrols] name = "AIControls Governance Proxy" base_url = "https://YOUR_ORG.aicontrols.dev/v1" requires_openai_auth = true wire_api = "responses" http_headers = { "X-AIControls-Token" = "YOUR_ACCESS_TOKEN" } ``` Replace `YOUR_ORG` with your workspace subdomain and `YOUR_ACCESS_TOKEN` with your personal access token. :::note `requires_openai_auth = true` tells Codex to forward the JWT from `~/.codex/auth.json` to AIControls automatically. Your ChatGPT subscription is used for billing — AIControls never stores your ChatGPT credentials. ::: :::tip `config.toml` is recommended over shell env vars — it keeps model provider settings and proxy config together and avoids conflicts with other OpenAI-compatible tools. ::: #### Run Codex ```bash codex "write a test for the payment handler" ``` ### Direct API calls If you call the OpenAI Responses API directly in code, point the client at the proxy with your personal access token as the API key: ```python # Python from openai import OpenAI client = OpenAI( base_url="https://YOUR_ORG.aicontrols.dev/v1", api_key="YOUR_ACCESS_TOKEN", ) response = client.responses.create( model="codex-mini-latest", instructions="You are a coding assistant.", input="Write a Python function to parse ISO 8601 dates.", ) ``` ```typescript // TypeScript import OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://YOUR_ORG.aicontrols.dev/v1", apiKey: "YOUR_ACCESS_TOKEN", }); ``` ### Verify the connection Run a Codex command and check your workspace **Audit Log**. The request should appear with the model name (`codex-mini-latest` or similar) and your identity within seconds. ### Troubleshooting #### Authentication error (proxy mode) Confirm `OPENAI_API_KEY` is your AIControls personal access token, not an OpenAI API key. The token should start with `aic_` — regenerate it in **Settings → Access Tokens** if needed. #### Authentication error (ChatGPT OAuth mode) - Re-run `codex login` to refresh your JWT if it has expired - Confirm `~/.codex/config.toml` has the correct `base_url` and `X-AIControls-Token` value - Verify `requires_openai_auth = true` is set — without it, the JWT is not forwarded #### Model not available Codex models require specific account access on OpenAI. In proxy mode, your administrator needs to ensure the OpenAI upstream account has Codex access enabled. In ChatGPT OAuth mode, confirm your ChatGPT subscription includes Codex access. #### Requests not appearing in Audit Log - Confirm `OPENAI_BASE_URL` ends with `/v1` (unlike Claude Code, Codex does not append this automatically) - Restart your terminal after editing shell profiles --- ## GitHub Copilot Source: https://docs.aicontrols.dev/docs/tasks/connect-copilot > Govern GitHub Copilot traffic through AIControls using the AIControls VS Code extension. Route GitHub Copilot completions and chat through AIControls using the AIControls VS Code extension. Setup takes under two minutes — no GitHub organization settings or config files to edit. ### Prerequisites - VS Code installed - GitHub Copilot active on your GitHub account (Individual, Business, or Enterprise) - A GitHub account already signed in to VS Code ### Setup **Step 1.** **Install the AIControls VS Code extension.** Install from the [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=nirmata.aicontrols) or from [downloads.nirmata.io](https://downloads.nirmata.io/). The extension adds an AIControls item to the VS Code status bar. **Step 2.** **Open the AIControls panel.** Click the **AIControls** item in the VS Code status bar (bottom bar). The panel opens and checks whether a GitHub account is already signed in to VS Code. **Step 3.** **Connect with your GitHub account.** If a GitHub session is detected, click **"Connect with GitHub account: <your-username>"**. The extension silently exchanges your VS Code GitHub session for an AIControls personal access token — no copy-pasting required. No GitHub session in VS Code? Sign in to GitHub first via **Accounts → Sign in with GitHub**, then return to this step. Alternatively, paste a personal access token from **Settings → Access Tokens** directly into the AIControls panel. **Step 4.** **Done.** All GitHub Copilot Chat and inline completions now route through AIControls. Policies, audit logging, spend tracking, and HITL approvals apply automatically. ### What gets governed - Inline code completions in VS Code - Copilot Chat messages and responses - Copilot edits and multi-file changes :::note Governance applies to Copilot traffic routed through the VS Code extension. Copilot usage in other IDEs (JetBrains, Neovim, etc.) or via `gh copilot` in the CLI is not covered by this extension. ::: ### Verify the connection Use Copilot Chat or trigger an inline completion in VS Code. Check your workspace **Audit Log** — the request should appear with your GitHub identity within seconds. ### Troubleshooting #### No GitHub session detected Sign in to GitHub in VS Code via **Accounts → Sign in with GitHub**, then reopen the AIControls panel and connect again. #### Copilot completions not appearing in Audit Log - Confirm the AIControls panel shows your account as connected (not "disconnected" or "token expired") - Restart VS Code after installing the extension if the status bar item is missing - Regenerate your access token in **Settings → Access Tokens** and reconnect in the panel #### Copilot stops working after connecting If Copilot becomes unresponsive after connecting AIControls, a policy may be blocking requests. Check **Audit Log → Denied** for your identity and contact your administrator. --- ## Configure an Upstream Source: https://docs.aicontrols.dev/docs/tasks/configure-an-upstream > Add and route to an LLM provider — Anthropic, OpenAI, Azure OpenAI, or Amazon Bedrock. Add an upstream provider so AIControls can route developer requests to it. For how upstream routing works conceptually, see [Upstreams](https://docs.aicontrols.dev/docs/concepts/upstreams). **Anthropic:** - Go to **Settings → Upstreams → Add upstream** and select **Anthropic**. **Step 1.** Fill in the upstream fields: | Field | Value | |---|---| | Name | Any label, e.g. `anthropic-prod` | | API Key | Your `sk-ant-...` key from [console.anthropic.com](https://console.anthropic.com) | | Models | Leave blank to allow all, or restrict to specific model IDs | :::note AIControls supports all Claude models including claude-opus-4-8, claude-sonnet-4-6, and claude-haiku-4-5. New models appear automatically as Anthropic releases them. ::: **OpenAI:** - Select **OpenAI** as the provider. **Step 1.** Fill in the upstream fields: | Field | Value | |---|---| | Name | e.g. `openai-prod` | | API Key | Your `sk-...` key from [platform.openai.com](https://platform.openai.com) | | Organization ID | Optional — your OpenAI org ID if using multiple orgs | **Azure OpenAI:** - Select **Azure OpenAI** as the provider. **Step 1.** Fill in the upstream fields: | Field | Value | |---|---| | Endpoint | `https://YOUR_RESOURCE.openai.azure.com` | | API Key | Your Azure OpenAI resource key | | Deployment | Your deployment name, e.g. `gpt-4o` | | API Version | `2024-10-21` (or your target version) | **Amazon Bedrock:** - Select **Amazon Bedrock** as the provider. **Step 1.** Fill in the upstream fields: | Field | Value | |---|---| | Region | e.g. `us-east-1` | | Access Key ID | AWS access key with Bedrock invoke permissions | | Secret Access Key | Corresponding AWS secret | | Role ARN | Optional — assume a role instead of using static credentials | :::note For Bedrock, we recommend a dedicated IAM user with `bedrock:InvokeModel` permission scoped to the specific model ARNs you want to allow. ::: ### See also For how AIControls picks between multiple configured upstreams, see [Upstreams](https://docs.aicontrols.dev/docs/concepts/upstreams). --- ## Write a Policy Source: https://docs.aicontrols.dev/docs/tasks/write-a-policy > Worked examples for writing, testing, and deploying CEL policies that govern tool calls and LLM requests. Each example below is a complete, deployable Kyverno CEL policy. For how policy anatomy, enforcement modes, and matching work conceptually, see [Policies](https://docs.aicontrols.dev/docs/concepts/policies). ### General workflow - **Decide what to match.** Use `object.mcp.tool != ""` to target MCP tool calls or `object.llm.model != ""` to target LLM calls — see [Policy Context](https://docs.aicontrols.dev/docs/reference/policy-context) for the full set of available fields. - **Write the validation expression.** A CEL boolean expression that must evaluate to `true` for the request to be allowed. - **Start in `Audit` mode.** Deploy with `validationActions: [Audit]` to measure false-positive rates against real workload before enforcing. - **Graduate to `Warn`, then `Deny`.** Once you have confidence in the pattern, tighten the enforcement mode — or use `require-approval` to route matching requests to human review instead of blocking them outright. ### Restrict premium models by capability Deny requests for Claude Opus unless the calling agent has the `premium-models` capability: ```yaml apiVersion: policies.kyverno.io/v1 kind: ValidatingPolicy metadata: name: model-access-by-capability spec: matchConditions: - expression: 'object.llm.model != ""' validations: - expression: | !object.llm.model.startsWith("claude-opus") || "premium-models" in object.agent.capabilities message: "Claude Opus is restricted to agents with the premium-models capability" validationActions: [Deny] ``` ### Block shell commands containing secret patterns Match only `bash` tool calls, then deny any command whose text matches common secret-key prefixes: ```yaml apiVersion: policies.kyverno.io/v1 kind: ValidatingPolicy metadata: name: no-secrets-in-bash spec: matchConditions: - expression: 'object.mcp.tool == "bash"' validations: - expression: | !object.mcp.arguments.command.matches("(sk-|ghp_|AKIA)[A-Za-z0-9]+") message: "Possible secret detected in bash command — request blocked" validationActions: [Deny] ``` ### Require a ticket when session budget is half-consumed Combine a namespace match condition with a session-budget validation to require a ticket ID once spend crosses 50%: ```yaml apiVersion: policies.kyverno.io/v1 kind: ValidatingPolicy metadata: name: session-budget-gate spec: matchConditions: - expression: 'object.agent.namespace == "production"' validations: - expression: | object.session.percentUsed < 0.5 || object.session.ticketId != "" message: "A ticket ID is required once 50% of session budget is consumed" validationActions: [Deny] ``` ### Route model from Opus to Haiku for non-ML users Use a `MutatingPolicy` instead of a `ValidatingPolicy` to rewrite the request rather than block it — here, redirecting Opus requests to Haiku for anyone outside the `ml-team` group: ```yaml apiVersion: policies.kyverno.io/v1 kind: MutatingPolicy metadata: name: route-to-haiku spec: matchConditions: - expression: | object.llm.model.startsWith("claude-opus") && !("ml-team" in object.user.groups) mutations: - patchType: ApplyConfiguration applyConfiguration: expression: '{"model": "claude-haiku-4-5"}' ``` ### Content safety policies AIControls scans every LLM prompt and tool call inline before forwarding it. The examples below use the `Warn` enforcement mode where a soft interrupt is preferable to a hard block: the request is allowed through, but a warning is appended to the model's response. The AI tool (e.g. Claude Code) sees the warning in its next context window and surfaces it to the developer, who can then decide whether to continue. #### Warn the agent when a prompt contains PII Detects common PII patterns (email addresses, SSNs, credit card numbers) in the user's prompt and asks the agent to confirm before proceeding. The request is not blocked — the agent receives the response plus the warning and can relay it to the developer. ```yaml apiVersion: policies.kyverno.io/v1 kind: ValidatingPolicy metadata: name: warn-pii-in-prompt annotations: proxy.nirmata.io/enforcement-mode: warn spec: matchConditions: - expression: 'object.llm.model != ""' - expression: 'object.llm.currentPrompt != ""' validations: - expression: | !object.llm.currentPrompt.matches( "\\b[A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z]{2,}\\b|" + "\\b\\d{3}-\\d{2}-\\d{4}\\b|" + "\\b(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14})\\b" ) message: | This prompt appears to contain personal data (email address, SSN, or credit card number). Confirm with the user that sharing this information is intentional before continuing. validationActions: [Warn] ``` :::note Because the mode is `Warn`, the LLM receives both the original response and the warning appended to it. Claude Code will show the warning to the developer and pause for confirmation before its next action. ::: #### Block prompt injection attempts Detects common prompt injection patterns — instructions embedded in tool outputs or user messages that attempt to hijack the agent's behavior. ```yaml apiVersion: policies.kyverno.io/v1 kind: ValidatingPolicy metadata: name: block-prompt-injection spec: matchConditions: - expression: 'object.llm.model != ""' - expression: 'object.llm.currentPrompt != ""' validations: - expression: | !object.llm.currentPrompt.matches( "(?i)(ignore (previous|prior|all) instructions|" + "you are now|disregard your|new persona|" + "system prompt:|<\\/?(system|instruction)>)" ) message: "Possible prompt injection detected — request blocked" validationActions: [Deny] ``` #### Warn before reading credential or secret files Allows the read to proceed but warns the agent — and by extension the developer — that a sensitive file is being accessed. Useful as a first step before committing to a hard block. ```yaml apiVersion: policies.kyverno.io/v1 kind: ValidatingPolicy metadata: name: warn-credential-file-access annotations: proxy.nirmata.io/enforcement-mode: warn spec: matchConditions: - expression: 'object.mcp.tool == "read_file"' validations: - expression: | !has(object.mcp.arguments.path) || !object.mcp.arguments.path.matches( "(?i)(\\.env|\\.pem|\\.key|credentials|secrets|id_rsa|id_ed25519|" + "\\.aws/credentials|\\.kube/config)" ) message: | This file may contain credentials or secrets. Confirm with the user that reading it is intentional and that the content will not be logged or forwarded to external systems. validationActions: [Warn] ``` #### Block exfiltration of secrets through bash Denies bash commands that print or curl known secret file paths or environment variables matching credential name patterns. ```yaml apiVersion: policies.kyverno.io/v1 kind: ValidatingPolicy metadata: name: block-secret-exfiltration spec: matchConditions: - expression: 'object.mcp.tool == "bash"' validations: - expression: | !object.mcp.arguments.command.matches( "(?i)(cat|curl|wget|echo).*(\\.(env|pem|key)|" + "AWS_SECRET|GITHUB_TOKEN|ANTHROPIC_API_KEY|" + "DATABASE_URL)" ) message: "Possible secret exfiltration blocked — review the command and try again" validationActions: [Deny] ``` :::tip Start with `Audit` mode for all content safety policies to measure false-positive rates against your team's real workload. Graduate to `Warn`, then `Deny`, once you have confidence in the patterns. ::: ### See also - [Policies](https://docs.aicontrols.dev/docs/concepts/policies) - [Policy Context](https://docs.aicontrols.dev/docs/reference/policy-context) --- ## Set a Budget Source: https://docs.aicontrols.dev/docs/tasks/set-a-budget > Create a budget rule, set a session limit, and configure spend alerts. Create a rule to cap spend for an organization, team, or user, set a hard session-level cap, and configure the alerts that notify you as spend approaches those limits. ### Create a budget rule **Step 1.** Navigate to **Cost → Budgets → Rules**. **Step 2.** Click **+ New rule** in the top-right corner and choose a starting template: | Template | Use for | | --- | --- | | Org spend ceiling | Global limit across all models for the whole organization | | Team budget | Total cap for one team across all models | | Model cap | Limit one model family (e.g. `claude-opus*`) at any scope | | Blank rule | Start from scratch | **Step 3.** Set the rule's **Scope** — `Global` (all identities), `Team` (a named group), or `User` (a specific identity) — and its **Target** (the team name or user email, or `*` for Global). **Step 4.** Set the **Model match** — a glob pattern such as `claude-opus*`, `gpt-4o`, or `*` for all models. The first matching rule within each scope applies. **Step 5.** Set the **Limit** (maximum spend in USD) and the **Window** — a rolling period of `1h`, `24h`, `7d`, or `30d`. **Step 6.** Choose what happens **when the limit is reached**: | Mode | What happens | | --- | --- | | **Deny** | Requests are blocked until the window resets. | | **Audit** | Requests are allowed; overage is tracked and shown in the Overview "Audit-mode Overage" tile. | | **Warn** | Requests are allowed with a budget-exceeded warning appended to each response. | | **Require approval** | Requests are held for a manager to approve or deny in the Approvals queue. | **Step 7.** Set **Warn at** — the percentage of the limit at which a `budget_warning` notification fires (once per window). Default: 80%. **Step 8.** Save the rule. Use the **Effective budget** inspector at the top of the Rules tab to type any identity and model and confirm which rules bind, the remaining headroom, and the decision for the next request. :::note Rules are AND-enforced: a request must pass the first matching rule in every applicable scope (global, team, user). If multiple rules match a request, all of them apply. ::: :::tip To promote an audit-mode rule to Deny once you've reviewed the overage it would have caught, use the one-click promote action from the Overview tab. ::: ### Set the default session cap **Step 1.** Navigate to **Cost → Budgets → Limits**. **Step 2.** Set **Default session cap** — the maximum spend (USD) for any single session. When a session hits this cap, further requests are blocked until the session ends or an admin resets it. Set to 0 to disable. Individual sessions can override the default via their PAT settings. ### Configure alerts Alerts notify you as spend approaches a limit — they do not, on their own, block requests. Configure them in **Cost → Budgets → Alerts**. **Step 1.** Under **Budget warning thresholds**, add one or more percentage values (e.g. 75, 90). Each threshold fires a `budget_warning` notification at most once per window per rule. Notifications are delivered to: - The developer whose spend triggered the alert (in-app and email if configured) - Administrators (configurable in **Settings → Notifications**) - Slack or Teams (if an integration is configured) **Step 2.** Under **Session spend alert**, set a USD threshold at which an in-app notification fires the first time a session's spend crosses that value. Set to 0 to disable. This is independent of the session cap configured in Limits — it only notifies, it does not block requests. :::note For conditional enforcement near a budget threshold — for example, requiring a ticket ID once spend exceeds 80% — use a [CEL policy](https://docs.aicontrols.dev/docs/concepts/policies) with `object.modelBudget.team.pctUsed`. ::: ### See also - [Cost Governance](https://docs.aicontrols.dev/docs/concepts/cost-governance) --- ## Optimize Cost Source: https://docs.aicontrols.dev/docs/tasks/optimize-cost > Enable context optimization and compression to reduce token usage, and track the savings. Turn on context optimization and compression to cut the tokens each request consumes, then confirm the savings in the Context Savings dashboard. ### Enable context optimization **Step 1.** Navigate to **Settings → Context Optimization**. **Step 2.** Use the master toggle to enable context optimization. Individual settings below can be adjusted independently once it's on. **Step 3.** Enable **Noise filtering** to strip ANSI escape codes, progress bars, and terminal noise from Bash and shell tool responses before they are forwarded to the LLM. This has no effect on non-terminal tool output. **Step 4.** Enable **Response deduplication** to suppress exact duplicate tool responses within a session using a content-hash cache. Repeated occurrences of the same result are replaced with a short reference instead of the full text. **Step 5.** Set **Brevity injection** to one of: - **Off** — disabled - **Auto** — applied when context pressure is detected - **Always** — applied to every request **Step 6.** Optionally set a **Custom brevity prompt** to override the built-in instruction. Leave blank to use the default: *"Be concise. Omit preamble and trailing summaries. Prefer code over prose."* :::note Brevity injection is the highest-leverage technique for most teams — a single setting that reduces output tokens on every request it applies to. ::: ### Enable compression **Step 1.** Navigate to **Settings → Compression**. **Step 2.** Use the master toggle to enable compression. When enabled, the settings below control behavior. **Step 3.** Set **Default mode** — the compression level applied to all tool responses. **ML** (model-based) achieves ~90–95% size reduction by summarizing content semantically. Additional modes may be available depending on your workspace configuration. **Step 4.** Enable **Code-aware (AST) compression** to compress source code responses using an AST-aware pass that strips function bodies and retains signatures, imports, and structure. This requires the Compression Service to be reachable from your workspace. **Step 5.** Set **Threshold** — the minimum response size in bytes before compression is attempted. Responses smaller than this value are returned unmodified. Default: 512 bytes. :::note Compression is a preview feature. Results vary by tool and content type. Monitor the Context Savings dashboard after enabling to confirm the savings are being applied as expected. ::: ### Review your savings After enabling either feature, go to **Cost → Context Savings** and confirm the savings are landing: **Step 1.** Check the token reduction rate and estimated cost saved for the period — if they stay at zero, the techniques you enabled aren't matching your traffic. **Step 2.** Open **Savings by Technique** to see which methods contribute the most, and **Top Sessions by Savings** to find the developers and workflows that benefit — and those where further tuning would help. ### See also - [Cost Governance](https://docs.aicontrols.dev/docs/concepts/cost-governance) --- ## Configure Detection Thresholds Source: https://docs.aicontrols.dev/docs/tasks/configure-detection-thresholds > Tune anomaly detection thresholds for your workload and configure where alerts are delivered. Adjust the call-rate, token-spike, and repeated-prompt thresholds that drive anomaly detection, and route the resulting alerts to the channels your team monitors. ### Set detection thresholds **Step 1.** Navigate to **Settings → Anomaly Detection**. **Step 2.** Set the three thresholds: | Threshold | Default | What triggers it | |---|---|---| | **Max calls per minute** | 60 | A session exceeds this call rate in any rolling 1-minute window. Counts all MCP tool calls and LLM requests combined. | | **Token spike threshold** | 50 000 | A single LLM request uses more tokens than this value. Catches unexpectedly large context payloads — for example, a `read_file` on a multi-megabyte binary piped into a prompt. | | **Max repeated prompts** | 5 | The same prompt hash appears more than N times in the last 20 calls. Detects prompt-loop behavior, runaway retry logic, or agents stuck in a repeat cycle. | **Step 3.** Save. All three thresholds are independent — any one can fire an anomaly event without the others being crossed. :::note Run detection in observation mode (auto-pause off) and watch the Session Anomalies feed for at least a week before enabling enforcement — see [Enable auto-pause](#auto-pause) below. ::: ### Tune thresholds for agentic workloads Default thresholds are calibrated for interactive developer use and are usually too tight for automated or multi-agent workloads. **Step 1.** Open the **Session Anomalies** feed under **Security → Detections** and observe the real metric values your team's agentic workloads produce (each anomaly entry shows the exact triggering value). **Step 2.** Adjust thresholds in **Settings → Anomaly Detection** based on the workload pattern: | Workload pattern | Recommended adjustment | |---|---| | Claude Code with sub-agents (fan-out) | Raise **Max calls per minute** to 150–200 | | Large file indexing or repo scanning | Raise **Token spike threshold** to 150 000–200 000 | | Iterative code generation loops | Raise **Max repeated prompts** to 10–15 | **Step 3.** Save, then continue watching the feed to confirm the new ceilings stop flagging normal activity without hiding genuine anomalies. ### Enable auto-pause By default, anomalies create alerts but never block developers. **Step 1.** Navigate to **Settings → Anomaly Detection**. **Step 2.** Turn on **Auto-pause on anomaly** (default: Off). When off, anomalies only produce alerts; when on, sessions can be paused once the cumulative count is reached. **Step 3.** Set **Pause after N anomalies** (default: 20) — the number of cumulative anomaly events in a session before it is paused. This guards against pausing on a single transient spike. **Step 4.** Save. When a session is paused, the developer's next request returns a `session_paused` error with instructions to contact their admin. Admins can resume the session from **Identity → Sessions** or from the alert detail in **Security → Detections**. :::warning Enable auto-pause only after observing anomaly patterns in the feed for at least a week. Premature enablement with default thresholds can pause legitimate agentic workloads during normal operation. ::: ### Configure alert delivery channels **Step 1.** Navigate to **Settings → Notifications**. **Step 2.** Choose delivery channels: Slack, email, Microsoft Teams, and in-app (the bell icon). **Step 3.** Configure routing per event type — for example, route anomaly alerts to Slack while sending budget alerts only via email. **Step 4.** Save. Channel delivery is best-effort — the **Baseline Alerts** tab in **Security → Detections** always shows the complete alert history regardless of delivery configuration. ### See also - [Detections](https://docs.aicontrols.dev/docs/concepts/detections) --- ## Generate a Compliance Report Source: https://docs.aicontrols.dev/docs/tasks/generate-a-compliance-report > Close common compliance gaps and export a coverage report for audits and reviews. Close the most common compliance gaps, then export a coverage report for security reviews, vendor assessments, or regulatory submissions. ### Close common gaps Each missing or partial control on the Compliance page includes a recommendation. To resolve the most common gaps: **Step 1.** **No human oversight policy** — Add a [ValidatingPolicy](https://docs.aicontrols.dev/docs/concepts/policies) with `mode: approval` for high-risk tool categories (production writes, credential access). **Step 2.** **No content safety scanning** — Enable the Prompt Scanner in **Settings → Security**. **Step 3.** **Anomaly detection disabled** — Enable detection thresholds in **Settings → Anomaly Detection** (alerts-only mode is sufficient for this control). **Step 4.** **No audit retention policy** — Configure an S3-compatible export target in **Settings → Integrations** to retain events beyond the 90-day default. **Step 5.** **No identity-level access control** — Add a budget rule or deny policy scoped to a specific team or user. :::note Enabling a capability in audit mode (rather than enforce mode) still counts as coverage for monitoring-class controls, but not for enforcement-class controls. The detail panel distinguishes between the two. ::: ### Export a report **Step 1.** Navigate to **Security → Compliance**. **Step 2.** Click **Export report** to generate a PDF or CSV summary of your current coverage state — control by control, with status, evidence (which policy or setting provides coverage), and any open gaps. **Step 3.** Use the exported report for: - Internal security reviews and board-level AI risk reporting - Customer trust questionnaires and vendor assessments - SOC 2 or ISO 27001 supplementary evidence (AI controls annex) - Regulatory submissions where NIST AI RMF alignment is requested The report timestamps each control's evidence so reviewers can see that coverage was active at the time of the assessment, not just at export time. ### See also - [Compliance](https://docs.aicontrols.dev/docs/concepts/compliance) --- ## Connect an MCP Server Source: https://docs.aicontrols.dev/docs/tasks/connect-an-mcp-server > Register and authenticate an MCP server with AIControls. Register an upstream MCP server and choose how AIControls authenticates to it. For how MCP tool-call proxying and authorization work conceptually, see [MCP Governance](https://docs.aicontrols.dev/docs/concepts/mcp-governance). ### Register the server - Go to **Settings → MCP Servers → Add server**. **Step 1.** Fill in the server fields: | Field | Description | |---|---| | Name | Used as a tool prefix in agent calls, e.g. `prometheus` → tool `prometheus__query` | | Type | `http` (SSE) or `stdio` (local command) | | URL / Command | MCP server endpoint or shell command | | Authentication | See [Choose an authentication method](#authentication) below | :::note Developers don't configure MCP servers themselves — they're provisioned centrally and available to all agents automatically based on group membership policies. ::: ### Choose an authentication method Each MCP server can be configured with one of six authentication methods. The right choice depends on whether the upstream server has shared credentials, per-developer credentials, or an OAuth-capable identity layer. **None:** No credentials are forwarded. **When to use:** Internal servers on a private network that trust all proxy traffic implicitly. **Bearer Token:** A static token stored in the workspace config is injected as an `Authorization: Bearer` header on every request. **When to use:** Servers with a shared service account; simple API key authentication. **Basic Auth:** A username and password stored in the workspace config are forwarded as an `Authorization: Basic` header. **When to use:** Legacy servers that require HTTP basic authentication. **Passthrough (per-developer):** The developer's own AIControls identity token is forwarded directly to the upstream server. The upstream must accept AIControls tokens. **When to use:** Internal servers that trust AIControls as an identity provider and want to enforce per-developer access controls themselves. **Per-developer (credential store):** Each developer stores their own credential for this server in AIControls. The proxy injects the correct credential at call time based on the calling developer's identity. Admins never see individual credentials. **When to use:** Servers where each developer has their own account — for example a database or internal API where per-developer audit trails matter. **OAuth 2.0 (per-developer):** Each developer completes a one-time OAuth authorization flow (Authorization Code + PKCE). AIControls acts as the OAuth client, stores and refreshes tokens automatically. Subsequent tool calls are transparent to the developer. **When to use:** Third-party SaaS MCP servers (GitHub, Jira, Salesforce, etc.) that use standard OAuth 2.0 for access control. :::tip For OAuth-enabled servers, developers authorize once by visiting a link shown in their AI tool. AIControls handles token refresh silently — developers are never prompted again unless their access is revoked. ::: ### Write a tool-authorization policy Use `object.mcp.tool` to match tool calls. Arguments are available as `object.mcp.arguments`: #### Block file writes outside the workspace ```yaml apiVersion: policies.kyverno.io/v1 kind: ValidatingPolicy metadata: name: restrict-write-file spec: matchConditions: - expression: 'object.mcp.tool == "write_file"' validations: - expression: | object.mcp.arguments.path.startsWith("/home/") || object.mcp.arguments.path.startsWith("/workspace/") message: "write_file is only permitted inside /home/ or /workspace/" validationActions: [Deny] ``` #### Audit all bash commands ```yaml apiVersion: policies.kyverno.io/v1 kind: ValidatingPolicy metadata: name: audit-bash annotations: proxy.nirmata.io/enforcement-mode: audit spec: matchConditions: - expression: 'object.mcp.tool == "bash"' validations: - expression: 'true' message: "bash call recorded" validationActions: [Audit] ``` #### Block destructive commands ```yaml apiVersion: policies.kyverno.io/v1 kind: ValidatingPolicy metadata: name: block-destructive-bash spec: matchConditions: - expression: 'object.mcp.tool == "bash"' validations: - expression: | !object.mcp.command.matches("(rm -rf|DROP TABLE|truncate)") message: "Destructive command blocked by policy" validationActions: [Deny] ``` ### See also - [MCP Governance](https://docs.aicontrols.dev/docs/concepts/mcp-governance) --- ## Generic Webhook Source: https://docs.aicontrols.dev/docs/tasks/configure-webhook > Send AIControls audit events and alerts to any HTTP endpoint using the generic webhook integration. Forward audit events, policy denials, budget alerts, and HITL notifications to any HTTP endpoint. Useful for connecting AIControls to internal SIEM systems, custom dashboards, or workflow automation tools. ### Configure the webhook - Go to **Settings → Integrations → Generic Webhook** and click **Add webhook**. - Enter your endpoint URL — must be HTTPS and publicly reachable from AIControls servers. - Optionally set a signing secret. AIControls will include an `X-AIControls-Signature` header on every request so you can verify authenticity. - Select which event types to send (see below). - Click **Save**. AIControls sends a test POST immediately — confirm your endpoint returns `2xx`. ### Payload format All events are delivered as HTTP POST with `Content-Type: application/json`. The envelope is consistent across event types: ```json { "event_type": "tool_denied", "timestamp": "2026-06-30T12:34:56Z", "workspace": "your-org", "data": { ... } } ``` Your endpoint must return a `2xx` status within 10 seconds. AIControls retries up to 3 times with exponential backoff on non-2xx or timeout. ### Event types | Event type | Triggered when | |---|---| | `tool_denied` | A policy denies an MCP tool call or LLM request | | `budget_alert` | Org or team spend reaches the configured alert threshold | | `budget_exceeded` | Org or team spend cap is hit — new requests are blocked | | `hitl_pending` | A request is queued for human approval | | `hitl_resolved` | A HITL request is approved or denied | | `policy_violation` | Content safety or PII policy triggers | ### Signature verification If you configured a signing secret, each request includes: ``` X-AIControls-Signature: sha256= ``` Compute `HMAC-SHA256(secret, raw-request-body)` and compare. Reject requests where the signature doesn't match. ### Troubleshooting #### Test delivery failed Check that your endpoint is publicly reachable over HTTPS and returns `2xx`. Firewall rules, self-signed certificates, or redirects (301/302) will cause delivery failures. #### Events not arriving Confirm the event type is enabled in the webhook configuration. Check **Settings → Integrations → Webhook → Delivery log** for recent attempts and response codes. --- ## Slack Source: https://docs.aicontrols.dev/docs/tasks/configure-slack > Send AIControls alerts, policy denials, and HITL approval requests to Slack channels. Route policy denial alerts, budget warnings, and human-in-the-loop approval requests to Slack channels. Approvers can act on HITL requests directly from Slack. ### Prerequisites - A Slack workspace where you have permission to add an app or create an incoming webhook - AIControls admin access ### Configure the integration - In Slack, go to **api.slack.com/apps**, create a new app, and enable **Incoming Webhooks**. Copy the webhook URL for the target channel. - In AIControls, go to **Settings → Integrations → Slack** and click **Add integration**. - Paste the webhook URL and give the integration a name (e.g. `#security-alerts`). - Select which event types should be delivered to this channel. - Click **Save**. AIControls sends a test message immediately — confirm it appears in the channel. :::note You can configure multiple Slack integrations pointing to different channels — for example, routing budget alerts to `#finops` and policy denials to `#security`. ::: ### Which events fire | Event | Default channel behaviour | |---|---| | Policy denial | Sent to all configured Slack integrations with the `tool_denied` event enabled | | Budget alert (80%) | Sent when org or team spend crosses the alert threshold | | Budget exceeded | Sent when the cap is hit and requests start being blocked | | HITL pending | Sent to the approver channel with Approve / Deny action buttons | Event routing is configurable per integration in **Settings → Notifications → Routing**. ### HITL approvals in Slack When a HITL approval request fires, AIControls posts an interactive message with **Approve** and **Deny** buttons. Clicking either responds immediately — no browser login required. The outcome is recorded in the Audit Log with the approver's Slack identity. :::note HITL interactive buttons require the Slack app to have **Interactivity** enabled and a valid **Request URL** pointing to your AIControls workspace. See **Settings → Integrations → Slack → Advanced** for the URL to paste into your Slack app config. ::: ### Troubleshooting #### Test message not appearing Confirm the incoming webhook URL is for the correct workspace and channel. Slack disables webhooks for deleted channels — create a new webhook if the channel was removed and recreated. #### HITL buttons not working Verify the Interactivity Request URL in your Slack app config matches `https://YOUR_ORG.aicontrols.dev/api/v1/integrations/slack/actions`. The endpoint must be reachable from Slack's servers. --- ## Microsoft Teams Source: https://docs.aicontrols.dev/docs/tasks/configure-teams > Send AIControls alerts and HITL approval requests to Microsoft Teams channels. Route policy denial alerts, budget warnings, and human-in-the-loop approval requests to Microsoft Teams channels via incoming webhooks. ### Prerequisites - A Microsoft Teams channel where you can add a connector - AIControls admin access ### Configure the integration - In Microsoft Teams, open the target channel, click **···** → **Connectors** → **Incoming Webhook**. Configure the webhook and copy the URL. - In AIControls, go to **Settings → Integrations → Microsoft Teams** and click **Add integration**. - Paste the webhook URL and give the integration a name. - Select which event types should be delivered to this channel. - Click **Save**. AIControls sends a test card immediately — confirm it appears in the Teams channel. ### Which events fire | Event | Behaviour | |---|---| | Policy denial | Adaptive Card with agent identity, tool name, and denial reason | | Budget alert (80%) | Card with current spend, cap, and a link to the Cost dashboard | | Budget exceeded | Card with blocked status and instructions to raise the cap | | HITL pending | Card with request details; approvers click a link to act in the AIControls UI | :::note Teams incoming webhooks don't support interactive action buttons. HITL approval cards include a direct link to the Approvals page in AIControls where the approver can act. ::: ### Troubleshooting #### Test card not appearing Confirm the connector is still active in Teams — connectors can be removed by channel owners or auto-disabled after inactivity. Recreate the incoming webhook and update the URL in AIControls if needed. #### Cards appearing without formatting Some Teams tenants restrict Adaptive Cards. If cards appear as raw JSON or plain text, contact your Teams administrator to allow Adaptive Card rendering for incoming webhooks. --- ## S3 / Object Store Source: https://docs.aicontrols.dev/docs/tasks/configure-s3 > Stream AIControls audit logs to S3-compatible object storage for long-term retention and SIEM ingestion. Export AIControls audit events to any S3-compatible object store — AWS S3, Google Cloud Storage, Azure Blob Storage, or MinIO. Useful for long-term retention, compliance archiving, and feeding events into a SIEM. ### Prerequisites - An S3 bucket (or GCS/Azure Blob container) with write access - An access key ID and secret (or service account credentials) with `s3:PutObject` permission - AIControls admin access ### Configure the integration - Go to **Settings → Integrations → S3 / Object Store** and click **Add integration**. - Select your provider: **AWS S3**, **Google Cloud Storage**, **Azure Blob Storage**, or **S3-compatible** (MinIO, Cloudflare R2, etc.). - Enter the bucket name, region, and credentials. For S3-compatible providers, enter a custom endpoint URL. - Set the key prefix (e.g. `aicontrols/audit/`). Objects are written as `<prefix>YYYY/MM/DD/<timestamp>.ndjson.gz`. - Click **Test connection** — AIControls writes a small test object and reads it back. Confirm success before saving. - Click **Save**. Audit events begin streaming to the bucket within minutes. ### Export format Events are exported as newline-delimited JSON (`.ndjson`), gzip-compressed. Each line is one audit event with the same schema as the Audit Log API: ```json {"event_type":"tool_call","timestamp":"2026-06-30T12:34:56Z","agent":"claude-code","tool":"bash","decision":"allow","identity":"alice@example.com"} {"event_type":"llm_request","timestamp":"2026-06-30T12:35:01Z","agent":"claude-code","model":"claude-sonnet-4-6","decision":"allow","tokens_in":1200,"tokens_out":340} ``` ### Retention and rotation AIControls batches events and flushes to S3 every 5 minutes or when the batch reaches 10 MB — whichever comes first. Objects are named by UTC timestamp so they sort chronologically in any S3 browser. Set lifecycle rules on the bucket directly in your cloud provider to enforce retention (e.g. expire objects after 90 days, transition to Glacier after 30 days). :::note S3 export complements — not replaces — the built-in SQLite audit store. AIControls retains events locally for the configured `session_retention_days` window regardless of whether S3 export is enabled. ::: ### Troubleshooting #### Test connection fails Check that the credentials have `s3:PutObject` and `s3:GetObject` on the target bucket and prefix. Some bucket policies also require `s3:ListBucket` for the test — add it temporarily if needed. #### Events delayed or missing Events are batched — up to a 5-minute delay is expected. If objects stop appearing entirely, check **Settings → Integrations → S3 → Delivery log** for export errors. Common causes: expired credentials, full bucket quota, or a changed bucket policy. --- ## Manage Builder Portal Access Source: https://docs.aicontrols.dev/docs/tasks/manage-builder-portal-access > Sign in to the Builder Portal, create and revoke access tokens, connect AI tools, manage connected accounts, and request policy exceptions. Procedures for signing in to the Builder Portal and managing your access tokens, connected accounts, sessions, and policy exceptions. ### Accessing the portal - Go to your workspace URL. - Sign in with your developer credentials. The Builder Portal opens by default — no admin role is required. :::note Admins also have access to the Builder Portal from the same workspace. ::: ### Access tokens #### Create a token - Go to **Access Tokens** and click **Create New Token**. - Give the token a name that identifies the tool or machine (e.g. **claude-code-macbook**). - Select an expiry: 30, 60, 90, 180, or 365 days. - Click **Create**. The token is shown once — copy it immediately. It cannot be retrieved again. :::warning The token value is only shown at creation time. If you lose it, revoke and create a new one. ::: To revoke a token, click **Revoke** next to it in the Access Tokens list — it stops working immediately. #### Connect your AI tool - Create a token as described above. - On the **Access Tokens** tab, copy the ready-to-paste shell command shown for your tool and shell (bash, zsh, fish). - Choose a connection mode: **Proxy mode** (all LLM and MCP traffic routes through the AIControls proxy) or **Passthrough mode** (your tool keeps its existing upstream configuration; AIControls intercepts via a lightweight observer). - Run the command in your terminal, then restart your AI tool. See the [Claude Code](https://docs.aicontrols.dev/docs/tasks/connect-claude-code), [Cursor](https://docs.aicontrols.dev/docs/tasks/connect-cursor), [Codex](https://docs.aicontrols.dev/docs/tasks/connect-codex), or [GitHub Copilot](https://docs.aicontrols.dev/docs/tasks/connect-copilot) pages for tool-specific details. ### Sessions and projects **Sessions** and **Projects** are described in [Builder Portal](https://docs.aicontrols.dev/docs/concepts/builder-portal#sessions). The one action available here: open a session's detail drawer to end an active or degraded session. ### Connected accounts #### Manage a stored credential - Go to **Connected Accounts**. - Find the datasource under **Stored credentials**. - Click **Connect** (if not yet connected) or **Update** (to refresh an expired or existing credential). #### Configure a client-side credential - Go to **Connected Accounts** and find the datasource under **Client-configured** credentials. - Click **View Config** to generate the client configuration snippet for that datasource. - Add the header shown to your AI tool's configuration. AIControls does not store these credentials. ### Policy exceptions - Go to **Policy Exceptions** to view exceptions granted for your identity — operations that would normally be denied by policy but have been explicitly approved, each with an expiry date. - To request a new exception, submit it via the HITL approval flow or contact your admin directly. You cannot create exceptions yourself. ### See also - [Builder Portal](https://docs.aicontrols.dev/docs/concepts/builder-portal) --- ## Policy Context Source: https://docs.aicontrols.dev/docs/reference/policy-context > The full set of fields available to CEL policy expressions, plus the built-in policy library. Every CEL expression evaluates against an object map pre-populated from the request. This page lists every available field, its type, and what it contains. ### Available context Every CEL expression evaluates against an `object` map pre-populated from the request. The fields are grouped by namespace below. Use `object.mcp.tool != ""` to target MCP tool calls and `object.llm.model != ""` to target LLM calls — both are empty for the other type. #### Agent identity — `object.agent.*` | Field | Type | Description | |---|---|---| | `object.agent.agentId` | string | Unique agent or developer identifier (email or agent ID) | | `object.agent.namespace` | string | Kubernetes namespace of the agent's service account | | `object.agent.capabilities` | list<string> | Granted capability tags, e.g. `"premium-models"` | | `object.agent.labels` | map<string,string> | Custom agent metadata, e.g. cost center or environment tag | | `object.agent.quarantined` | bool | `true` if the agent is suspended | | `object.agent.tokenClaims` | map | All raw JWT claims — useful for custom IdP attributes | #### MCP tool call — `object.mcp.*` | Field | Type | Description | |---|---|---| | `object.mcp.tool` | string | MCP tool name, e.g. `bash`, `read_file`. Empty for LLM calls. | | `object.mcp.arguments` | map | Tool arguments. Access with `object.mcp.arguments.path`; use `has()` to guard optional keys. | | `object.mcp.command` | string | Shell command text (shell tools only) | | `object.mcp.commandRisk` | string | Pre-classified risk: `"risky"`, `"moderate"`, or `"safe"` | | `object.mcp.trustTier` | string | MCP server trust: `"trusted/internal"`, `"trusted/verified"`, `"untrusted/external"` | #### LLM call — `object.llm.*` | Field | Type | Description | |---|---|---| | `object.llm.model` | string | Requested model identifier, e.g. `claude-sonnet-4-6`. Empty for MCP calls. | | `object.llm.tier` | string | Cost tier: `"premium"`, `"standard"`, or `"economy"` | | `object.llm.inputTokens` | int | Input token count for this request (0 if not yet known) | | `object.llm.currentPrompt` | string | Text of the last user message | | `object.llm.messages` | list | Full conversation history — each item has `role` and `content` | | `object.llm.upstream.zeroDataRetention` | bool | Upstream provider guarantees zero data retention | | `object.llm.upstream.jurisdiction` | string | Data residency region, e.g. `"EU"`, `"US"` | #### Delegating user — `object.user.*` Populated when a human OIDC token is present alongside the agent token. All fields are empty / false for machine-to-machine calls — guard with `object.user.isPresent`. | Field | Type | Description | |---|---|---| | `object.user.isPresent` | bool | `true` if a user token was validated | | `object.user.email` | string | User email from OIDC token | | `object.user.groups` | list<string> | OIDC group memberships | | `object.user.roles` | list<string> | OIDC roles or approved actions | | `object.user.tokenClaims` | map | Raw user JWT claims for custom IdP attributes | #### Session context — `object.session.*` Populated when the request carries a session token. Enables budget-aware and intent-aware policies. | Field | Type | Description | |---|---|---| | `object.session.isPresent` | bool | `true` if a session context is active | | `object.session.developerId` | string | Email of the developer who started the session | | `object.session.intent` | string | Declared session purpose | | `object.session.ticketId` | string | Associated Jira / GitHub issue ID | | `object.session.budgetUSD` | float | Allocated cost budget for this session | | `object.session.spentUSD` | float | Cost spent so far in this session | | `object.session.percentUsed` | float | Fraction of budget consumed (0.0–1.0) | | `object.session.toolCallCount` | int | Total tool calls in the session | | `object.session.deniedInSession` | int | Policy denials already recorded in this session | | `object.session.toolsCalledInSession` | list<string> | Distinct tools used so far (capped at 200) | #### Context efficiency — `object.context.*` Real-time signals from the session anomaly detector, injected at policy evaluation time. All fields default to `0` when monitoring is not enabled. | Field | Type | Description | |---|---|---| | `object.context.fillPct` | float | Fraction of the model's context window currently in use (0.0–1.0) | | `object.context.loopScore` | float | Structural repetition score across recent outputs (0.0–1.0; higher = more looping) | | `object.context.repeatReadCount` | int | Times the same file or resource has been read in this session | | `object.context.latencyGrowthRatio` | float | Current call latency relative to session baseline (>1.0 = degrading) | | `object.context.cacheHitRate` | float | Fraction of prompt tokens served from cache (0.0–1.0) | #### Time — top-level variable | Variable | Type | Description | |---|---|---| | `now` | timestamp | Current wall-clock time at policy evaluation. Use `now.getHours()`, `now.getDayOfWeek()` for business-hours rules. | ### Built-in policy library AIControls ships with a curated library of policies covering common governance scenarios. Enable them from **Policies → Library**: | Category | Example policies | |---|---| | Security | Block credential patterns in prompts, deny requests with PII in tool arguments | | Cost | Enforce model tiers by developer group, block Opus for non-engineering roles | | Compliance | Require audit mode for regulated data namespaces, block data export tools | | Operations | Rate-limit bash calls per session, require HITL for infrastructure mutations | ### See also - [Policies](https://docs.aicontrols.dev/docs/concepts/policies) --- ## Decision Types Source: https://docs.aicontrols.dev/docs/reference/decision-types > The full set of governance decisions that can appear in the Audit Log. Every audit event records a decision — the outcome of evaluating the request against your policies. ### Decision types | Decision | Meaning | | --- | --- | | **Allow** | Request passed all policy checks and was forwarded to the upstream | | **Deny** | Request was blocked by a policy or budget rule; the caller received an error | | **Audit** | Request was allowed but flagged — typically by an audit-mode rule or anomaly detection | | **Warn** | Request was allowed with a warning appended to the response | | **Held** | Request is waiting for human approval in the Approvals queue | ### See also - [Audit Log](https://docs.aicontrols.dev/docs/concepts/audit-log) --- ## Admin MCP Server Source: https://docs.aicontrols.dev/docs/reference/admin-mcp-server > Tools exposed by the admin MCP server. AIControls exposes its own MCP server so you can query governance data directly from Claude Code or any MCP client. ### Admin MCP server AIControls exposes its own MCP server at `https://YOUR_ORG.aicontrols.dev/mcp/admin`. This lets you query governance data directly from Claude Code or any MCP client: | Tool | Description | |---|---| | `aicontrols_audit_query` | Search audit events by agent, tool, decision, or time range | | `aicontrols_cost_summary` | Get aggregate cost and token usage by developer or model | | `aicontrols_risk_scores` | Return computed risk scores for agents | | `aicontrols_session_list` | List active developer sessions with budget utilization | | `aicontrols_hitl_list` | List pending human-in-the-loop approval requests | | `aicontrols_policy_list` | List loaded policies with match statistics | Authenticate to the admin MCP server with an admin-role personal access token. Connect it to Claude Code by adding it to your MCP server list in `~/.claude/settings.json`: ```json { "mcpServers": { "aicontrols": { "url": "https://YOUR_ORG.aicontrols.dev/mcp/admin", "headers": { "Authorization": "Bearer YOUR_ADMIN_TOKEN" } } } } ``` ### See also - [MCP Governance](https://docs.aicontrols.dev/docs/concepts/mcp-governance) --- ## Compliance Controls Source: https://docs.aicontrols.dev/docs/reference/compliance-controls > The full list of NIST AI RMF control categories assessed by AIControls, and what is checked in each. The controls assessed by AIControls span the following AI RMF categories. ### Control categories | Category | Examples of what AIControls assesses | |---|---| | **Govern** | Policy documentation, approval workflows, exception tracking, audit log retention | | **Map — Risk Identification** | Identity attribution, tool classification, blast-radius tracking, anomaly detection coverage | | **Measure — Monitoring** | Continuous audit logging, behavioral baselines, token spike detection, violation rate tracking | | **Measure — Content Safety** | PII detection, prompt injection scanning, output filtering policies | | **Manage — Human Oversight** | HITL approval rules for high-risk operations, auto-pause configuration, session review | | **Manage — Access Control** | Identity-scoped budget rules, tool-level allow/deny policies, PAT scope restrictions | | **Manage — Incident Response** | Alert routing, anomaly escalation, session pause capability, audit export for investigation | ### See also - [Compliance](https://docs.aicontrols.dev/docs/concepts/compliance) ---