# Drift Detection
Source: https://docs.anyshift.io/pages/iac/drift_detection
Find the gap between what you declared in Terraform and what is actually running in your cloud and Kubernetes clusters.
## Overview
Drift happens. Someone edits a security group in the AWS console, an engineer scales a deployment manually, a failed `terraform apply` leaves state out of sync. Annie continuously correlates your **declared** infrastructure (Terraform code + state) with your **actual** infrastructure (live cloud, live Kubernetes) and surfaces the gaps.
What your Terraform modules and manifests say should exist.
What your Terraform state believes it's tracking.
What's really running in AWS, GCP, and Kubernetes right now.
## What You Can Ask Annie
* *"What resources were modified outside of Terraform this week?"*
* *"Show me security groups changed via the AWS console in the last 24 hours"*
* *"Which IAM roles had policies attached manually?"*
* *"Which live resources are not in any Terraform state file?"*
* *"Show me EC2 instances with no Terraform backing"*
* *"Which S3 buckets exist in AWS but aren't declared anywhere?"*
* *"Are my declared replica counts matching the pods actually running?"*
* *"Show me deployments where ready replicas differ from desired"*
* *"Which ConfigMaps were edited directly in the cluster?"*
* *"Which Terraform resources reference dependencies that no longer exist?"*
* *"Show me state entries pointing to deleted cloud resources"*
## Real-World Examples
PagerDuty alerted on an unexpected SSH attempt against a dev box.
*"Has any security group been changed outside Terraform this week?"*
> I found 2 manual changes:
>
> * `sg-dev-debug`: Port 22 opened to `0.0.0.0/0` via AWS console on Tuesday 14:03 by user `alice@...`
> * `sg-prod-db`: Inbound rule for `10.0.5.0/24` added via CLI on Wednesday 09:17
>
> Neither change is reflected in the Terraform code or state.
The checkout service is flaky. I suspect a partial rollout.
*"Which deployments have fewer ready replicas than declared?"*
> 3 deployments have drift:
>
> * `checkout`: declared 8, ready: 5 (3 pods in `ImagePullBackOff`)
> * `billing-worker`: declared 4, ready: 4 ✓ (no drift)
> * `search-indexer`: declared 2, ready: 0 (OOMKilled, CrashLoopBackOff)
>
> The `checkout` image tag in your Helm values doesn't exist in the registry.
I suspect the cloud bill has resources nobody remembers.
*"Show me EC2 instances and RDS databases not backed by any Terraform state"*
> I found 7 unmanaged resources across your AWS accounts:
>
> * 4 EC2 instances in `us-east-1` (tagged `env=experiment`, launched 2024)
> * 2 RDS snapshots in `eu-west-1` (no source instance exists)
> * 1 NAT Gateway in `us-west-2` (no route table references it)
## Best Practices
Ask Annie for drift in the target environment before running `terraform plan`. It often explains surprising diffs.
Drift queries are more useful when narrowed: *"...in the `prod` workspace"*, *"...in the `networking` module"*.
Pair drift queries with [Change Management](/pages/product/time_travel) to see *who* made the change and *when*.
Unmanaged resources are both a cost and a security concern. Ask Annie monthly.
## Get Started
You need code + state connected for drift detection to work.
Install the agent to get declared-vs-actual drift inside your clusters.
# Kubernetes (Live)
Source: https://docs.anyshift.io/pages/iac/kubernetes_live
Anyshift streams live Kubernetes cluster state via an in-cluster agent and correlates it with your Terraform and application code.
## Overview
The Anyshift Kubernetes agent runs in your cluster and streams **live resource state** to Annie's knowledge graph in near real-time. That live state is linked back to your Terraform declarations (for resources Terraform manages) and your application code, giving Annie a full picture from *declared* to *actually running*.
For installation and setup, see the [Kubernetes integration page](/pages/integration/kubernetes). This page focuses on **what Annie does** with the data.
## What the Agent Captures
* Pods, Deployments, ReplicaSets, StatefulSets, DaemonSets
* Services, Ingresses
* ConfigMaps, Secrets
* PersistentVolumeClaims, PersistentVolumes
* Namespaces, Nodes
* RBAC (Roles, RoleBindings, ClusterRoles, ClusterRoleBindings)
* HorizontalPodAutoscalers, PodDisruptionBudgets
* Jobs, CronJobs
* KEDA ScaledObjects / ScaledJobs
* ...
**Helm-deployed workloads** are visible too: Annie sees the Kubernetes resources that Helm created. Release-level metadata (chart version, revision history) isn't modeled as a first-class entity today.
## What You Can Ask Annie
* *"How many pods are running in the `payments` namespace?"*
* *"Which deployments have zero available replicas?"*
* *"Show me all pods in CrashLoopBackOff"*
* *"Which services expose port 443?"*
* *"Are my declared replica counts matching what's actually running?"*
* *"Which workloads have fewer ready pods than desired?"*
* *"Show me resources in the cluster that weren't deployed by Helm or Terraform"*
* *"Which Terraform module provisioned this cluster?"*
* *"What application code runs in this pod?"*
* *"Which RDS instance does this deployment connect to?"*
## Real-World Example
Checkout service is slow. I want to know if it's a scaling issue.
*"Is the checkout service scaled correctly?"*
> The `checkout` deployment is declared with `replicas: 8`.
>
> * 8 ReplicaSet replicas scheduled
> * **Only 5 pods Ready** (3 are `ImagePullBackOff` on `checkout:v2.3.1`)
> * HPA is at max (`target: 80% CPU`, `current: 94%`)
>
> The underlying image pull is failing, likely a registry auth issue introduced by the latest deploy.
## Get Started
Deploy the Anyshift Kubernetes agent via Helm.
See how live K8s state fits into the three-universe model.
# Infrastructure as Code
Source: https://docs.anyshift.io/pages/iac/overview
Anyshift is built on IaC. Annie correlates your Terraform code, Terraform state, and live infrastructure so you always know what you declared, what you stored, and what is actually running.
## Built on Infrastructure as Code
Anyshift doesn't just read your cloud. It reads your **code**, your **state**, and your **live infrastructure**, then correlates the three so you can see where they agree and where they've drifted.
Declared resources are linked to the state that instantiated them, and state entries are linked to the live resources they manage. That's how Annie answers questions that span layers: *"Which module deployed this pod?"*, *"What code manages this RDS instance?"*, *"Which resources are running without any Terraform backing?"*
The same model applies to Kubernetes: declared manifests (or Helm charts) → live cluster state, streamed by the Anyshift agent.
## See the graph
Annie can also draw the graph. Ask *"map our cluster"* or *"diagram the dependencies of the payment service"* and she renders the live topology from the [knowledge graph](/pages/overview/knowledge_graph) as a diagram you can read at a glance.
The diagram comes from the same graph that powers [Annie Knowledge](/pages/product/annie_knowledge), so it shows what is *actually running* right now: real resource names, live dependencies, and gaps like a missing config or an unmanaged instance. No stale wiki sketch.
### Working with diagrams
Zoom, pan, and open any diagram fullscreen to follow a dependency chain across layers.
Every diagram lands in [**Artifacts → Diagrams**](https://app.anyshift.io/artifacts), so you can reopen and share it later.
Diagrams are plain [Mermaid](https://mermaid.js.org). Copy the source and paste it into GitHub, Notion, or any Mermaid-compatible tool.
Ask for a diagram in a [conversation](/pages/product/annie_knowledge), and dig deeper with a follow-up question right where you are.
## What You Can Ask Annie
* *"Which Terraform module created this EC2 instance?"*
* *"Show me all resources defined in the networking module"*
* *"What variables does this state file use?"*
* *"What resources were modified outside of Terraform this week?"*
* *"Which live resources have no Terraform backing?"*
* *"Are my declared replicas matching the pods actually running?"*
See the [Drift Detection](/pages/iac/drift_detection) page for more.
* *"What breaks if I destroy this module?"*
* *"Which services depend on this security group?"*
* *"If I change this variable, what resources are affected?"*
## Explore the IaC Section
How Annie ingests Terraform code and state, and what she does with them.
How Annie streams live cluster state and ties it to your declared K8s manifests.
Find the gap between what you declared and what's actually running.
How all of this connects under the hood.
# Terraform
Source: https://docs.anyshift.io/pages/iac/terraform
Anyshift ingests your Terraform code and state, then correlates them against live cloud infrastructure to power drift detection, impact analysis, and code-to-infra queries.
## Overview
Anyshift treats Terraform as a first-class citizen. Annie reads your **code** (modules, resources, variables) and your **state** (`.tfstate` files from S3 or HCP Terraform Cloud), and links both to the actual cloud resources they manage.
HCL parsed from your connected Git repositories: modules, resources, data sources, variables, outputs, and inter-module references.
`.tfstate` ingested from S3 buckets and HCP Terraform Cloud workspaces. Managed instances are linked back to their declarations and forward to the live cloud resources they manage.
## How It Connects
Once your Terraform code and state are both connected, Annie builds this chain in her knowledge graph:
That chain is what lets you ask questions across layers, from code, to state, to the running resource, without leaving the chat.
## Connecting Your Terraform
Connect GitHub or GitLab to ingest your Terraform modules, resources, and references.
Connect HashiCorp Cloud Platform workspaces to ingest state from HCP Terraform Cloud.
**S3 state buckets are auto-discovered.**
If your Terraform state lives in S3, there's nothing extra to configure. Once your AWS account is connected, Annie detects state buckets automatically from your ingested Terraform backend blocks and from AWS API extraction. You'll see them in the Anyshift app under Integrations → Terraform Backends.
## What You Can Ask Annie
* *"Which resources are managed by Terraform vs. manually?"*
* *"Show me all modules that use the `aws_instance` resource"*
* *"Which workspaces deploy to the `prod` environment?"*
* *"What variables does the networking module expose?"*
* *"What resources depend on this module?"*
* *"If I destroy this VPC, what breaks?"*
* *"Which services will be affected by changing this security group rule?"*
* *"What resources were modified outside of Terraform?"*
* *"Which live resources are not in any state file?"*
See the [Drift Detection](/pages/iac/drift_detection) page for more.
## Real-World Examples
I just ran `terraform apply` and want to verify what actually changed.
*"What changed in the last 30 minutes?"*
> I found 5 resources updated:
>
> * `aws_instance.prod-api-1`: instance\_type → t3.large
> * `aws_instance.prod-api-2`: instance\_type → t3.large
> * `aws_autoscaling_group.prod-api-asg`: desired\_capacity → 4
> * `aws_lb_target_group.prod-api-tg`: 2 new targets
> * `aws_cloudwatch_metric_alarm.prod-api-cpu`: threshold → 80
>
> All changes match your most recent plan.
I'm about to refactor a shared module and want to know what depends on it.
*"What uses the `shared-networking` module?"*
> 14 workspaces reference `shared-networking`:
>
> * `platform-prod` (3 VPCs, 12 subnets)
> * `data-prod` (1 VPC, 6 subnets)
> * `security-prod` (consumes outputs: vpc\_id, private\_subnets)
> * ...
>
> Breaking changes to the outputs will require coordinated updates.
## Get Started
Ingest your Terraform code.
Ingest your Terraform state from HCP (S3 is auto-detected).
# AWS Integration
Source: https://docs.anyshift.io/pages/integration/aws
Connect Annie to your AWS account for real-time infrastructure mapping and monitoring.
# Overview
Connect your AWS account to Annie for real-time infrastructure mapping, monitoring, and intelligent insights. Annie ingests your AWS resources and relationships to build a knowledge graph of your cloud environment.
Annie is read-only: it uses `Describe*` / `List*` / `Get*` actions only, takes no write actions, and cannot modify your infrastructure. See the [IAM permissions reference](#iam-permissions-reference) for exactly what is read.
# Setup
The recommended path is a least-privilege managed policy attached to an assume role. For an IAM user instead, see [Alternative: IAM user](#alternative-iam-user).
Go to the [Anyshift integrations page](https://app.anyshift.io/integrations) and navigate to the AWS section.
Create the least-privilege managed policy Annie uses. The same policy is reused by the assume role and the IAM user options.
```hcl theme={null}
data "aws_iam_policy_document" "annie_readonly" {
statement {
sid = "AllowS3Metadata"
effect = "Allow"
actions = [
"s3:GetAccessPoint",
"s3:GetAccessPointPolicy",
"s3:GetBucketLocation",
"s3:GetBucketNotification",
"s3:GetEncryptionConfiguration",
"s3:GetMultiRegionAccessPoint",
"s3:GetMultiRegionAccessPointRoutes",
"s3:ListAccessPoints",
"s3:ListAllMyBuckets",
"s3:ListBucket",
"s3:ListMultiRegionAccessPoints",
]
resources = ["*"]
}
statement {
sid = "AllowComputeResources"
effect = "Allow"
actions = [
"ec2:Describe*",
"ecs:Describe*",
"ecs:List*",
"eks:DescribeAddon",
"eks:DescribeCluster",
"eks:DescribeNodegroup",
"eks:ListAddons",
"eks:ListClusters",
"eks:ListNodegroups",
"ecr:DescribeRepositories",
"ecr:GetRepositoryPolicy",
"lambda:GetAlias",
"lambda:GetEventSourceMapping",
"lambda:GetFunction",
"lambda:GetFunctionConfiguration",
"lambda:GetFunctionUrlConfig",
"lambda:List*",
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribePolicies",
"application-autoscaling:DescribeScalableTargets",
"application-autoscaling:DescribeScalingPolicies",
]
resources = ["*"]
}
statement {
sid = "AllowStorageResources"
effect = "Allow"
actions = [
"rds:Describe*",
"rds:ListTagsForResource",
"dynamodb:DescribeKinesisStreamingDestination",
"dynamodb:DescribeTable",
"dynamodb:GetResourcePolicy",
"dynamodb:ListTables",
"elasticache:DescribeCacheClusters",
"elasticache:DescribeCacheParameterGroups",
"elasticache:DescribeCacheSubnetGroups",
"elasticache:DescribeReplicationGroups",
"elasticache:DescribeServerlessCaches",
"backup:DescribeBackupVault",
"backup:DescribeRecoveryPoint",
"backup:GetBackupPlan",
"backup:GetBackupSelection",
"backup:GetBackupVaultAccessPolicy",
"backup:GetBackupVaultNotifications",
"backup:List*",
]
resources = ["*"]
}
statement {
sid = "AllowNetworkResources"
effect = "Allow"
actions = [
"elasticloadbalancing:Describe*",
"route53:GetHostedZone",
"route53:GetQueryLoggingConfig",
"route53:GetReusableDelegationSet",
"route53:List*",
"cloudfront:GetDistribution",
"cloudfront:GetDistributionConfig",
"cloudfront:ListDistributions",
"cloudfront:ListFunctions",
"cloudfront:ListTagsForResource",
]
resources = ["*"]
}
statement {
sid = "AllowIdentityResources"
effect = "Allow"
actions = [
"iam:Get*",
"iam:List*",
]
resources = ["*"]
}
statement {
sid = "AllowMonitoringResources"
effect = "Allow"
actions = [
"cloudwatch:DescribeAlarms",
"cloudwatch:GetMetricStatistics",
"cloudwatch:ListMetrics",
"logs:DescribeLogGroups",
"events:List*",
]
resources = ["*"]
}
statement {
sid = "AllowApplicationResources"
effect = "Allow"
actions = [
"sns:GetTopicAttributes",
"sns:ListSubscriptionsByTopic",
"sns:ListTopics",
"sqs:GetQueueAttributes",
"sqs:GetQueueUrl",
"sqs:ListDeadLetterSourceQueues",
"sqs:ListQueues",
"apigateway:GET",
"elasticmapreduce:DescribeStudio",
"elasticmapreduce:ListStudioSessionMappings",
"elasticmapreduce:ListStudios",
"kinesis:DescribeStreamSummary",
"kinesis:GetResourcePolicy",
"kinesis:ListStreams",
"kinesis:ListTagsForStream",
"states:DescribeStateMachine",
"states:ListStateMachines",
"states:ListTagsForResource",
]
resources = ["*"]
}
statement {
sid = "AllowKMS"
effect = "Allow"
actions = [
"kms:DescribeKey",
"kms:GetKeyPolicy",
"kms:GetKeyRotationStatus",
"kms:ListAliases",
"kms:ListKeyPolicies",
"kms:ListKeys",
"kms:ListResourceTags",
]
resources = ["*"]
}
statement {
sid = "AllowNotifications"
effect = "Allow"
actions = [
"codestar-notifications:DescribeNotificationRule",
"codestar-notifications:ListNotificationRules",
"notifications:ListEventRules",
"notifications:ListNotificationConfigurations",
]
resources = ["*"]
}
statement {
sid = "AllowAdditionalServices"
effect = "Allow"
actions = [
"acm:DescribeCertificate",
"acm:GetCertificate",
"acm:ListCertificates",
"acm:ListTagsForCertificate",
"athena:GetDataCatalog",
"athena:GetWorkGroup",
"athena:ListDataCatalogs",
"athena:ListDatabases",
"athena:ListEngineVersions",
"athena:ListWorkGroups",
"codebuild:BatchGetProjects",
"codebuild:ListProjects",
"codebuild:ListSourceCredentials",
"docdb-elastic:GetCluster",
"docdb-elastic:ListClusters",
"docdb-elastic:ListTagsForResource",
"emr-serverless:GetApplication",
"emr-serverless:ListApplications",
"firehose:DescribeDeliveryStream",
"firehose:ListDeliveryStreams",
"firehose:ListTagsForDeliveryStream",
"glue:GetConnection",
"glue:GetCrawler",
"glue:GetCrawlers",
"glue:GetDatabases",
"glue:GetJob",
"glue:GetJobs",
"glue:GetSecurityConfiguration",
"glue:GetTable",
"glue:GetTables",
"memorydb:DescribeACLs",
"memorydb:DescribeClusters",
"memorydb:DescribeParameterGroups",
"memorydb:DescribeSubnetGroups",
"memorydb:DescribeUsers",
"airflow:GetEnvironment",
"airflow:ListEnvironments",
"airflow:ListTagsForResource",
"oam:GetSink",
"oam:ListAttachedLinks",
"oam:ListLinks",
"oam:ListSinks",
"ram:GetResourceShareAssociations",
"ram:GetResourceShares",
"ram:ListPrincipals",
"ram:ListResources",
"sagemaker:DescribeNotebookInstance",
"sagemaker:DescribeNotebookInstanceLifecycleConfig",
"sagemaker:ListNotebookInstanceLifecycleConfigs",
"sagemaker:ListNotebookInstances",
"secretsmanager:DescribeSecret",
"secretsmanager:GetResourcePolicy",
"secretsmanager:ListSecrets",
"ses:DescribeConfigurationSet",
"ses:GetIdentityNotificationAttributes",
"ses:ListConfigurationSets",
"ses:ListIdentities",
"transfer:DescribeServer",
"transfer:ListServers",
"vpc-lattice:GetAccessLogSubscription",
"vpc-lattice:GetResourcePolicy",
"vpc-lattice:GetServiceNetworkVpcAssociation",
"vpc-lattice:ListAccessLogSubscriptions",
"vpc-lattice:ListServiceNetworkResourceAssociations",
"vpc-lattice:ListServiceNetworkServiceAssociations",
"vpc-lattice:ListServiceNetworkVpcAssociations",
"vpc-lattice:ListServiceNetworks",
"waf:GetWebACL",
"waf:ListIPSets",
"waf:ListRuleGroups",
"waf:ListRules",
"waf:ListWebACLs",
"waf-regional:GetWebACL",
"waf-regional:ListIPSets",
"waf-regional:ListResourcesForWebACL",
"waf-regional:ListRuleGroups",
"waf-regional:ListRules",
"waf-regional:ListWebACLs",
"wafv2:GetWebACLForResource",
"wafv2:List*",
]
resources = ["*"]
}
statement {
sid = "AllowCloudTrailLookup"
effect = "Allow"
actions = [
"cloudtrail:LookupEvents",
]
resources = ["*"]
}
}
resource "aws_iam_policy" "annie_readonly" {
name = "annie-readonly"
policy = data.aws_iam_policy_document.annie_readonly.json
}
```
To restrict which S3 buckets Annie can introspect, see [Restrict S3 to specific buckets](#restrict-s3-to-specific-buckets) before applying.
Create an assume role that trusts the Annie account (`211125758836`) and attach the `annie-readonly` policy.
**Using Terraform (recommended)**
```hcl theme={null}
resource "aws_iam_role" "annie_assume_role" {
name = "annie-assume-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::211125758836:root"
}
Action = "sts:AssumeRole"
Condition = {
StringEquals = {
"sts:ExternalId" = "replace_with_optional_external_id"
}
}
}
]
})
}
resource "aws_iam_role_policy_attachment" "annie_readonly" {
role = aws_iam_role.annie_assume_role.name
policy_arn = aws_iam_policy.annie_readonly.arn
}
```
**Using AWS Console**
* Navigate to IAM Roles and select **Create Role**.
* Choose **Another AWS account** and enter the **Account ID**: `211125758836`.
* Add an **External ID** (Optional: acts as a shared secret).
* Attach the **`annie-readonly`** policy created above.
* Complete the role creation process.
* Copy the **Role ARN** for the next step.
* Navigate to Anyshift Configuration and select **Add AWS Role**.
* Enter a descriptive **Display Name** (e.g., `"read_only_role_for_anyshift"`).
* Paste the **Role ARN** from the previous step.
* Enter the **External ID** (Optional).
* Save the configuration.
## Features enabled
Real-time visibility into your cloud infrastructure
Understand your infrastructure dependencies
## Reference
The `annie-readonly` policy grants only what Annie needs for the **resource graph** (bucket inventory and per-bucket metadata only: no object reads, no data-plane access):
* **S3:** bucket inventory and per-bucket metadata (location, default encryption, event notifications, access points, multi-region access points). No object content is read for the resource graph.
* **Compute, network, identity, monitoring, application, KMS, notifications, and other services:** `Describe*` / `List*` / `Get*` only.
* **No write actions.** No `kms:Decrypt`, no `secretsmanager:GetSecretValue` (only `secretsmanager:GetResourcePolicy` for resource policies, not secret material).
* **CloudTrail:** `cloudtrail:LookupEvents` only. This lets Annie pull recent AWS API activity (who changed what) directly through this read-only role, without deploying the [CloudTrail forwarder](/pages/integration/aws/cloudtrail). It is read-only, returns only the last **90 days of management events**, and requires `Resource: "*"` (an AWS constraint: `LookupEvents` has no resource-level scoping). CloudTrail lookups are **per-region**: Annie always polls **US East (N. Virginia)** — where AWS records global-service events (IAM, STS, CloudFront, Route 53) — plus any additional regions we configure. Tell us which regions your workloads run in so we can include them; activity in regions we aren't polling won't appear.
To ingest **Terraform state files stored in S3**, an additional bucket-scoped grant is needed. See [Terraform state ingestion](#terraform-state-ingestion).
Use an IAM user instead of an assume role. Reuse the `annie-readonly` policy from the setup steps.
**Using Terraform (highly recommended)**
```hcl theme={null}
resource "aws_iam_user" "annie_user" {
name = "annie-readonly-user"
}
resource "aws_iam_access_key" "annie_access_key" {
user = aws_iam_user.annie_user.name
}
resource "aws_iam_user_policy_attachment" "annie_readonly" {
user = aws_iam_user.annie_user.name
policy_arn = aws_iam_policy.annie_readonly.arn
}
```
**Using AWS Console**
* Go to IAM → Users → Add User
* Enable Programmatic Access
* Attach the **`annie-readonly`** policy created in the setup steps.
* Save Access Key ID and Secret Access Key
**Configure in Anyshift**
* Enter the **Access Key ID** and **Secret Access Key** from the IAM user creation step.
* Provide a descriptive **AWS Account Name** label (e.g., `"read_only_user_for_anyshift"`).
Use this variant to introspect only certain S3 buckets. Bucket enumeration (`s3:ListAllMyBuckets`, `s3:GetBucketLocation`) cannot be resource-scoped at the IAM level: every bucket name and region stays visible. Per-bucket metadata (encryption, notifications) is read only for the buckets you list.
Keep the `data "aws_iam_policy_document" "annie_readonly"` block from setup unchanged. Add the blocks below in the same Terraform configuration, and change the `policy` argument on `aws_iam_policy.annie_readonly` from `data.aws_iam_policy_document.annie_readonly.json` to `data.aws_iam_policy_document.annie_readonly_bucket_scoped.json`.
```hcl theme={null}
data "aws_iam_policy_document" "annie_s3_scoped_override" {
statement {
sid = "AllowS3Metadata"
effect = "Allow"
actions = [
"s3:ListAllMyBuckets",
"s3:GetBucketLocation",
"s3:ListBucket",
]
resources = ["*"]
}
statement {
sid = "AllowS3IntrospectionScoped"
effect = "Allow"
actions = [
"s3:GetEncryptionConfiguration",
"s3:GetBucketNotification",
]
resources = [
"arn:aws:s3:::your-bucket-name-1",
"arn:aws:s3:::your-bucket-name-2",
]
}
}
data "aws_iam_policy_document" "annie_readonly_bucket_scoped" {
source_policy_documents = [data.aws_iam_policy_document.annie_readonly.json]
override_policy_documents = [data.aws_iam_policy_document.annie_s3_scoped_override.json]
}
```
The `override_policy_documents` argument replaces the original `AllowS3Metadata` statement (matched by `sid`) and appends the new `AllowS3IntrospectionScoped` statement.
**Tradeoff:** buckets not listed in `AllowS3IntrospectionScoped` appear in the Annie graph as bare entries (name + region) without encryption or notification attributes. S3 access points and multi-region access points are not bucket-scopable in IAM and are not introspected in this variant.
If you store Terraform state in S3 and want Annie to ingest it (drift detection, IaC-to-live mapping), grant the same role/user `s3:GetObject` and `s3:ListBucket` on your tfstate bucket(s) in addition to the policy above. Scope tightly to the buckets that hold state: Annie reads only the keys you tell it to ingest, and only those grants are needed.
```hcl theme={null}
data "aws_iam_policy_document" "annie_tfstate_read" {
statement {
sid = "AllowTfstateBucketList"
effect = "Allow"
actions = ["s3:ListBucket"]
resources = [
"arn:aws:s3:::your-tfstate-bucket",
]
}
statement {
sid = "AllowTfstateObjectRead"
effect = "Allow"
actions = ["s3:GetObject"]
resources = [
"arn:aws:s3:::your-tfstate-bucket/*",
]
}
}
resource "aws_iam_policy" "annie_tfstate_read" {
name = "annie-tfstate-read"
policy = data.aws_iam_policy_document.annie_tfstate_read.json
}
```
Attach `aws_iam_policy.annie_tfstate_read.arn` to the same role or user using the same `aws_iam_role_policy_attachment` / `aws_iam_user_policy_attachment` pattern shown above. If your state is encrypted with a customer-managed KMS key, also grant `kms:Decrypt` on that key's ARN.
## Try Annie Today
Start building your infrastructure knowledge graph and unlock intelligent infrastructure management.
Create your Anyshift account
See Annie's knowledge graph in action
# CloudTrail Integration
Source: https://docs.anyshift.io/pages/integration/aws/cloudtrail
Forward AWS CloudTrail logs to Annie to enrich your infrastructure knowledge graph with API activity and changes.
## Prerequisites
* AWS account with CloudTrail enabled and logs stored in S3
* Terraform 1.0+ (or OpenTofu)
* Anyshift API token (generate one from the [AWS integration page](https://app.anyshift.io/integrations/aws))
## How It Works
The Anyshift Forwarder is a Lambda function that:
1. Triggers automatically when new CloudTrail logs are written to S3
2. Parses and processes the CloudTrail events
3. Forwards the events to Anyshift for analysis and visualization
## Installation
### Step 1: Store Your API Token
Create a secret in AWS Secrets Manager to store your Anyshift API token:
```bash theme={null}
aws secretsmanager create-secret \
--name anyshift-forwarder-token \
--secret-string "YOUR_API_TOKEN" \
--region us-east-1
```
Replace `YOUR_API_TOKEN` with your token from the [AWS integration page](https://app.anyshift.io/integrations/aws).
### Step 2: Clone the Terraform Module
```bash theme={null}
git clone https://github.com/anyshift-io/anyshift-forwarder.git
cd anyshift-forwarder
```
### Step 3: Configure Variables
Create a `terraform.tfvars` file:
```hcl theme={null}
aws_account_id = "YOUR_AWS_ACCOUNT_ID"
aws_region = "us-east-1"
cloudtrail_bucket_arn = "arn:aws:s3:::YOUR_CLOUDTRAIL_BUCKET"
anyshift_token_secret_arn = "arn:aws:secretsmanager:us-east-1:YOUR_ACCOUNT:secret:anyshift-forwarder-token-XXXXXX"
# Use the pre-built Lambda layer for your region (check releases for latest version)
lambda_layer_arn = "arn:aws:lambda:us-east-1:211125758836:layer:anyshift-forwarder:3"
# Optional: If your CloudTrail bucket uses KMS encryption
# kms_key_arn = "arn:aws:kms:us-east-1:YOUR_ACCOUNT:key/YOUR_KEY_ID"
```
### Step 4: Deploy
```bash theme={null}
terraform init
terraform apply
```
## Configuration Options
| Variable | Description | Required |
| --------------------------- | ----------------------------------------------------------- | -------- |
| `aws_account_id` | Your AWS account ID | Yes |
| `aws_region` | AWS region for deployment | Yes |
| `cloudtrail_bucket_arn` | ARN of your CloudTrail S3 bucket | Yes |
| `anyshift_token_secret_arn` | ARN of the Secrets Manager secret containing your API token | Yes |
| `lambda_layer_arn` | ARN of the pre-built Lambda layer for your region | Yes |
| `kms_key_arn` | KMS key ARN if your bucket uses SSE-KMS encryption | No |
## Lambda Layer ARN
Use the following ARN format, replacing `{REGION}` with your AWS region:
```
arn:aws:lambda:{REGION}:211125758836:layer:anyshift-forwarder:3
```
Check the [releases page](https://github.com/anyshift-io/anyshift-forwarder/releases) for the latest version.
Supported regions: `us-east-1`, `us-east-2`, `us-west-1`, `us-west-2`, `eu-west-1`, `eu-west-2`, `eu-west-3`, `eu-central-1`, `eu-north-1`, `ap-northeast-1`, `ap-northeast-2`, `ap-southeast-1`, `ap-southeast-2`, `ap-south-1`, `sa-east-1`, `ca-central-1`
## Validate Installation
Check that the Lambda function is deployed:
```bash theme={null}
aws lambda get-function --function-name anyshift-forwarder --region us-east-1
```
View Lambda logs:
```bash theme={null}
aws logs tail /aws/lambda/anyshift-forwarder --follow --region us-east-1
```
## Permissions
The Lambda function requires the following permissions:
* **S3**: Read access to your CloudTrail bucket
* **Secrets Manager**: Read access to the API token secret
* **KMS**: Decrypt permission (only if using KMS-encrypted bucket)
* **CloudWatch Logs**: Write access for logging
All permissions are automatically configured by the Terraform module.
## Upgrade
To upgrade to the latest version:
```bash theme={null}
cd anyshift-forwarder
git pull origin main
terraform apply
```
When using Lambda layers, simply update the `lambda_layer_arn` to the latest version from the [releases page](https://github.com/anyshift-io/anyshift-forwarder/releases).
## Uninstall
```bash theme={null}
terraform destroy
```
## Source Code
The Anyshift Forwarder is open source. View the source code, report issues, or contribute:
View source code and releases
# Azure Integration
Source: https://docs.anyshift.io/pages/integration/azure
Integrate Annie with Microsoft Azure to unlock infrastructure mapping, monitoring, and dependency insights.
Connect your Microsoft Azure subscription to Annie for real-time infrastructure mapping, monitoring, and dependency insights, using Azure-native service principal authentication.
**Security first**: every role below grants read-only access to your infrastructure. Anyshift cannot access secrets, passwords, API keys, or any other sensitive data stored in your Azure subscription.
# Setup Guide
The recommended path uses a service principal with the built-in `Reader` role assigned at the Management Group level, giving Anyshift visibility into every subscription you want to track.
See the [Microsoft Entra ID documentation](https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app) for app registration details.
```hcl theme={null}
# Create the Azure AD Application
resource "azuread_application" "anyshift" {
display_name = "anyshift-readonly"
}
# Create the Service Principal
resource "azuread_service_principal" "anyshift" {
client_id = azuread_application.anyshift.client_id
}
# Create a client secret
resource "azuread_application_password" "anyshift" {
application_id = azuread_application.anyshift.id
display_name = "anyshift-secret"
end_date = "2030-01-01T00:00:00Z"
}
# Assign Reader role at Management Group level
resource "azurerm_role_assignment" "anyshift_reader" {
scope = "/providers/Microsoft.Management/managementGroups/${var.management_group_id}"
role_definition_name = "Reader"
principal_id = azuread_service_principal.anyshift.object_id
}
# Output the credentials (store securely!)
output "tenant_id" {
value = data.azurerm_client_config.current.tenant_id
}
output "client_id" {
value = azuread_application.anyshift.client_id
sensitive = true
}
output "client_secret" {
value = azuread_application_password.anyshift.value
sensitive = true
}
```
1. Go to **Microsoft Entra ID** (formerly Azure Active Directory)
2. Navigate to **App registrations** → **New registration**
3. Enter the following:
* **Name**: `anyshift-readonly`
* **Supported account types**: "Accounts in this organizational directory only"
* Click **Register**
4. Note the **Application (client) ID** and **Directory (tenant) ID** from the Overview page
5. Go to **Certificates & secrets** → **Client secrets** → **New client secret**
* **Description**: `anyshift-secret`
* **Expires**: Choose your preferred duration (recommended: 24 months)
* Click **Add** and **copy the secret value immediately** (it won't be shown again)
**Recommended**: assign Reader at the **Management Group** level to cover all subscriptions you want to track.
1. Go to **Management groups** → select the management group containing all subscriptions you want to track
2. Navigate to **Access control (IAM)** → **Add** → **Add role assignment**
3. Select the **Reader** role → **Next**
4. Select **User, group, or service principal** → **Select members**
5. Search for `anyshift-readonly` and select it
6. Click **Review + assign**
```bash theme={null}
# List management groups
az account management-group list --query "[].{Name:name, DisplayName:displayName}"
# Assign Reader role at the management group level
az role assignment create \
--assignee \
--role "Reader" \
--scope "/providers/Microsoft.Management/managementGroups/"
```
```bash theme={null}
# If you prefer to limit access to a single subscription
az role assignment create \
--assignee \
--role "Reader" \
--scope "/subscriptions/"
```
1. Go to **Integrations** → **Azure** → **Credentials** → **New Credential**
2. Enter your credentials:
* **Tenant ID**: Your Azure AD tenant ID (Directory ID)
* **Client ID**: The Application (client) ID from Step 1
* **Client Secret**: The secret value from Step 1
3. Click **Save**
Anyshift automatically discovers all subscriptions accessible by the service principal and begins scanning your Azure infrastructure.
# Reference
The recommended setup assigns the built-in `Reader` role at the **Management Group** level containing all subscriptions you want to track, giving Anyshift complete infrastructure visibility. Scanned resources include:
* Compute (Virtual Machines, VM Scale Sets, Disks, Availability Sets)
* Network (VNets, Subnets, NICs, NSGs, Load Balancers, Private DNS Zones)
* Storage (Storage Accounts, Blob Containers, File Shares, Queues, Tables)
* Containers (AKS Clusters, Agent Pools, Container Registries)
* Identity (Managed Identities, Role Assignments, Role Definitions)
* Key Vault metadata
* Log Analytics Workspaces
* Resource Groups and Subscriptions
For more granular control, create a custom role with the read-only actions Anyshift uses:
| Service | Actions | What We Scan |
| ------------------ | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| Compute | `Microsoft.Compute/*/read` | VMs, VM Scale Sets, Disks, Disk Encryption Sets |
| Network | `Microsoft.Network/*/read` | VNets, Subnets, NICs, NSGs, Public IPs, Load Balancers, Private DNS Zones, Application Gateways, Firewalls, VPN Gateways |
| Storage | `Microsoft.Storage/*/read` | Storage Accounts, Blob Containers, File Shares, Queues, Tables |
| Containers | `Microsoft.ContainerService/*/read` | AKS Clusters, Agent Pools |
| Container Registry | `Microsoft.ContainerRegistry/*/read` | Container Registries |
| Key Vault | `Microsoft.KeyVault/*/read` | Key Vaults, Keys, Secrets metadata (not values) |
| Managed Identity | `Microsoft.ManagedIdentity/*/read` | User-Assigned Managed Identities |
| Log Analytics | `Microsoft.OperationalInsights/*/read` | Log Analytics Workspaces |
| Authorization | `Microsoft.Authorization/*/read` | Role Assignments, Role Definitions |
| Resources | `Microsoft.Resources/*/read` | Resource Groups, Subscriptions |
| App Service | `Microsoft.Web/*/read` | Web Apps, Function Apps, App Service Plans |
| SQL | `Microsoft.Sql/*/read` | SQL Servers, Databases, Elastic Pools |
| Cosmos DB | `Microsoft.DocumentDB/*/read` | Cosmos DB Accounts, Databases |
| Redis Cache | `Microsoft.Cache/*/read` | Redis Cache instances |
| Service Bus | `Microsoft.ServiceBus/*/read` | Service Bus Namespaces, Queues, Topics |
| Event Hubs | `Microsoft.EventHub/*/read` | Event Hub Namespaces, Event Hubs |
| API Management | `Microsoft.ApiManagement/*/read` | API Management Services, APIs |
| Monitor | `Microsoft.Insights/*/read` | Alerts, Metrics, Diagnostic Settings |
All permissions Anyshift uses for comprehensive infrastructure scanning:
### Compute Resources
* `Microsoft.Compute/virtualMachines/read`
* `Microsoft.Compute/virtualMachineScaleSets/read`
* `Microsoft.Compute/disks/read`
* `Microsoft.Compute/diskEncryptionSets/read`
* `Microsoft.Compute/availabilitySets/read`
### Network Resources
* `Microsoft.Network/virtualNetworks/read`
* `Microsoft.Network/networkInterfaces/read`
* `Microsoft.Network/networkSecurityGroups/read`
* `Microsoft.Network/publicIPAddresses/read`
* `Microsoft.Network/loadBalancers/read`
* `Microsoft.Network/privateDnsZones/read`
* `Microsoft.Network/applicationGateways/read`
* `Microsoft.Network/azureFirewalls/read`
* `Microsoft.Network/virtualNetworkGateways/read`
* `Microsoft.Network/dnszones/read`
### Storage Resources
* `Microsoft.Storage/storageAccounts/read`
* `Microsoft.Storage/storageAccounts/blobServices/read`
* `Microsoft.Storage/storageAccounts/blobServices/containers/read`
* `Microsoft.Storage/storageAccounts/fileServices/read`
* `Microsoft.Storage/storageAccounts/fileServices/shares/read`
* `Microsoft.Storage/storageAccounts/queueServices/read`
* `Microsoft.Storage/storageAccounts/tableServices/read`
### Container Resources
* `Microsoft.ContainerService/managedClusters/read`
* `Microsoft.ContainerService/managedClusters/agentPools/read`
* `Microsoft.ContainerRegistry/registries/read`
### Identity & Authorization
* `Microsoft.ManagedIdentity/userAssignedIdentities/read`
* `Microsoft.Authorization/roleAssignments/read`
* `Microsoft.Authorization/roleDefinitions/read`
### App Service & Serverless
* `Microsoft.Web/sites/read`
* `Microsoft.Web/serverfarms/read`
* `Microsoft.Web/sites/functions/read`
### Databases
* `Microsoft.Sql/servers/read`
* `Microsoft.Sql/servers/databases/read`
* `Microsoft.Sql/servers/elasticPools/read`
* `Microsoft.DocumentDB/databaseAccounts/read`
* `Microsoft.Cache/redis/read`
### Messaging & Events
* `Microsoft.ServiceBus/namespaces/read`
* `Microsoft.ServiceBus/namespaces/queues/read`
* `Microsoft.ServiceBus/namespaces/topics/read`
* `Microsoft.EventHub/namespaces/read`
* `Microsoft.EventHub/namespaces/eventhubs/read`
### Other Resources
* `Microsoft.KeyVault/vaults/read`
* `Microsoft.OperationalInsights/workspaces/read`
* `Microsoft.ApiManagement/service/read`
* `Microsoft.Insights/alertRules/read`
* `Microsoft.Insights/diagnosticSettings/read`
* `Microsoft.Resources/subscriptions/read`
* `Microsoft.Resources/subscriptions/resourceGroups/read`
Workload Identity Federation lets Anyshift authenticate to Azure without a client secret. Anyshift signs a short-lived JWT token that Azure trusts via a federated identity credential. This removes secret rotation and is more secure.
## Step 1 - Register an Application in Microsoft Entra ID
Follow the same steps as the service principal setup to create an App Registration and assign the Reader role, but **skip creating a client secret**.
**Terraform**
```hcl theme={null}
# Create the Azure AD Application
resource "azuread_application" "anyshift" {
display_name = "anyshift-readonly"
}
# Create the Service Principal
resource "azuread_service_principal" "anyshift" {
client_id = azuread_application.anyshift.client_id
}
# Assign Reader role at Management Group level
resource "azurerm_role_assignment" "anyshift_reader" {
scope = "/providers/Microsoft.Management/managementGroups/${var.management_group_id}"
role_definition_name = "Reader"
principal_id = azuread_service_principal.anyshift.object_id
}
```
**Azure Portal**
1. Go to **Microsoft Entra ID** → **App registrations** → **New registration**
2. Enter:
* **Name**: `anyshift-readonly`
* **Supported account types**: "Accounts in this organizational directory only"
* Click **Register**
3. Note the **Application (client) ID** and **Directory (tenant) ID**
4. Assign the **Reader** role as described in the service principal setup, Step 2
## Step 2 - Add Credentials in Anyshift
1. Go to **Integrations** → **Azure** → **Credentials** → **New Credential**
2. Select **OIDC** as the authentication method
3. Enter:
* **Tenant ID**: Your Azure AD tenant ID
* **Client ID**: The Application (client) ID from Step 1
4. Click **Save**
Anyshift displays a dialog with three values you need for the next step:
* **Issuer URL**: The Anyshift OIDC issuer (e.g. `https://api.anyshift.io`)
* **Subject Identifier**: A unique identifier for this credential (e.g. `anyshift:project::credential:`)
* **Audience**: `api://AzureADTokenExchange`
Copy these values using the copy buttons in the dialog.
## Step 3 - Configure Federated Identity Credential in Azure
Using the values from the Anyshift dialog:
**Terraform**
```hcl theme={null}
resource "azuread_application_federated_identity_credential" "anyshift" {
application_id = azuread_application.anyshift.id
display_name = "anyshift-oidc"
issuer = "" # From the dialog
subject = "" # From the dialog
audiences = ["api://AzureADTokenExchange"]
}
```
**Azure Portal**
1. Go to **Azure Portal** → **App Registrations** → your app → **Certificates & secrets** → **Federated credentials**
2. Click **Add credential** and select **Other issuer**
3. Paste the **Issuer URL**, **Subject Identifier**, and **Audience** values from the Anyshift dialog
4. Click **Add**
## Step 4 - Verify the Connection
Click **Done & Verify Connection** in the Anyshift dialog. Anyshift triggers a scan to verify the federation is working correctly.
**Status shows "Error" after adding credentials**
This usually means the service principal lacks the required permissions. Verify that:
1. The Reader role is assigned at the subscription level
2. The credentials (Tenant ID, Client ID, Client Secret) are correct
3. The client secret hasn't expired (for service principal auth)
**Status shows "Error" with OIDC federation**
1. Verify the federated identity credential is configured correctly in Azure AD (Issuer URL, Subject Identifier, Audience)
2. Ensure the Issuer URL matches exactly (no trailing slash)
3. Check that the App Registration has the Reader role assigned
**No resources showing up**
1. Ensure the service principal has access to the correct subscription
2. Check that resources exist in the subscription
3. Allow a few minutes for the initial scan to complete
**Multiple subscriptions**
Anyshift automatically discovers and scans all subscriptions accessible by the service principal. Assign Reader at the **Management Group level** to cover all subscriptions you want to track, with no need for separate credentials per subscription.
# Try Anyshift
Start mapping your Azure infrastructure today.
See Anyshift Root Cause Analysis in action
# Read-Only Agentic Live Queries
Source: https://docs.anyshift.io/pages/integration/cloud_cli
Annie can query your live cloud infrastructure using native CLI tools to verify state, diagnose issues, and enumerate resources in real time.
# Overview
Annie can execute **read-only cloud CLI commands** against your live infrastructure during investigations and chat sessions. This complements the [knowledge graph](/pages/overview/knowledge_graph): the graph maps relationships and topology, while live queries verify **live state** in real time.
## Setup
Live queries are enabled **per credential** from the credential list in your cloud integration settings. For each connected AWS role, AWS IAM user, GCP service account, or Azure credential, a toggle controls whether Annie can run live queries with it.
Connect via the existing integrations: [AWS](/pages/integration/aws) (IAM Assume Role or IAM User), [GCP](/pages/integration/gcp) (Service Account), or [Azure](/pages/integration/azure) (Service Principal or Workload Identity Federation).
Go to [Integrations](https://app.anyshift.io/integrations) and select the cloud provider (AWS, GCP, or Azure).
On the credentials list page, toggle **"Read-Only Agentic Live Queries"** for each credential you want to enable. This grants Annie permission to run allowlisted CLI commands using that specific credential.
Annie uses the enabled credentials for live query operations during investigations and chat sessions. No restart or configuration reload needed.
You can enable live queries on some credentials and not others. For example, enable it on your production AWS role for incident investigation but leave it off on staging credentials.
## Security
Every CLI command Annie can execute is **explicitly allowlisted**. If a command is not on the allowlist, it is rejected.
* **Strict allowlisting**: Only explicitly reviewed and approved commands can run. Unknown commands are blocked by default.
* **Read-only operations only**: The allowlist includes only `describe`, `list`, `get`, and `show` commands. No `create`, `update`, `delete`, or `terminate` operations are permitted.
* **Pagination limits**: Commands returning large datasets enforce pagination via `--max-items` or `--top` to prevent runaway queries and excessive costs.
* **Restricted utility flags**: Tools like `curl` and `dig` have a strict subset of allowed flags. For example, `curl` can only access HTTPS URLs and cannot send custom headers.
Annie **cannot** modify your infrastructure through CLI commands. All access is strictly read-only. If a command isn't on the allowlist, it's rejected with a clear error and Annie falls back to the knowledge graph.
## Reference
Every command goes through multiple validation checks before execution:
| Validation | What It Checks | Example |
| -------------- | --------------------------------------------- | ------------------------------------------------------------- |
| **Binary** | The tool must have a registered validator | `rm`, `chmod`, `wget` → rejected |
| **Command** | The specific subcommand must be allowlisted | `aws ec2 terminate-instances` → rejected |
| **Flags** | Every flag must be explicitly permitted | `curl -H "Authorization: ..."` → rejected |
| **URLs** | Must be HTTPS, no internal/metadata endpoints | `curl http://169.254.169.254/` → rejected |
| **Pagination** | Large-output commands must include limits | `aws ec2 describe-instances` without `--max-items` → enforced |
Annie uses the cloud credentials you've already configured in Anyshift, only those with **"Read-Only Agentic Live Queries"** enabled. The same credentials used for infrastructure graph ingestion are reused for live queries.
* **Credential selection**: When Annie runs a CLI command, she selects the appropriate credential set for the target account. With multiple enabled accounts (e.g., `prod-aws`, `staging-gcp`, `azure-prod`), she picks the one relevant to the investigation.
* **Secure injection**: Credentials are injected **server-side** into the command execution environment. They are never exposed to the AI model, never logged, and never included in responses.
| Cloud Provider | Credential Type | What's Used |
| -------------- | ----------------------------------- | ----------------------------------------------------------------- |
| **AWS** | IAM Assume Role / IAM User | Temporary STS credentials (access key, secret key, session token) |
| **GCP** | Service Account | Short-lived access token + project ID |
| **Azure** | Service Principal | Per-execution `az login` with client secret via stdin |
| **Azure** | Workload Identity Federation (OIDC) | Per-execution `az login` with JWT federated token |
Annie uses cloud CLI commands when she needs information beyond what the knowledge graph snapshot provides.
* **Live state verification**: During an RCA, Annie found EC2 instance `i-0abc123` in the graph but runs `aws ec2 describe-instance-status` to confirm it's still running and healthy, catching stale snapshots or recent changes.
* **Resource enumeration**: For *"How many Lambda functions do we have in production?"*, Annie runs `aws lambda list-functions` for an accurate real-time count. CLI is often more direct than a graph query for counts and listings.
* **Operational diagnostics**: Seeing connection timeouts in logs, Annie uses `dig` and `curl` to verify DNS resolution and endpoint reachability, useful when logs reference external dependencies or network issues.
* **Configuration verification**: Investigating a flagged security group change, Annie runs `aws ec2 describe-security-groups` to compare current rules against what the graph recorded.
* **Load balancer health**: On 5xx alerts from an ALB, Annie checks `aws elbv2 describe-target-health` for unhealthy targets and correlates with ECS task status via `aws ecs describe-tasks`, then traces the issue using the graph's dependency map.
* **Azure metrics & monitoring**: For a high-CPU Azure VM, Annie runs `az monitor metrics list` for latest values and `az monitor metrics alert list` to check firing alert rules.
* **Azure Container App logs**: Investigating errors in an Azure Container App, Annie pulls recent console output with `az containerapp logs show --tail` and, when logs are forwarded to Log Analytics, queries them historically with `az monitor log-analytics query`.
**Compute**
| Service | Commands |
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **EC2** | `describe-instances`, `describe-instance-status`, `describe-images`, `describe-volumes`, `describe-snapshots` |
| **ECS** | `list-clusters`, `describe-clusters`, `list-services`, `describe-services`, `list-tasks`, `describe-tasks`, `describe-task-definition` |
| **EKS** | `list-clusters`, `describe-cluster`, `list-nodegroups`, `describe-nodegroup`, `list-addons`, `describe-addon-versions` |
| **Lambda** | `list-functions`, `get-function`, `get-policy`, `list-event-source-mappings`, `get-function-concurrency`, `get-function-url-config`, `get-function-code-signing-config`, `list-provisioned-concurrency-configs` |
**Networking**
| Service | Commands |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **EC2 (VPC)** | `describe-vpcs`, `describe-subnets`, `describe-security-groups`, `describe-route-tables`, `describe-nat-gateways`, `describe-internet-gateways`, `describe-network-interfaces` |
| **ELBv2** | `describe-load-balancers`, `describe-listeners`, `describe-target-groups`, `describe-target-health` |
| **CloudFront** | `list-distributions`, `get-distribution` |
| **API Gateway** | `get-integration`, `get-stage` |
**Storage & Databases**
| Service | Commands |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **S3** | `ls` |
| **S3 API** | `list-buckets`, `get-bucket-encryption`, `get-bucket-lifecycle-configuration`, `get-bucket-policy`, `get-bucket-replication`, `get-bucket-versioning`, `get-public-access-block` |
| **RDS** | `describe-db-instances`, `describe-db-clusters`, `describe-db-log-files` |
| **DynamoDB** | `describe-table`, `describe-continuous-backups`, `describe-time-to-live` |
| **ElastiCache** | `describe-cache-clusters`, `describe-replication-groups` |
**Identity & Security**
| Service | Commands |
| ------- | --------------------------------------------------------------------------------------------------------------------------- |
| **IAM** | `list-roles`, `list-users`, `list-policies`, `list-attached-role-policies`, `get-role`, `get-policy`, `get-account-summary` |
| **STS** | `get-caller-identity`, `get-access-key-info` |
**Monitoring & Events**
| Service | Commands |
| ------------------- | -------------------------------------------------------------------- |
| **CloudWatch** | `describe-alarms`, `describe-alarm-history`, `get-metric-statistics` |
| **CloudWatch Logs** | `describe-log-groups`, `describe-log-streams`, `filter-log-events` |
| **EventBridge** | `list-rules`, `describe-rule`, `list-targets-by-rule` |
**Compute & Containers**
| Service | Commands |
| ----------------------- | -------------------------------------------- |
| **Compute Instances** | `list`, `describe`, `get-serial-port-output` |
| **Compute Disks** | `list`, `describe` |
| **Instance Groups** | `list`, `managed describe` |
| **GKE Clusters** | `list`, `describe` |
| **GKE Node Pools** | `list` |
| **Cloud Run Services** | `list`, `describe` |
| **Cloud Run Revisions** | `list` |
**Networking**
| Service | Commands |
| -------------------- | --------------------------------------- |
| **Networks** | `list`, `peerings list`, `subnets list` |
| **Firewall Rules** | `list` |
| **Forwarding Rules** | `list` |
| **Routes** | `list` |
| **Addresses** | `list` |
| **Backend Services** | `list`, `get-health` |
**Databases**
| Service | Commands |
| ----------------------- | ------------------------------------------------------------------------------------------- |
| **Cloud SQL** | `instances list`, `instances describe`, `databases list`, `backups list`, `operations list` |
| **Spanner** | `instances list`, `instances describe`, `databases list`, `operations list` |
| **Memorystore (Redis)** | `instances list`, `instances describe` |
**Storage & Data**
| Service | Commands |
| ----------------- | ------------------------------------------------------------- |
| **Cloud Storage** | `buckets list`, `buckets describe` |
| **Pub/Sub** | `topics list`, `subscriptions list`, `subscriptions describe` |
| **Dataproc** | `clusters list`, `clusters describe`, `jobs list` |
**Identity & Projects**
| Service | Commands |
| ------------------------ | ------------------------------------ |
| **Projects** | `list`, `describe`, `get-iam-policy` |
| **IAM Service Accounts** | `list`, `describe`, `keys list` |
**Monitoring & Logging**
| Service | Commands |
| -------------- | ---------------------------------- |
| **Monitoring** | `dashboards list`, `policies list` |
| **Logging** | `read` |
**Monitoring & Diagnostics**
| Service | Commands |
| ----------------------- | --------------------------------------------- |
| **Monitor Metrics** | `list`, `list-definitions`, `list-namespaces` |
| **Monitor Alerts** | `alert list`, `alert show` |
| **Activity Log** | `list` |
| **Log Analytics** | `workspace list`, `query` |
| **Diagnostic Settings** | `list` |
**Compute**
| Service | Commands |
| -------------------- | --------------------------------------------------- |
| **Virtual Machines** | `list`, `show` |
| **AKS** | `list`, `show`, `nodepool list` |
| **Container Apps** | `list`, `show`, `logs show`, `env list`, `env show` |
**Networking**
| Service | Commands |
| --------------------------- | --------------------------- |
| **Virtual Networks** | `vnet list` |
| **Network Security Groups** | `nsg list`, `nsg rule list` |
| **Public IPs** | `public-ip list` |
**Storage & Databases**
| Service | Commands |
| -------------------- | ---------------------------- |
| **Storage Accounts** | `account list` |
| **SQL Server** | `server list`, `server show` |
| **SQL Databases** | `db list` |
| **Cosmos DB** | `list` |
**Resource Discovery**
| Service | Commands |
| ------------------- | -------------- |
| **Account** | `show`, `list` |
| **Resource Groups** | `list` |
| **Resources** | `list`, `show` |
Azure supports both **Service Principal** (client secret) and **Workload Identity Federation** (OIDC) authentication. Both work with live queries. See the [Azure integration guide](/pages/integration/azure) for setup.
Alongside cloud CLIs, Annie has access to utility tools for diagnostics and data processing:
| Tool | Purpose | Example Use Case |
| ----------- | ---------------------------------------------------- | ----------------------------------------------------------------------- |
| **curl** | HTTP endpoint checks (HTTPS only, no custom headers) | Check if an API endpoint is reachable and responding |
| **dig** | DNS lookups and diagnostics | Verify DNS resolution for a service endpoint during connectivity issues |
| **jq** | JSON processing and filtering | Parse and filter complex CLI output |
| **yq** | YAML processing | Parse Kubernetes manifests or configuration files |
| **base64** | Encode/decode data | Decode base64-encoded configuration values |
| **date** | Date/time operations | Convert timestamps between formats during log analysis |
| **openssl** | Certificate inspection | Check TLS certificate expiry and chain validity |
## Get Started
Sign up for Anyshift and connect your cloud accounts
See Annie's live query capabilities in action
# Cloudflare Integration
Source: https://docs.anyshift.io/pages/integration/cloudflare
Connect Cloudflare so Annie can inventory DNS, zones, certificates, WAF, load balancers, Workers, tunnels, and Access via OAuth/OIDC or an API token.
Connect your Cloudflare account to Annie to inventory DNS records, zones, certificates, WAF, load balancers, Workers, tunnels, Access, and other edge configuration. Annie uses this data during investigations to map hostnames to infrastructure and surface edge-related changes.
The Cloudflare integration is currently in **beta**. Inventory coverage and
supported product surfaces may expand as we harden the connector.
**Security first**: Anyshift only requests read-only access. Prefer **Connect with Cloudflare** (OAuth / OIDC). An Account API token is available as a fallback. Do not grant Edit or Write permissions.
# Setup Guide
You can connect Cloudflare in either of two ways. OAuth / OIDC is recommended.
Go to [Integrations → Cloudflare](https://app.anyshift.io/integrations/cloudflare/credentials) in Anyshift to start.
## Connect with Cloudflare (OAuth / OIDC)
Use OAuth when you want a one-click authorize flow without pasting a long-lived API token.
1. Open **Integrations → Cloudflare**.
2. Click **Connect with Cloudflare**.
3. Sign in to Cloudflare if prompted, pick the account to authorize, and approve the read-only scopes Anyshift requests.
4. You return to Anyshift. The page shows the connected Cloudflare account.
Anyshift stores the OAuth tokens encrypted and refreshes them automatically. If the connection status shows that re-authorization is required, click **Reconnect** and approve again.
### OAuth scopes (recommended full read set)
Anyshift requests these read-only scopes for full inventory. Approving a subset (or using a zone-scoped grant) still works; missing scopes soft-fail and those inventory families may be incomplete.
| Scope ID | Purpose |
| ---------------------------------------- | --------------------------------------------- |
| `account-settings.read` | Account metadata |
| `zone.read` | Zone inventory |
| `zone-settings.read` | Zone settings (including SSL mode) |
| `dns.read` | DNS records for hostname mapping |
| `ssl-and-certificates.read` | Certificate packs, custom hostnames |
| `account-ssl-and-certificates.read` | Origin CA certificates |
| `zone-waf.read` | Zone WAF / ruleset phases |
| `firewall-services.read` | Zone firewall surfaces |
| `account-rulesets.read` | Account rulesets |
| `load-balancing-monitors-and-pools.read` | Pools, origins, monitors |
| `load-balancers.read` | Zone load balancers |
| `workers-scripts.read` | Workers scripts |
| `workers-routes.read` | Worker routes |
| `argotunnel.read` | Cloudflare Tunnels |
| `access.read` | Access applications and policies |
| `offline_access` | Refresh tokens so the connection stays active |
## Connect with an API token
Use an Account API token when OAuth is unavailable in your workspace, or when you prefer a manually created token.
1. In the [Cloudflare dashboard](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/), create an **Account API token** with the recommended Read permissions below.
2. In Anyshift, open **Integrations → Cloudflare**.
3. Click **New credential** (or **Add API token credentials** if OAuth is also enabled).
4. Enter:
* **Name**: a label for this connection (for example `Production Cloudflare`)
* **Account ID**: from the Cloudflare dashboard overview for that account
* **API token**: the token value (stored encrypted; not shown again after save)
5. Click **Save**.
### API token permissions (recommended full read set)
Grant these read-only permissions (equivalent to the OAuth scopes above) for full inventory. A subset or zone-scoped token is allowed; missing permissions soft-fail and inventory for those families may be incomplete.
| Permission | Scope |
| --------------------------------------- | ------- |
| Account Settings Read | Account |
| Zone Read | Zone |
| Zone Settings Read | Zone |
| DNS Read | Zone |
| SSL and Certificates Read | Zone |
| Account: SSL and Certificates Read | Account |
| Zone WAF Read | Zone |
| Firewall Services Read | Zone |
| Account Rulesets Read | Account |
| Load Balancing: Monitors and Pools Read | Account |
| Load Balancers Read | Zone |
| Workers Scripts Read | Account |
| Workers Routes Read | Zone |
| Cloudflare Tunnel Read | Account |
| Access: Apps and Policies Read | Account |
**Optional** (omit family when missing; not treated as a partial failure): Account Logs Read; Memberships Read (user tokens).
Do not grant Edit or Write.
# What Annie uses this for
Once connected, Annie can:
* List zones and DNS records for hostname-to-resource mapping
* Read zone settings that affect edge behavior (for example SSL mode)
* Inventory certificates, WAF/firewall rulesets, load balancers, Workers, tunnels, and Access when those Read permissions are present
* Correlate Cloudflare configuration with your broader infrastructure graph during investigations
* Trace public exposure paths for Cloudflare hostnames, including optional [origin reachability](/pages/product/graph-api/origin-reachability) on ALB and NLB origins
# Troubleshooting
**OAuth connect fails or returns to Anyshift with an error**
1. Confirm you approved the requested scopes in the Cloudflare consent screen.
2. Try **Disconnect**, then **Connect with Cloudflare** again.
3. If your Cloudflare user cannot authorize the account, ask an account admin to complete the connect flow.
**API token credential shows Error**
1. Confirm the Account ID matches the account the token was created for.
2. Confirm the token includes at least the core Read permissions you expect (Account Settings, Zone, Zone Settings, DNS).
3. Confirm the token is not expired or revoked in the Cloudflare dashboard.
**Incomplete inventory after connect**
Allow a few minutes for the initial inventory scan. If some families are missing, confirm the authorized account (or token) includes the matching Read permissions. Subset and zone-scoped grants are supported; denied families soft-fail rather than failing the whole extract.
# Try Anyshift
See Anyshift Root Cause Analysis in action
# Confluence Integration
Source: https://docs.anyshift.io/pages/integration/confluence
Connect your Confluence instance to enable Annie to search pages, access documentation, and leverage knowledge base content during incident investigation.
# Confluence Integration
Confluence integration enables Annie to access your knowledge base, allowing it to search pages, retrieve documentation, and correlate incidents with existing runbooks, procedures, and historical knowledge.
## Setup Guide
The recommended way to connect is **Connect with Atlassian** (OAuth). One authorization covers both Confluence and [Jira](/pages/integration/jira). You can still use an email + API token as a fallback.
### Option A: Connect with Atlassian (recommended)
1. Go to the [Anyshift integrations page](https://app.anyshift.io/integrations)
2. Navigate to the Knowledge Base section
3. Select **Confluence**
4. Click **Connect with Atlassian**
5. Sign in to Atlassian and approve access for your site
6. You return to Anyshift with the connected site shown (for example, your company Atlassian domain)
The same connection also enables Jira. You do not need to authorize twice if you later open the Jira integration page.
To disconnect, use **Disconnect** on the Confluence or Jira integration page. That removes the shared Atlassian OAuth connection for the project.
### Option B: Email + API token (fallback)
Use this if your organization prefers API tokens, or if OAuth is unavailable.
1. Go to the [Anyshift integrations page](https://app.anyshift.io/integrations)
2. Navigate to the Knowledge Base section
3. Select **Confluence**
4. Under the API token section, click **Add**
5. Enter your **Confluence Domain**, **Email**, and **API Token**
6. Click **Save**
#### Confluence Domain
Enter your Atlassian domain (e.g., `yourcompany.atlassian.net`).
This is the same domain you use to access Confluence Cloud. For example, if you access Confluence at `https://acme.atlassian.net/wiki`, enter `acme.atlassian.net`.
#### Email
Enter the email address associated with your Atlassian account (e.g., `user@company.com`).
#### API Token
Anyshift supports both **scoped** and **classic** Atlassian API tokens. Prefer scoped tokens for least-privilege access.
No admin configuration is required. Any Atlassian user can create a token and connect their Confluence instance.
**Scoped API token**
1. Go to [Atlassian API Token Management](https://id.atlassian.com/manage-profile/security/api-tokens)
2. Click **Create API token**
3. Select **Scoped** token type
4. Enter a label (e.g., "Anyshift Confluence Integration")
5. Grant the following permissions:
* All `read:confluence-*` scopes (content, spaces, users, props, etc.)
* `search:confluence` - Search Confluence content (**required**; this is not a `read:*` scope)
* `read:me` - Read your profile information
* `read:account` - Read account information
6. Click **Create**
7. Copy the token and paste it into Anyshift
**Classic API token**
Classic tokens inherit all permissions of the Atlassian account.
1. Go to [Atlassian API Token Management](https://id.atlassian.com/manage-profile/security/api-tokens)
2. Click **Create API token**
3. Select **Classic** token type
4. Enter a label (e.g., "Anyshift Confluence Integration")
5. Click **Create**
6. Copy the token and paste it into Anyshift
For more details, see [Atlassian's API Token documentation](https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/).
Keep your API token secure and do not share it publicly.
## Required Permissions
Annie performs **read-only** operations on your Confluence instance. Access follows the Atlassian account you authorize (OAuth) or the account tied to your API token.
Your account needs access to:
* View spaces
* View pages and their content
* Search content using CQL
Annie does not create, modify, or delete any pages, comments, or other content in your Confluence instance.
## How It Works
Once connected, Annie can leverage your Confluence instance during:
* **Incident Investigation**: When analyzing an incident, Annie searches for related runbooks, troubleshooting guides, and architecture documentation to find relevant context
* **Question Answering**: When you ask about specific topics, Annie retrieves documentation directly from Confluence
* **Correlation**: Annie can correlate alerts and incidents with documented procedures, known issues, and operational playbooks
### Example Use Cases
* "Search Confluence for the deployment runbook"
* "Find documentation about Redis failover procedures"
* "What does the architecture page say about the payment service?"
* "Search for post-incident reviews related to database outages"
Annie will search your Confluence instance using CQL (Confluence Query Language) and cite relevant pages in its responses.
### CQL Query Examples
Annie can construct CQL queries automatically based on your questions:
| Question | CQL Query |
| ------------------ | -------------------------------------------- |
| "Recent pages" | `type = page AND lastModified >= now('-7d')` |
| "Pages in a space" | `space = OPS AND type = page` |
| "Runbooks" | `label = runbook AND type = page` |
| "Deployment docs" | `text ~ "deployment procedure"` |
## Supported Features
Annie can access the following Confluence data:
**Pages**
* Search pages using CQL or text search
* Get full page content (title, body, metadata)
* Navigate page hierarchies (parent/child pages)
* View space page trees
**Page Metadata**
* View comments on pages
* Get labels applied to pages
* Access page version history
* Compare page versions (diffs)
**Attachments**
* List attachments on pages
## Space Scoping
You can optionally restrict which Confluence spaces Annie can access by specifying **Allowed Spaces** when configuring credentials.
Enter a comma-separated list of Confluence space keys (e.g., `ENG,OPS,SRE`). When configured:
* **Searches** are automatically scoped to the specified spaces
* **Direct page access** is restricted — Annie cannot fetch pages from spaces not in the list
* **Space listings** only show the allowed spaces
Leave the field empty to allow access to all spaces the service account can see.
This is useful when a service account has broad access but you want Annie to focus on specific documentation spaces. For stronger isolation, you can also configure space-level permissions on the Atlassian service account itself.
## Security
* OAuth access and refresh tokens, and API tokens, are encrypted at rest using AWS KMS
* Anyshift only reads from your Confluence instance (no write operations)
* All communication uses HTTPS/TLS encryption
* Credentials are validated against Atlassian APIs when you connect
## Troubleshooting
### OAuth connect fails or returns an error
1. **Consent cancelled**: Start again with **Connect with Atlassian** and approve access.
2. **Wrong Atlassian account**: Sign out of Atlassian in the browser, then reconnect with the account that can see your Confluence site.
3. **Connection shows error status**: Disconnect and reconnect with Atlassian so Anyshift can obtain a fresh grant.
### "401 Unauthorized" or "Invalid credentials" error (API token)
This is usually caused by one of the following:
1. **Token missing required scopes** (scoped tokens only): Ensure your scoped token has all `read:confluence-*` scopes, plus `search:confluence` (this is a separate scope, not covered by `read:*`), `read:me`, and `read:account`.
2. **Email/token mismatch**: Verify your email matches your Atlassian account email exactly.
3. **Expired or revoked token**: Generate a new API token from your [Atlassian account settings](https://id.atlassian.com/manage-profile/security/api-tokens).
### "No pages found" when searching
* Verify your account has permission to view the spaces being searched
* Check that the CQL query syntax is valid
* Ensure pages exist matching your search criteria
### Connection timeout
* For API token setup, verify your Confluence domain is correct (e.g., `yourcompany.atlassian.net`)
* Check that your Atlassian instance is accessible
Ready to get started? [Configure Confluence Integration](https://app.anyshift.io/integrations)
# Datadog Integration
Source: https://docs.anyshift.io/pages/integration/datadog
Integrate Annie with Datadog for monitoring and observability.
# Datadog Integration
Datadog integration will enable Annie to ingest monitoring and observability data, providing a unified view of your infrastructure's health and performance.
## Setup Guide
1. Go to the [Anyshift integrations page](https://app.anyshift.io/integrations)
2. Navigate to the Monitoring section
3. Create Datadog API credentials to connect your Datadog account
⚠️ For now, Anyshift support only one set of credentials per Anyshift account. Ping us if it is a blocker for you, we will prioritize it.
### 1. Datadog Site URL
Usually datadoghq.com but it can vary based on your region (e.g., datadoghq.eu for Europe).
### 2. Datadog API key
Create an API key in your Datadog account settings. This key will be used to authenticate requests from Annie to Datadog.
### 3. Datadog Application Key
Create an application key in your Datadog account settings. This key is used to authorize API requests and should be kept secure.
### 4. Required Permissions
Your Datadog Application Key needs specific scopes to work with Anyshift:
**Minimum Required:**
* `read_hosts` - Required for basic connectivity check
**For Full Functionality:**
* `monitors_read` - Access monitor definitions and status
* `logs_read` - Query and retrieve log data
* `dashboards_read` - List and view dashboards
* `metrics_read` - Query metrics data
* `incidents_read` - View incident information
* `apm_read` - Access APM traces and service data
* `timeseries_query` - Query time series metrics
## How It Works
Once connected, Anyshift automatically ingests logs and metrics from Datadog. When an incident occurs, Annie’s AI agent:
* Correlates Datadog logs and metrics with your resource graph
* Traces request chains across services
* Surfaces root causes and actionable insights
* Reduces the need to manually jump between dashboards
# ElasticSearch Integration
Source: https://docs.anyshift.io/pages/integration/elasticsearch
Configure your ElasticSearch connection to enable Annie integration
# ElasticSearch Configuration
Configure your ElasticSearch connection to enable Annie integration.
## Setup ElasticSearch Integration
1. **Deployment Type**: Select your deployment type (e.g., Elastic Cloud (SaaS)).
2. **API Key**: Enter your ElasticSearch API key.
3. **Save Configuration**: Click to save your setup.
## How It Works
Once connected, Anyshift automatically ingests logs and metrics from ElasticSearch. When an incident occurs, Annie’s AI agent:
* Correlates ElasticSearch logs and metrics with your resource graph
* Traces request chains across services
* Surfaces root causes and actionable insights
* Reduces the need to manually jump between dashboards
# GCP Integration
Source: https://docs.anyshift.io/pages/integration/gcp
Connect your Google Cloud project to Annie to unlock real-time infrastructure mapping, monitoring, and dependency insights—exactly the same capabilities as our AWS integration, but using GCP-native security primitives.
**Security First**: All the roles listed below provide read-only access to your infrastructure. Anyshift cannot access secrets, passwords, API keys, or any other sensitive data stored in your GCP project.
## Query retained GCP evidence
After connecting a project, you can inspect the inventory and change evidence collected for it with
the [Annie CLI](/pages/product/integration/cli):
```bash theme={null}
annie graph cloud-resources --provider gcp --type COMPUTE_INSTANCES --max-age 24h
annie graph cloud-events --provider gcp --since 24h
annie graph cloud-events --provider gcp --operation operation-123 --diff
```
Cloud resources report their lifecycle, observation freshness, and stored IaC provenance. Cloud
events distinguish provider audit evidence, snapshot-derived changes, and reconciliation deletes.
A provider operation ID groups GCP-native activity; an Anyshift correlation ID groups the broader
retained event story.
Cloud-event browsing is bounded by default: Annie reports the events shown plus pagination state
without calculating an exact full-window total. Add `--exact-stats` only when you explicitly need
the exact total and event-type breakdown, which can take longer on large projects.
Audit event categories are normalized from the GCP operation: instance insert/delete operations are
`lifecycle`, `compute_instances_set_metadata` is `configuration`, and
`iam_service_accounts_set_iam_policy` is `identity`. Current producers exclude mutations rejected
by GCP because they did not change provider state. Their absence from cloud-event results does not
prove that no rejected calls occurred. A retained legacy row can still report `failed`; an accepted
event without enough outcome evidence remains `unknown`, never inferred as success.
Rejected-call rates can be useful security or automation-health signals, but they are not change
events or causal roots. Any future rejection detector will remain outside event-story correlation.
An empty filtered CLI page is a successful evidence result and says that no matching cloud events
or resources were found. An ambiguous resource is not selected automatically; add provider, scope,
region, type, or the exact native ID and retry.
Coverage depends on enabled APIs, granted read permissions, regions, resource families, and event
retention. Snapshot and reconciliation evidence is not an immediate provider notification. Missing
actor, status, freshness, or provenance evidence remains `unknown`. Anyshift does not turn it into a
success, stale verdict, unmanaged verdict, Terraform drift verdict, or causal claim.
# Required Roles and Permissions
## Setup Options
**Minimal Setup with `roles/viewer`**
Using only the `roles/viewer` role provides basic access but with limitations.
Anyshift will be able to scan core GCP resources like Compute Engine, Cloud SQL, GKE, Logging, Monitoring, and Pub/Sub.
However, many specialized services will not be accessible.
**Essential Roles for Comprehensive Scanning**
For full infrastructure visibility, add these roles beyond `roles/viewer`:
| Role | Service | What We Scan |
| ------------------------------------------------------ | ------------------- | ------------------------------------------------- |
| `roles/apigateway.viewer` | API Gateway | APIs, gateways, and configurations |
| `roles/artifactregistry.reader` | Artifact Registry | Container images and packages |
| `roles/bigquery.dataViewer` + `roles/bigquery.jobUser` | BigQuery | Datasets, tables, and query jobs |
| `roles/certificatemanager.viewer` | Certificate Manager | SSL/TLS certificates |
| `roles/cloudbuild.builds.viewer` | Cloud Build | Build configurations and history |
| `roles/cloudfunctions.viewer` | Cloud Functions | Serverless functions |
| `roles/cloudkms.viewer` | Cloud KMS | Encryption key metadata (not the keys themselves) |
| `roles/composer.environmentAndStorageObjectViewer` | Cloud Composer | Airflow environments |
| `roles/datacatalog.viewer` | Data Catalog | Data discovery and metadata |
| `roles/dataflow.viewer` | Dataflow | Stream and batch processing jobs |
| `roles/dataproc.viewer` | Dataproc | Hadoop/Spark clusters |
| `roles/dns.reader` | Cloud DNS | DNS zones and records |
| `roles/redis.viewer` | Memorystore | Redis and Memcached instances |
| `roles/storage.objectViewer` | Cloud Storage | Buckets and object metadata |
| `roles/workflows.viewer` | Workflows | Workflow definitions and executions |
| `roles/iam.roleViewer` | IAM | Roles and permissions |
| `roles/iam.serviceAccountViewer` | IAM | Service accounts and keys |
| `roles/iam.workloadIdentityPoolViewer` | IAM | Workload identity pools |
View all available roles that Anyshift can utilize for comprehensive infrastructure scanning:
### Services Requiring Additional Roles
These services need specific roles beyond `roles/viewer`:
* **AI Platform**: `roles/aiplatform.viewer`, `roles/notebooks.viewer`
* **API Gateway**: `roles/apigateway.viewer`
* **Artifact Registry**: `roles/artifactregistry.reader`
* **BigQuery**: `roles/bigquery.dataViewer`, `roles/bigquery.jobUser`, `roles/bigquery.metadataViewer`
* **Certificate Manager**: `roles/certificatemanager.viewer`
* **Cloud Billing**: `roles/billing.viewer`, `roles/billing.budgets.viewer`
* **Cloud Build**: `roles/cloudbuild.builds.viewer`
* **Cloud Functions**: `roles/cloudfunctions.viewer`
* **Cloud KMS**: `roles/cloudkms.viewer`
* **Composer**: `roles/composer.environmentAndStorageObjectViewer`
* **Data Catalog**: `roles/datacatalog.viewer`
* **Dataflow**: `roles/dataflow.viewer`
* **Dataproc**: `roles/dataproc.viewer`
* **DNS**: `roles/dns.reader`
* **IAM**: `roles/iam.roleViewer`, `roles/iam.serviceAccountViewer`, `roles/iam.workloadIdentityPoolViewer`
* **Memorystore/Redis**: `roles/redis.viewer`
* **Storage**: `roles/storage.objectViewer`
* **Workflows**: `roles/workflows.viewer`
### Services Covered by `roles/viewer`
These services are already accessible with the basic viewer role:
* Cloud SQL
* Compute Engine (including networks)
* Container/GKE
* Firestore
* Logging
* Monitoring
* Pub/Sub
* Service Networking
# Setup Guide
## Step 1 · Create a read-only service account
**Terraform**
```hcl theme={null}
resource "google_service_account" "anyshift" {
account_id = "anyshift-readonly"
display_name = "Read-only service account for Anyshift"
}
# Option 1: Quick setup with basic viewer role
resource "google_project_iam_member" "anyshift_viewer" {
project = var.project_id
role = "roles/viewer"
member = "serviceAccount:${google_service_account.anyshift.email}"
}
# Option 2: Comprehensive setup with all recommended roles
locals {
anyshift_roles = [
"roles/viewer",
"roles/apigateway.viewer",
"roles/artifactregistry.reader",
"roles/bigquery.dataViewer",
"roles/bigquery.jobUser",
"roles/certificatemanager.viewer",
"roles/cloudbuild.builds.viewer",
"roles/cloudfunctions.viewer",
"roles/cloudkms.viewer",
"roles/composer.environmentAndStorageObjectViewer",
"roles/datacatalog.viewer",
"roles/dataflow.viewer",
"roles/dataproc.viewer",
"roles/dns.reader",
"roles/redis.viewer",
"roles/storage.objectViewer",
"roles/workflows.viewer",
"roles/iam.roleViewer",
"roles/iam.serviceAccountViewer",
"roles/iam.workloadIdentityPoolViewer"
]
}
resource "google_project_iam_member" "anyshift_comprehensive" {
for_each = toset(local.anyshift_roles)
project = var.project_id
role = each.value
member = "serviceAccount:${google_service_account.anyshift.email}"
}
```
**Console**
1. Go to **IAM & Admin → Service Accounts → Create Service Account**
2. Name: `anyshift-readonly`, Description: "Read-only service account for Anyshift" → **Create**
3. Go to **IAM & Admin → IAM → Grant Access**
4. Add the service account email and assign roles:
**For Quick Setup:**
* `Viewer` (Basic role)
**For Recommended Setup, also add:**
* `API Gateway Viewer`
* `Artifact Registry Reader`
* `BigQuery Data Viewer`
* `BigQuery Job User`
* `Certificate Manager Viewer`
* `Cloud Build Viewer`
* `Cloud Functions Viewer`
* `Cloud KMS Viewer`
* `Cloud Composer Viewer`
* `Data Catalog Viewer`
* `Dataflow Viewer`
* `Dataproc Viewer`
* `DNS Reader`
* `Memorystore Redis Viewer`
* `Storage Object Viewer`
* `Workflows Viewer`
* `IAM Role Viewer`
* `IAM Service Account Viewer`
* `IAM Workload Identity Pool Viewer`
**Tip**: Use the filter box to quickly find roles. You can select multiple roles before clicking Save.
5. Go back to **Service Accounts**, click on your `anyshift-readonly` account
6. Go to **Keys** tab → **Add Key** → **Create new key** → **JSON** → **Create**
7. Download and securely store the JSON key file
## Step 2 · Add the service account in Anyshift
Go to `Integrations → GCP → Add Service Account` and upload the JSON file containing the credentials.
We are working to add support for Workload Identity Federation.
This will allow you to grant Anyshift access without managing service account keys, using GCP's native identity federation capabilities.
# Try Anyshift
Start mapping your GCP infrastructure today!
See Anyshift Root Cause Analysis in action
# GitHub Integration
Source: https://docs.anyshift.io/pages/integration/github
Enhance Annie's knowledge with your application and infrastructure code
Connect your GitHub repositories to Annie to enrich her understanding of your application and infrastructure code. This integration enables Annie to:
* Map your application code and Infrastructure as Code (IaC)
* Provide intelligent PR reviews
* Track code and infrastructure changes
* Map resource dependencies
## Setup Guide
1. Go to the [Anyshift integrations page](https://app.anyshift.io/integrations)
2. Navigate to the GitHub section
3. Follow the setup instructions
Choose which repositories to connect:
1. Select your GitHub organization
2. Choose repositories containing application or infrastructure code
**Tip**: Include all repositories with application or infrastructure code to maximize Annie's understanding of your environment.
The default install (`anyshift-app`) is **read-only**. If you also want Annie to open pull requests via the [Propose Fix](/pages/product/propose_fix) feature, install the separate **Anyshift Agentic App** (`anyshift-agentic-app`).
1. In the Anyshift integrations page, click **Enable write mode** in the GitHub section
2. Authorize the Agentic App on the same organization
3. Pick the repositories Annie is allowed to write to
The two apps are independent: the investigation app keeps its read-only scope, and the agentic app's write permissions are isolated to repositories you explicitly select. Without the agentic app installed, Propose Fix CTAs do not appear and Annie cannot create branches, commits, or pull requests.
## Features Enabled
Deep understanding of your application code, infrastructure definitions, and dependencies
Comprehensive analysis of infrastructure changes and their effects
## Integration Capabilities
* **Code Understanding**: Annie analyzes your application and infrastructure code to build a comprehensive knowledge base
* **Change Detection**: Monitors repository changes to keep insights current
* **PR Integration**: Provides automated reviews and suggestions
* **Cross-Repository Analysis**: Understands dependencies across multiple repositories
This integration forms a key part of Annie's knowledge base, enabling her to provide more accurate and context-aware assistance across all features.
## Try Annie Today
Start building your infrastructure knowledge graph and unlock intelligent infrastructure management.
Create your Anyshift account
See Annie's knowledge graph in action
# GitLab Integration
Source: https://docs.anyshift.io/pages/integration/gitlab
Enhance Annie's knowledge with your application and infrastructure code
Connect your GitLab projects to Annie to enrich her understanding of your application and infrastructure code. This integration enables Annie to:
* Map your application code and Infrastructure as Code (IaC)
* Track code and infrastructure changes
* Map resource dependencies
## Setup Guide
1. In your GitLab account, create a new application (Settings → Applications)
2. Name it "Anyshift"
3. Set the redirect URL: `https://app.anyshift.io/gitlab-callback/authenticated`
4. Select the following permission scopes:
* `api` (Access the API on your behalf) — allows Anyshift to configure webhooks on your projects
* `read_user` (Read your personal information)
* `read_repository` (Allows read-only access to the repository)
1. Go to the [Anyshift integrations page](https://app.anyshift.io/integrations)
2. Connect the integration and accept to install the Anyshift application
3. Once redirected to Anyshift, click on Configure
4. Select the projects to synchronize with Anyshift
**Tip**: Include all projects with application or infrastructure code to maximize Annie's understanding of your environment.
## Features Enabled
Deep understanding of your application code, infrastructure definitions, and dependencies
Comprehensive analysis of infrastructure changes and their effects
## Integration Capabilities
* **Code Understanding**: Annie analyzes your application and infrastructure code to build a comprehensive knowledge base
* **Change Detection**: Monitors project changes to keep insights current
* **Cross-Project Analysis**: Understands dependencies across multiple projects
This integration forms a key part of Annie's knowledge base, enabling her to provide more accurate and context-aware assistance across all features.
## Try Annie Today
Start building your infrastructure knowledge graph and unlock intelligent infrastructure management.
Create your Anyshift account
See Annie's knowledge graph in action
# Grafana Integration
Source: https://docs.anyshift.io/pages/integration/grafana
Integrate Annie with Grafana for unified observability and intelligent investigation.
# Grafana Integration
Grafana integration enables Annie to ingest logs, metrics, and alerts (alert rules and their firing instances), providing a unified, intelligent view of your infrastructure's health and performance.
## Setup Guide
1. Create a Grafana [service account and token](#create-a-grafana-service-account) with the required roles
2. Go to the [Anyshift Grafana integration page](https://app.anyshift.io/integrations/monitoring/grafana)
3. Select **Grafana Cloud** or **Self-Hosted Grafana**
4. Enter your **Grafana Instance URL**
5. Enter a display name for the service account and paste the **Service Account Token**
6. Click **Save Grafana Configuration**
⚠️ Anyshift currently supports one Grafana integration per account. Contact us if you need multiple instances supported.
### 1. Grafana Instance URL
* For Grafana Cloud, enter your stack name only (for example `your-org`). Anyshift builds `https://your-org.grafana.net` for you.
* For self-hosted, use your public or internal Grafana URL (for example `https://grafana.example.com`)
### 2. Service Account & API Token
Annie authenticates with a Grafana **service account token** (it starts with `glsa_`). Do not use a personal API key or a Grafana Cloud Access Policy token.
#### Create a Grafana service account
You need Grafana organization Admin permissions (or equivalent service-account creator roles) in the instance you are connecting.
1. Sign in to the Grafana instance you want to connect (for Grafana Cloud, open your stack at `https://your-org.grafana.net`, not only the Grafana.com portal)
2. In the left menu, go to **Administration → Users and access → Service accounts**
3. Click **Add service account**
4. Enter a display name such as `anyshift-readonly`
5. Set the basic role to **Viewer**
6. Click **Create**
#### Add the Alerting provisioning role
A plain **Viewer** can query dashboards and data sources, but cannot read alert rules through the provisioning API that Anyshift uses (`/api/v1/provisioning/alert-rules`).
1. Open the service account you just created
2. In the role picker / Fixed roles section, add **Alerting:Read via Provisioning API + Export Secrets** (`fixed:alerting.provisioning.secrets:reader`)
3. Click **Update**
Anyshift only reads alert rule definitions. It does not call Grafana's export-with-decrypted-secrets endpoints. Grafana nevertheless packages that capability into this fixed role, so treat the token like any other credential that could reach alerting contact-point secrets if misused. On Grafana Cloud or Enterprise you can instead create a custom role with only `alert.provisioning:read` if you want to avoid the secrets permission.
If your Grafana edition does not expose that fixed role, assign **Alerting provisioning writer** (`fixed:alerting.provisioning:writer`) instead. That grants write access to alert rules; Anyshift still only reads them.
#### Create a service account token
1. Still on the service account page, click **Add service account token**
2. Enter a token name such as `anyshift`
3. Optionally set an expiration date
4. Click **Generate token**
5. Copy the token immediately and store it securely. Grafana shows it only once.
Paste that token into Anyshift as the **Service Account Token**. The **Service Account Name** field in Anyshift is a label for your team; it does not need to match the Grafana display name exactly.
## How It Works
Once connected, Anyshift automatically ingests logs, metrics, and alerts from Grafana. When an incident occurs, Annie’s AI agent:
* Correlates Grafana logs and metrics with your resource graph
* Traces request chains across services
* Surfaces root causes and actionable insights
* Reduces the need to manually jump between dashboards
**Anyshift + Grafana = Observability superpowers.**
Ready to get started?
# Guru Integration
Source: https://docs.anyshift.io/pages/integration/guru
Connect your Guru knowledge base to enable Annie to search and leverage your team's internal documentation and runbooks.
# Guru Integration
Guru integration enables Annie to access your team's knowledge base, allowing it to search internal documentation, runbooks, and procedures when investigating incidents or answering questions.
## Setup Guide
### Option A: Connect with Guru (recommended)
1. Go to the [Guru integration page](https://app.anyshift.io/integrations/knowledge/guru).
2. Click **Connect with Guru**.
3. Sign in to Guru (if needed) and authorize Anyshift.
4. You are redirected back to Anyshift with Guru connected.
OAuth uses Guru's MCP Dynamic Client Registration flow. Access is scoped to the authorizing Guru user's permissions. You can disconnect at any time from the Anyshift integration page.
> **Note:** Guru may require Support to whitelist Anyshift redirect URIs before OAuth works in a given environment. If authorize fails before consent, contact Guru Support (or Anyshift) to confirm the whitelist.
### Option B: Email + User Token
Use this if you prefer a static token or OAuth is not available yet.
1. Go to the [Guru integration page](https://app.anyshift.io/integrations/knowledge/guru).
2. Click **Connect Guru** (or **New credentials**).
3. Enter your **Guru Email** and **User Token**.
4. Optionally configure a custom **Base URL** (for enterprise deployments).
5. Click **Save**.
### 1. Email
Enter the email address associated with your Guru account (e.g., `user@company.com`).
### 2. User Token
Generate a User Token from your Guru account:
1. Log in to Guru
2. Go to **Manage** > **Apps and Integrations** > **API Access**
3. Click **Generate User Token**
4. Copy the token and paste it into Anyshift
For more details on Guru's authentication methods, see [Guru's API Authentication documentation](https://developer.getguru.com/docs/guru-api-authentication).
Keep your API token secure and do not share it publicly.
### 3. Base URL (Optional)
For most users using Guru Cloud, leave this field empty - the default URLs work automatically.
If your organization uses a **self-hosted Guru deployment**, enter your custom base URL here. This URL is used for both:
* Generating clickable links to Guru cards in Annie's responses
* Connecting to your Guru MCP server (appends `/mcp` to your base URL)
**Example**: If your self-hosted Guru is at `https://guru.company.com`, Annie will connect to `https://guru.company.com/mcp`.
## Required Permissions
Annie performs **read-only** operations on your Guru knowledge base. Your User Token grants access to all collections you can view.
Your token needs access to:
* Knowledge agents
* Cards and collections
* Search functionality
Annie does not create, modify, or delete any content in your Guru knowledge base.
## How It Works
Once connected, Annie can leverage your Guru knowledge base during:
* **Incident Investigation**: When analyzing an incident, Annie searches your runbooks and procedures for relevant remediation steps and correlates issues with documented known problems and solutions
* **Question Answering**: When you ask Annie about internal processes, it searches Guru for documented procedures
### Example Use Cases
* "What's our procedure for Redis failover?"
* "Search our knowledge base for Kubernetes pod restart troubleshooting"
* "Find the runbook for database connection pool exhaustion"
Annie will search your Guru knowledge base and cite the relevant cards in its responses.
## Security
* API tokens are encrypted at rest using AWS KMS
* Anyshift only reads from your Guru knowledge base (no write operations)
* All communication uses HTTPS/TLS encryption
Ready to get started?
# HCP Integration
Source: https://docs.anyshift.io/pages/integration/hcp
Integrate Annie with HashiCorp Cloud Platform for Terraform backend and secrets management.
# HCP Integration
HCP integration allows Annie to connect to HashiCorp Cloud Platform (HCP Terraform / Terraform Enterprise) to retrieve state file data when it is not stored on S3.
## Setup Guide
1. Go to the [HCP Cloud integration page](https://app.anyshift.io/integrations/terraform-backend/hcp-cloud)
2. Click **New token**
3. Fill in the HCP Cloud URL, workspace, and API token as described below
### 1. HCP Cloud URL
Usually `https://app.terraform.io`. Use your Terraform Enterprise hostname if you are self-hosting.
### 2. Workspace
The HCP Terraform workspace whose state Annie should ingest. Supported formats:
* Workspace ID: `ws-…`
* Organization and name: `organization/workspace`
Create one Anyshift credential set per workspace you want Annie to read.
### 3. Token
Annie authenticates to HCP Terraform with an API token that can **read the workspace and download its current state**. A **team token** (or group token on HCP Europe) is the recommended choice for shared automation. A **user token** also works if the user can access the workspace.
Organization tokens are not recommended for this integration. Prefer a team or user token scoped to the workspaces Annie needs.
#### Option A: Team API token (recommended)
1. Sign in to [HCP Terraform](https://app.terraform.io) (or your Terraform Enterprise instance)
2. Open **Organization Settings** → **API Tokens** → **Team Tokens**
3. Choose a team that has access to the target workspace
4. Create a new team token and copy it immediately (it is only shown once)
5. Paste the token into Anyshift
For details, see HashiCorp's [Manage API tokens](https://developer.hashicorp.com/terraform/cloud-docs/users-teams-organizations/api-tokens) documentation.
#### Option B: User API token
1. Sign in to [HCP Terraform](https://app.terraform.io) (or your Terraform Enterprise instance)
2. Click your user icon → **Account settings** → **Tokens**
3. Click **Create an API token**, add a description, and set an expiration
4. Copy the token immediately (it is only shown once)
5. Paste the token into Anyshift
For details, see HashiCorp's [Creating a token](https://developer.hashicorp.com/terraform/cloud-docs/users-teams-organizations/users#api-tokens) documentation.
If you have a single token that can access multiple workspaces, you can reuse it in Anyshift, but you still need a separate credential set per workspace. If that is a blocker, tell us and we will prioritize multi-workspace credentials.
# Incident.io Integration
Source: https://docs.anyshift.io/pages/integration/incident-io
Integrate with incident.io to give Annie read access to your incidents, alerts, postmortems, and workflows.
# Incident.io Integration
Connect incident.io to give Annie access to your incident management data. During investigations, Annie can correlate alerts with incidents, review postmortems, and surface actionable context from your incident history.
## Setup Guide
1. Go to the [Incident.io integration page](https://app.anyshift.io/integrations/incidents-management/incident-io)
2. Click **New token** to add your incident.io API key
### API Key
Generate an API key from your incident.io dashboard under **Settings > API keys**. The key should have read access to the resources you want Annie to use.
### Required Permissions
When creating the API key, enable the following permission groups:
* **View data, like public incidents and organization settings** (18 scopes) - Access incidents, alerts, postmortems, users, and organization data
* **View catalog types and entries** (3 scopes) - Browse catalog entries for service and team context
## How It Works
Once connected, Annie's AI agent can:
* **Investigate incidents** - Fetch incident details, timelines, and status updates
* **Correlate alerts** - Link alerts to incidents and trace alert routes
* **Review postmortems** - Access postmortem content and learnings from past incidents
* **Inspect workflows** - View incident response workflows
* **Browse the catalog** - Query catalog entries for service and team context
* **Track follow-ups** - List follow-up actions from incidents
* **View roles & users** - List available incident roles and responders
## Slack Bot in Incident Channels
To give Annie visibility into your incident channels, configure incident.io to automatically invite the Annie Slack bot to new incident channels:
1. In incident.io, go to **Settings > Workflows**
2. Add or edit a workflow triggered on incident creation
3. Add the **Invite a Slack bot user to an incident channel** step
4. Select **Annie** as the bot user
This ensures Annie is present in every incident channel and can follow conversations, provide context, and assist during active incidents.
## Webhooks
Click **New webhook** to configure a webhook for real-time incident updates. This allows Annie to react to incidents as they happen.
When Annie investigates a webhook-triggered incident, Slack notifications follow your project's **Webhook investigation notifications** settings on the [Slack integrations page](/pages/product/integration/slack#other-settings). If the incident includes a Slack channel (for example `slack_channel_id`), turn on **Channel from the incident** so Annie posts there. Use **Default notify channel** only as a fallback when no incident channel is attached.
# Jira Integration
Source: https://docs.anyshift.io/pages/integration/jira
Connect your Jira instance to enable Annie to search issues, access ticket details, and leverage project information during incident investigation.
# Jira Integration
Jira integration enables Annie to access your issue tracker, allowing it to search tickets, retrieve issue details, and correlate incidents with existing bugs, tasks, and historical issues.
## Setup Guide
The recommended way to connect is **Connect with Atlassian** (OAuth). One authorization covers both Jira and [Confluence](/pages/integration/confluence). You can still use an email + API token as a fallback.
### Option A: Connect with Atlassian (recommended)
1. Go to the [Anyshift integrations page](https://app.anyshift.io/integrations)
2. Navigate to the Knowledge Base section
3. Select **Jira**
4. Click **Connect with Atlassian**
5. Sign in to Atlassian and approve access for your site
6. You return to Anyshift with the connected site shown (for example, your company Atlassian domain)
The same connection also enables Confluence. You do not need to authorize twice if you later open the Confluence integration page.
To disconnect, use **Disconnect** on the Jira or Confluence integration page. That removes the shared Atlassian OAuth connection for the project.
### Option B: Email + API token (fallback)
Use this if your organization prefers API tokens, or if OAuth is unavailable.
1. Go to the [Anyshift integrations page](https://app.anyshift.io/integrations)
2. Navigate to the Knowledge Base section
3. Select **Jira**
4. Under the API token section, click **Add**
5. Enter your **Jira Domain**, **Email**, and **API Token**
6. Click **Save**
#### Jira Domain
Enter your Atlassian domain (e.g., `yourcompany.atlassian.net`).
This is the URL you use to access Jira Cloud. For example, if you access Jira at `https://acme.atlassian.net`, enter `acme.atlassian.net`.
#### Email
Enter the email address associated with your Atlassian account (e.g., `user@company.com`).
#### API Token
Anyshift supports both **scoped** and **classic** Atlassian API tokens. Prefer scoped tokens for least-privilege access.
No admin configuration is required. Any Atlassian user can create a token and connect their Jira instance.
**Scoped API token**
1. Go to [Atlassian API Token Management](https://id.atlassian.com/manage-profile/security/api-tokens)
2. Click **Create API token**
3. Select **Scoped** token type
4. Enter a label (e.g., "Anyshift Integration")
5. Grant the following scopes:
* `read:jira-work` - Read Jira issues and projects
* `read:jira-user` - Read user information
* `read:servicedesk-request` - Read service desk requests
* `read:me` - Read your profile information
* `read:account` - Read account information
6. Click **Create**
7. Copy the token and paste it into Anyshift
**Classic API token**
Classic tokens inherit all permissions of the Atlassian account.
1. Go to [Atlassian API Token Management](https://id.atlassian.com/manage-profile/security/api-tokens)
2. Click **Create API token**
3. Select **Classic** token type
4. Enter a label (e.g., "Anyshift Integration")
5. Click **Create**
6. Copy the token and paste it into Anyshift
For more details, see [Atlassian's API Token documentation](https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/).
Keep your API token secure and do not share it publicly.
## Required Permissions
Annie performs **read-only** operations on your Jira instance. Access follows the Atlassian account you authorize (OAuth) or the account tied to your API token.
Your account needs access to:
* View projects
* View issues and their details
* Search issues using JQL
Annie does not create, modify, or delete any issues, comments, or other content in your Jira instance.
## How It Works
Once connected, Annie can leverage your Jira instance during:
* **Incident Investigation**: When analyzing an incident, Annie searches for related issues, bugs, and historical tickets to find relevant context and past resolutions
* **Question Answering**: When you ask about specific tickets or projects, Annie retrieves the details directly from Jira
* **Correlation**: Annie can correlate alerts and incidents with existing Jira tickets to identify known issues
### Example Use Cases
* "Search Jira for authentication issues from the last week"
* "Get details on ticket INFRA-1234"
* "Find all high-priority bugs in the Platform project"
* "What Jira tickets are related to Redis connection issues?"
Annie will search your Jira instance using JQL (Jira Query Language) and cite relevant issues in its responses.
### JQL Query Examples
Annie can construct JQL queries automatically based on your questions:
| Question | JQL Query |
| ---------------------------- | ----------------------------------------------------- |
| "Recent bugs" | `type = Bug AND created >= -7d ORDER BY created DESC` |
| "Open high priority issues" | `priority = High AND status != Done` |
| "Authentication issues" | `text ~ "authentication" OR summary ~ "auth"` |
| "Issues in Platform project" | `project = PLATFORM ORDER BY updated DESC` |
## Supported Features
Annie can access the following Jira data:
**Issues**
* Search issues using JQL
* Get full issue details (summary, description, status, priority, assignee, etc.)
* View available status transitions
**Projects**
* List all accessible projects
* Get project details and metadata
**Metadata**
* Get available issue types for a project
* Get custom field definitions
## Project Scoping
You can optionally restrict which Jira projects Annie can access by specifying **Allowed Projects** when configuring credentials.
Enter a comma-separated list of Jira project keys (e.g., `CSGSRE,SRESD,CTXSRESD`). When configured:
* **Searches** are automatically scoped to the specified projects
* **Direct issue access** is restricted — Annie cannot fetch issues from projects not in the list
* **Project listings** only show the allowed projects
Leave the field empty to allow access to all projects the service account can see.
This is useful when a service account has broad access but you want Annie to focus on specific projects. For stronger isolation, you can also configure project-level permissions on the Atlassian service account itself.
## Security
* OAuth access and refresh tokens, and API tokens, are encrypted at rest using AWS KMS
* Anyshift only reads from your Jira instance (no write operations)
* All communication uses HTTPS/TLS encryption
* Credentials are validated against Atlassian APIs when you connect
## Troubleshooting
### OAuth connect fails or returns an error
1. **Consent cancelled**: Start again with **Connect with Atlassian** and approve access.
2. **Wrong Atlassian account**: Sign out of Atlassian in the browser, then reconnect with the account that can see your Jira site.
3. **Connection shows error status**: Disconnect and reconnect with Atlassian so Anyshift can obtain a fresh grant.
### "401 Unauthorized" or "Invalid credentials" error (API token)
This is usually caused by one of the following:
1. **Token missing required scopes** (scoped tokens only): Ensure your scoped token has the `read:jira-work`, `read:jira-user`, `read:servicedesk-request`, `read:me`, and `read:account` scopes.
2. **Email/token mismatch**: Verify your email matches your Atlassian account email exactly.
3. **Expired or revoked token**: Generate a new API token from your [Atlassian account settings](https://id.atlassian.com/manage-profile/security/api-tokens).
### "No issues found" when searching
* Verify your account has permission to view the projects being searched
* Check that the JQL query syntax is valid
* Ensure issues exist matching your search criteria
### Connection timeout
* For API token setup, verify your Jira domain is correct (e.g., `yourcompany.atlassian.net`)
* Check that your Atlassian instance is accessible
Ready to get started? [Configure Jira Integration](https://app.anyshift.io/integrations)
# Kubernetes Integration
Source: https://docs.anyshift.io/pages/integration/kubernetes
Integrate Annie with Kubernetes for container orchestration insights.
# Kubernetes Integration
Connect Annie to your clusters for deep insights into container orchestration, workloads, and resource usage.
## Prerequisites
* Kubernetes 1.20+
* Helm 3.8+
* Anyshift API token (generate one at [app.anyshift.io/integrations](https://app.anyshift.io/integrations))
[View changelog](https://helm.anyshift.io/changelog/latest.html)
## Setup
```bash theme={null}
helm repo add anyshift https://helm.anyshift.io
helm repo update
```
Recommended for production. Create a secret to hold your API token:
```bash theme={null}
kubectl create secret generic anyshift-secret \
--namespace anyshift-agent \
--from-literal api-key=""
```
Install using the secret:
```bash theme={null}
helm install anyshift-agent anyshift/anyshift-k8s-agent \
--namespace anyshift-agent --create-namespace \
--set token.secretName="anyshift-secret" \
--set token.secretKeyName="api-key" \
--set clusterName=""
```
Replace `` with your token from the [integrations page](https://app.anyshift.io/integrations) and `` with a meaningful name (e.g. "production-us-east", "staging-eu").
For testing, you can pass the token directly with `--set token.value=""` instead of using a secret.
Check that the agent is running:
```bash theme={null}
kubectl get pods -n anyshift-agent
```
View agent logs:
```bash theme={null}
kubectl logs -n anyshift-agent -l app.kubernetes.io/name=anyshift-k8s-agent
```
## Live Cluster Queries
Beyond the periodic snapshot, the agent supports live queries from Annie on demand: describing resources, reading pod logs, inspecting events, listing CRDs, and reading Helm release values. No inbound ports are opened on your cluster; the agent only makes outbound connections. Even over live queries, secret values are stripped from responses; only Secret metadata (name, namespace, labels, annotations, type) is ever returned.
## Reference
Agent resource usage depends on cluster size:
| Cluster Size | Recommended Memory |
| --------------------- | ------------------ |
| Small (\<50 nodes) | 256Mi - 512Mi |
| Medium (50-200 nodes) | 512Mi - 1Gi |
| Large (200+ nodes) | 1Gi - 2Gi |
On warmup, or when many events occur at once, the agent collects cluster state data which temporarily increases memory usage. For large clusters, you may need to set memory limits up to 2GB.
To configure higher memory limits:
```yaml theme={null}
resources:
limits:
memory: 2Gi
requests:
memory: 1Gi
```
Use a `values.yaml` file for full control over the install. If you use the secret method, create the secret first:
```bash theme={null}
kubectl create secret generic anyshift-secret \
--namespace anyshift-agent \
--from-literal api-key=""
```
Create `values.yaml`:
```yaml theme={null}
clusterName: "YOUR_CLUSTER_NAME" # Example: "staging-eu", "prod-cluster"
token:
# Option 1: Reference to Kubernetes secret (recommended)
secretName: "anyshift-secret"
secretKeyName: "api-key"
# Option 2: Direct value (not recommended for production)
# value: "your-api-token"
# Common optional configurations
replicaCount: 2
nameOverride: ""
fullnameOverride: ""
namespaceOverride: ""
image:
repository: ghcr.io/anyshift-io/anyshift-k8s-agent
pullPolicy: IfNotPresent
baseURL: "https://api.anyshift.io"
logLevel: info
logFormat: json
port: 8080
metricsPort: 8081
localMode: false
initialSnapshotWait: 30s
batchWindow: 5m
resyncPeriod: 1h
heartbeatInterval: 5m
# Exclude secrets from tracking. When true, the agent's ClusterRole drops
# get/list/watch on v1/secrets entirely.
excludeSecrets: false
# Extra API groups to grant the agent read access to, for in-house or niche
# CRDs not covered by the default ecosystem list.
# Example:
# extraApiGroups:
# - acme.com
# - crossplane.io
extraApiGroups: []
podAnnotations: {}
customLabels: {}
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 400m
memory: 512Mi
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 3
targetCPUUtilizationPercentage: 50
podDisruptionBudget:
enabled: true
minAvailable: 1
initialUploadRetry:
initialInterval: 2s
multiplier: 2
maxInterval: 30s
maxElapsed: 10m
# HTTP client timeout for upload requests
httpTimeout: 2m # Increase for large clusters or slow networks
nodeSelector: {}
tolerations: []
affinity: {}
```
Install with custom values:
```bash theme={null}
helm install anyshift-agent anyshift/anyshift-k8s-agent \
--namespace anyshift-agent --create-namespace \
-f values.yaml
```
**Cluster name templating.** Use Go template syntax for dynamic cluster names:
```bash theme={null}
# Use custom values in cluster name
helm install anyshift-agent anyshift/anyshift-k8s-agent \
--namespace anyshift-agent --create-namespace \
--set token.value="" \
--set clusterName="{{ .Values.customLabels.environment }}-{{ .Values.customLabels.region }}-cluster" \
--set customLabels.environment="production" \
--set customLabels.region="us-east"
# Results in cluster name: "production-us-east-cluster"
```
**Custom labels.** Add custom labels to all resources:
```bash theme={null}
helm install anyshift-agent anyshift/anyshift-k8s-agent \
--namespace anyshift-agent --create-namespace \
--set token.value="" \
--set clusterName="production" \
--set customLabels.environment=production \
--set customLabels.team=platform \
--set customLabels.cost-center=engineering
```
**Dynamic cluster naming with custom labels (values.yaml).**
```yaml theme={null}
token:
value: "your-api-token"
# Use custom labels in cluster naming via Go templates
clusterName: "{{ .Values.customLabels.environment }}-{{ .Values.customLabels.region }}-cluster"
# Custom labels applied to all resources
customLabels:
environment: production
region: us-east
team: platform
cost-center: engineering
compliance: sox
# This configuration will:
# - Create cluster name: "production-us-east-cluster"
# - Apply all custom labels to agent resources
```
The agent tracks Secret **metadata only** (name, namespace, labels, annotations, type). Secret values are stripped before anything leaves your cluster, in both the periodic snapshot and the live query paths. Metadata is what's needed to understand topology and relationships.
For environments with strict security requirements, you can drop secrets access entirely at the RBAC layer.
**Option 1: Command line**
```bash theme={null}
helm install anyshift-agent anyshift/anyshift-k8s-agent \
--namespace anyshift-agent --create-namespace \
--set token.value="" \
--set clusterName="" \
--set excludeSecrets=true
```
**Option 2: values.yaml**
```yaml theme={null}
excludeSecrets: true
```
When `excludeSecrets=true`, the agent's `ClusterRole` drops `get/list/watch` on `v1/secrets` entirely.
The agent requires **read-only** access (`get`, `list`, `watch`). The `ClusterRole` covers:
* All standard Kubernetes resources (core + apps, batch, networking, rbac, policy, autoscaling, storage, discovery, coordination, apiextensions, metrics, gateway, …).
* Common add-on ecosystems (Argo CD/Flux, Istio/Linkerd, KEDA, Cert-Manager, Prometheus Operator, Kyverno/Gatekeeper, Crossplane, Tekton, Knative, Velero, Cilium/Calico, Kafka, Elastic, …).
* Per-cloud controllers (EKS, GKE, AKS).
The full list is in the chart at [`templates/clusterRole.yaml`](https://github.com/anyshift-io/anyshift-k8s-agent/blob/main/chart/anyshift-k8s-agent/templates/clusterRole.yaml).
**Adding custom CRDs.** If you run in-house CRDs or an ecosystem not covered by the default list, extend the RBAC via `extraApiGroups`:
```yaml theme={null}
extraApiGroups:
- acme.com
- crossplane.io
```
These are added to the agent's `ClusterRole` with the same read-only verbs, so Annie can describe and list them during live queries.
To upgrade the agent to the latest version:
```bash theme={null}
# Step 1: Update the Helm repository
helm repo update anyshift
# Step 2: Upgrade the agent
helm upgrade anyshift-agent anyshift/anyshift-k8s-agent \
--namespace anyshift-agent \
--reset-then-reuse-values
```
`--reset-then-reuse-values` keeps the overrides you set at install time while picking up any new defaults shipped by the chart (new fields, updated values). It's the recommended flag for upgrades that introduce new configuration options.
```bash theme={null}
helm uninstall anyshift-agent --namespace anyshift-agent
```
# Linear Integration
Source: https://docs.anyshift.io/pages/integration/linear
Integrate with Linear to give Annie access to your issues, projects, and team context during incident investigations.
# Linear Integration
Connect Linear to give Annie visibility into the engineering work behind your infrastructure. During an incident or chat session, Annie can search Linear for related tickets, retrieve issue details, and tie infrastructure changes back to the issues that requested them.
## Setup Guide
### Option A: Connect with Linear (recommended)
1. Go to the [Linear integration page](https://app.anyshift.io/integrations/knowledge/linear).
2. Click **Connect with Linear**.
3. Sign in to Linear (if needed) and authorize Anyshift.
4. You are redirected back to Anyshift with the workspace connected.
OAuth uses a refreshable access token scoped to your Linear account. You can disconnect at any time from the Anyshift integration page or by revoking Anyshift in Linear's application settings.
### Option B: Personal API key
Use this if you prefer a static key or OAuth is not enabled for your workspace yet.
#### 1. Create a Linear personal API key
1. In Linear, open **Settings → My Account → Security & access → API keys**, or jump straight to the creation flow at `https://linear.app//settings/account/security/api-keys/new`.
2. Give the key a label (e.g. `Anyshift / Annie`) and click **Create key**.
3. Copy the generated API key. Linear only shows it once.
Personal API keys inherit the permissions of the user who created them. For least-privilege access, create the key from an account that has only the workspace access you want Annie to have.
#### 2. Find your workspace URL key
The workspace URL key is the slug in your Linear URL, immediately after `linear.app/`.
For example, if your workspace lives at `https://linear.app/acme`, your workspace URL key is `acme`.
You can paste the full URL into the Anyshift form. Anyshift strips the `linear.app/` prefix and any trailing slash automatically.
#### 3. Connect Linear to Anyshift
1. Go to the [Linear integration page](https://app.anyshift.io/integrations/knowledge/linear).
2. Click **New credentials**.
3. Fill in the form fields below and click **Save**.
##### Display name
A human-readable label for this credential (e.g. `Engineering Workspace`). Used only to identify the credential in the Anyshift UI.
##### Workspace URL key
The slug for your Linear workspace (e.g. `acme`). Pasting the full URL also works.
##### API key
Paste the **personal API key** you copied in step 1.
Anyshift validates the credentials against Linear's GraphQL API on save. The credential is stored even if validation fails, so you can fix and retry without re-entering the form.
### Required Permissions
Annie performs **read-only** operations on your Linear workspace. OAuth and personal API keys both grant access based on the permissions of the authorizing user.
The Linear user needs access to:
* View issues
* View teams and team members
* View projects
Annie does not create, modify, or delete any issues, comments, or other content in your Linear workspace.
## How It Works
Anyshift's agent gateway authenticates against Linear's GraphQL API using the OAuth access token or personal API key you provided. Tokens are encrypted at rest (KMS) and only decrypted in-process when Annie makes a Linear call. OAuth credentials are refreshed automatically when they expire.
Once connected, Annie's AI agent can:
* **List filtered issues** — Filter by assignee (including "assigned to me"), team, state, or title substring.
* **Search your workspace** — Free-text search across issues by title, description, and identifier (not by assignee).
* **Read issues** — Retrieve a single issue by identifier (e.g. `ENG-42`) with its team, state, assignee, labels, description, parent, and project.
* **Browse teams** — List teams in the workspace or fetch a specific team by key (e.g. `ENG`), including members and active issues.
* **Browse projects** — List projects in the workspace or fetch a specific project by slug or UUID.
* **Resolve the workspace** — Look up the authenticated user (viewer) and their organization to confirm what the credential can see.
### Example use cases
* "What Linear issues are assigned to me?"
* "List open tickets on the Platform team."
* "Find the Linear issue that tracks the database migration we shipped last Tuesday."
* "What's the engineering ticket behind this Terraform change?"
* "Pull the open issues in the `Platform` team that mention Redis."
* "What project does `ENG-1234` belong to?"
### Security & scope
* Access follows the Linear user who connected (OAuth) or created the key (API key). To restrict what Annie can see, connect from an account with scoped access.
* Credentials are encrypted at rest using AWS KMS and only decrypted in-process by Anyshift's gateway.
* All communication with Linear uses HTTPS/TLS.
* You can revoke access at any time by disconnecting in Anyshift, revoking the OAuth app in Linear, or deleting the personal API key.
**Anyshift + Linear = Annie ties every infrastructure change and incident back to the engineering work that drives it.**
# MotherDuck Integration
Source: https://docs.anyshift.io/pages/integration/motherduck
Connect Annie to MotherDuck for cloud analytics queries with DuckDB.
# MotherDuck Integration
MotherDuck integration enables Annie to query your cloud analytics data using DuckDB SQL, explore database schemas, and correlate analytics findings with infrastructure events during incident investigations.
## Setup Guide
1. Go to the [Anyshift integrations page](https://app.anyshift.io/integrations)
2. Navigate to the **Analytics** section
3. Click **Connect MotherDuck**
4. Enter a **Name** for your token (e.g., "Production MotherDuck")
5. Provide your **MotherDuck API Token**
6. Click **Save MotherDuck token**
Anyshift validates the token against MotherDuck's API on save. If validation fails, check that your token is correct and has not expired.
### MotherDuck API Token
1. Sign in to [app.motherduck.com](https://app.motherduck.com)
2. Go to **Settings** > **Access Tokens**
3. Create a new access token (read-only is sufficient for Annie)
4. Copy the token and paste it into the Anyshift integration form
## How It Works
Once connected, Annie can query your MotherDuck databases during investigations and chat sessions. Annie's AI agent can:
* **List and explore databases** — discover available databases, tables, columns, and shares
* **Run SQL queries** — execute read-only DuckDB SQL against your cloud data
* **Search the catalog** — fuzzy-search across databases, tables, and columns to find relevant data
* **Discover external connections** — identify configured S3 buckets, Azure storage, and other data sources accessible through MotherDuck
## Data Annie Can Access
Annie queries your MotherDuck account using DuckDB SQL. This includes:
* **MotherDuck databases** — your own databases and shared datasets
* **Attached storage** — S3 buckets, Azure Blob Storage, or GCS buckets connected via DuckDB secrets
* **Sample data** — MotherDuck's shared sample datasets (NYC taxi, Hacker News, etc.)
Annie uses read-only queries by default and always applies `LIMIT` clauses to avoid returning excessive data.
## Security
* Your MotherDuck token is encrypted at rest using AWS KMS
* The token is never exposed to the AI agent — it is resolved at request time by the agent gateway
* Annie uses read-only queries and cannot modify or delete data
## Troubleshooting
### "Invalid MotherDuck Token"
* Verify your token at [app.motherduck.com](https://app.motherduck.com) > Settings > Access Tokens
* Ensure the token has not expired or been revoked
* Read-scaling tokens and access tokens are both supported
### "MotherDuck MCP unreachable"
* MotherDuck's MCP endpoint may be temporarily unavailable
* Check [MotherDuck status](https://status.motherduck.com) for outages
* Retry after a few minutes
### Annie doesn't use MotherDuck tools
* Verify the integration shows **Active** status on the integrations page
# Notion Integration
Source: https://docs.anyshift.io/pages/integration/notion
Integrate with Notion to give Annie access to your team's pages, databases, and runbooks during incident investigations.
# Notion Integration
Connect Notion to give Annie visibility into your team's documentation, runbooks, and knowledge base. During an incident or chat session, Annie can search Notion for relevant procedures, retrieve page bodies, and (when permitted) update pages or post comments.
## Setup Guide
### 1. Create a Notion internal integration
1. Go to [Notion's My Integrations page](https://www.notion.so/my-integrations) and click **+ New integration**.
2. Give it a name (e.g. `Anyshift / Annie`) and associate it with the workspace you want Annie to access.
3. On the **Capabilities** tab, grant the capabilities you want Annie to use — at minimum **Read content**. Add **Update content**, **Insert content**, and **Read user information** if you want Annie to make changes or resolve user mentions.
4. Submit and copy the **Internal Integration Token** (starts with `ntn_...`).
### 2. Share the relevant pages and databases with the integration
Notion integrations are *opt-in per page*: Annie can only see pages that have been explicitly shared with your integration.
For each top-level page or database you want Annie to access:
1. Open the page in Notion.
2. Click **...** → **Connect to** → select your `Anyshift / Annie` integration.
3. The integration also gains access to child pages and databases automatically.
For broad access, share a single high-level workspace page (e.g. an `Engineering` or `Runbooks` parent) and Annie will be able to read everything beneath it.
### 3. Connect Notion to Anyshift
1. Go to the [Notion integration page](https://app.anyshift.io/integrations/knowledge/notion).
2. Click **New token**.
3. Fill in the form fields below and click **Save Notion token**.
#### Display name
A human-readable label for this token (e.g. `Engineering Workspace`). Used only to identify the credential in the Anyshift UI.
#### Integration token
Paste the **Internal Integration Token** you copied in step 1 (starts with `ntn_...`).
### Required Permissions
The integration needs these Notion capabilities for Annie to read and edit content:
* **Read content** — Required. Lets Annie search and read pages, databases, and blocks.
* **Update content** — Optional. Lets Annie edit blocks and update page properties.
* **Insert content** — Optional. Lets Annie create new pages, append blocks, or move pages.
* **Read user information** — Optional. Lets Annie resolve `@mentions` and assignees.
* **Read comments** / **Insert comments** — Optional. Lets Annie read and add comments.
Without **Update / Insert content**, Annie can still search and quote Notion pages — it just can't make changes.
## How It Works
Anyshift runs the official open-source [`@notionhq/notion-mcp-server`](https://github.com/makenotion/notion-mcp-server) on its agent gateway and authenticates against your Notion workspace using the integration token you provided.
Once connected, Annie's AI agent can:
* **Search your workspace** — Free-text search across all pages and databases the integration has access to (`post-search`).
* **Read pages and runbooks** — Retrieve page bodies, including nested blocks and child pages (`retrieve-a-page`, `get-block-children`).
* **Query databases** — Filter and sort rows in any database the integration can see (`query-data-source`, `retrieve-a-data-source`, `retrieve-a-database`).
* **Update content** — When permitted, edit blocks, update page properties, create pages, append children, move pages, and add comments.
* **Resolve users and mentions** — Look up workspace members to interpret `@mentions` and assignees.
### Security & scope
* Annie only sees pages explicitly shared with the integration — there is no workspace-wide access by default.
* The integration token is encrypted at rest (KMS) and is only decrypted in-process by Anyshift's gateway when Annie makes a Notion call.
* You can revoke access at any time by removing the integration from a page (or by deleting the integration entirely in Notion).
**Anyshift + Notion = Annie answers from your team's actual runbooks, not generic best-practices.**
# PagerDuty Integration
Source: https://docs.anyshift.io/pages/integration/pagerduty
Connect PagerDuty to Anyshift so Annie can read your incidents, post acknowledgements, and automatically run root cause analysis when alerts fire.
## Overview
The PagerDuty integration gives Annie two capabilities:
* **API access** — Annie reads your incidents, acknowledges them, and leaves comments via a PagerDuty API token.
* **Real-time webhook** — When an `incident.triggered` event fires, Annie immediately starts a root cause analysis, cross-references recent infrastructure changes, and can notify Slack based on your project's [webhook investigation notification destinations](/pages/product/integration/slack#other-settings).
* **Graph evidence** — PagerDuty alerts, response incidents, services, and explicit on-call windows become read-only operational evidence for the Graph API, SDK, and CLI.
***
## Step 1: Add an API Token
1. In PagerDuty, go to **Integrations → API Access Keys → Create New API Key**.
2. Give it a descriptive name (e.g. `Anyshift-Annie`) and copy the key — it is only shown once.
3. In Anyshift, go to **Integrations → PagerDuty → New Token**, paste the key, and save.
Annie uses this token to fetch incident metadata, post acknowledgements, and add resolution comments.
***
## Step 2: Configure the Webhook
The webhook delivers real-time incident lifecycle events to Anyshift. `incident.triggered` can start an Annie investigation. Triggered, acknowledged, and resolved lifecycle changes also update stored graph evidence without making the Graph API call PagerDuty directly.
### Create the webhook in Anyshift
1. Go to **Integrations → PagerDuty → New Webhook**.
2. Enter a name (e.g. `prod-webhook`) and choose a secret key.
3. Copy the **Webhook URL** and the **Secret Key** — you need both in the next step.
### Register it in PagerDuty
1. In PagerDuty, go to **Integrations → Generic Webhooks (V3) → New Webhook**.
2. Paste the Anyshift webhook URL.
3. Under **Scope**, select the services or the full account you want Annie to monitor.
4. Enable the incident lifecycle event types you want Anyshift to retain, including triggered, acknowledged, and resolved.
5. In the **Signature Secret** field, paste the secret key you set in Anyshift.
Anyshift verifies every incoming request using HMAC-SHA256 against the secret key. Requests with missing or invalid signatures are rejected before any processing occurs.
***
## What happens when an incident fires
When Anyshift receives an `incident.triggered` event:
1. **Signature verification** — the request is validated against the shared secret. Invalid requests are dropped immediately.
2. **Deduplication** — repeated deliveries are applied idempotently, preventing duplicate graph state and duplicate RCAs.
3. **Context assembly** — Annie retrieves the last 30–60 minutes of Slack messages, recent AWS resource changes, and prior incidents with completed analyses to build a context window.
4. **Routing decision** — Annie's router decides whether to run a full RCA, start a conversational thread, or skip the incident (e.g. for known-noisy alert patterns). [Automation](/pages/product/customization/instructions) rules can override this default.
5. **Analysis delivery** — if RCA is triggered, Annie delivers a final summary with a timeline, likely root cause, and recommended remediation steps. Slack notifications for start, complete, and fail follow the destinations configured under **Integrations → Slack → Webhook investigation notifications**. PagerDuty incidents typically have no attached Slack channel, so turn on **Default notify channel** and pick a mapped channel if you want Slack updates for these webhooks.
See [Root Cause Analysis](/pages/product/root_cause_analysis) for a full walkthrough of the analysis pipeline, and [Slack](/pages/product/integration/slack#other-settings) for destination settings.
## Query PagerDuty operational evidence
The public Graph surface is provider-neutral, so the same alerting workflows can later include Datadog, New Relic, Grafana, incident.io, and other providers. There is no PagerDuty-specific CLI namespace.
```bash theme={null}
annie graph alerts --provider pagerduty --status firing
annie graph incidents --provider pagerduty --status active
annie graph incidents --provider pagerduty --responder "Jane Doe"
annie graph oncall --at now
annie graph oncall --person "Jane Doe" --at now
annie graph oncall --from 2026-08-10 --to 2026-08-17
```
`--person` accepts an exact display name, canonical person ID, or PagerDuty user ID. `--responder` accepts an exact display name, canonical person ID or email, or PagerDuty user ID. Display-name matching is case-insensitive and exact, not fuzzy.
The Graph API and SDK expose the same normalized `alerts`, `response_incidents`, and `oncall` evidence. Results distinguish canonical Anyshift identities from unresolved PagerDuty users or services instead of guessing a mapping. These read paths do not acknowledge, reassign, or resolve incidents.
### Grouped incident context
Use `incident_context` when you need one stored incident assembled as grouped hops. It reads the graph only; it never calls PagerDuty live. Require exactly one of `id` or `target`. Optional `since` bounds similar-incident history. `LIMIT` caps history rows (`OFFSET` is not supported).
Returned hops: `incident`, `alerts`, `service` (`AFFECTS` / `RESOLVES_TO`), `onCall`, `responders`, and `history`.
History cites reviewed resolution evidence only (`confirmed_fix`, `explicit_reference`, or `unknown`). Temporal proximity alone is never treated as a confirmed fix.
`annie graph triage ` includes optional `incident_context` hops for the named resource. Empty hops are omitted from triage findings.
```bash theme={null}
annie graph query "SELECT * FROM incident_context WHERE id = Q2Q5QBE019PJM5 LIMIT 10"
annie graph query "SELECT * FROM incident_context WHERE target = checkout AND since = 30d LIMIT 10"
annie graph triage checkout --since 2h
```
See [`incident_context`](/pages/product/integration/graph_query_language#incident-context) and the [Annie CLI](/pages/product/integration/cli) graph commands.
## Map PagerDuty services to canonical graph resources
`PAGERDUTY_SERVICE -[:RESOLVES_TO]->` edges are owned mappings. Topology polls never create them from display names. Name a mapping owner per project before creating any link; unowned mappings are out of scope.
### Create, update, or revoke
1. In PagerDuty, edit the service **Description**.
2. Add only standalone directive lines (no prose on the same line):
```text theme={null}
anyshift.resource_id=
anyshift.qualified_name=
```
3. Save. The next operational graph poll stamps safe properties and enqueues resolution. Unique exact hostnames (when the whole service name or URL is a hostname) may also resolve when unambiguous.
4. To update, change the directive. To revoke, delete it. Do not hand-edit Neo4j edges.
Fuzzy name matching is never used. Zero or multiple candidates stay unresolved or ambiguous.
### Demo ownership
* Owner: Platform Engineering for project **Anyshift Demo Environment**.
* Runbook: this page and `docs/pagerduty-service-resolves-to.md` in `anyshift-backend`.
* Demo service `PUXIGO8` (**Anyshift Demo - Kubernetes**) maps via an explicit directive to the checkout workload. `PK9AOSO` (**Default Service**) stays unmapped.
***
## Verify the connection
Trigger a test incident in PagerDuty. Within a few seconds Annie should start an investigation. The incident also appears in Anyshift under **Incidents**. If you enabled Slack destinations (especially **Default notify channel**), you should also see a notification in that channel.
Map the Slack channel you want as the default notify channel to the correct Anyshift project, enable **Default notify channel** on the Slack integrations page, and register your PagerDuty bot in the **Annie On-Call Registry** when you also rely on channel bots. See [Slack Integration](/pages/product/integration/slack) for setup details.
***
## Customize Annie's behavior
By default Annie decides automatically whether to run RCA or start a chat based on the incident context. You can override this per project using [Automation](/pages/product/customization/instructions):
* **Force RCA** for all incidents from a specific service.
* **Suppress** noisy or low-signal alert patterns.
* **Trigger a custom report** instead of a standard RCA.
* **Silence** Annie for specific channels or time windows.
# Sentry Integration
Source: https://docs.anyshift.io/pages/integration/sentry
Integrate with Sentry to give Annie access to your errors, releases, and performance data during incident investigations.
# Sentry Integration
Connect Sentry to give Annie visibility into application errors, releases, and performance regressions. During an incident, Annie can correlate Sentry issues with your infrastructure changes and surface the events that matter.
## Setup Guide
1. Go to the [Sentry integration page](https://app.anyshift.io/integrations/incidents-management/sentry)
2. Click **New token** to add your Sentry user auth token
3. Fill in the form fields below and click **Save Sentry token**
### 1. Display name
A human-readable label for this token (e.g. `Production Sentry`). Used only to identify the credential in the Anyshift UI.
### 2. Auth token
A Sentry **user auth token**. Generate one from your Sentry account under **User Settings > Auth Tokens > Create New Token**.
### 3. Host (optional)
Leave this field empty to use Sentry SaaS (`sentry.io`).
For self-hosted or organization-scoped instances, enter the **bare hostname** — for example `anyshift.sentry.io`. Do not include `https://`
### Required Permissions
The auth token needs the following scopes for Annie to access your Sentry data:
* `org:read` — Read organization information
* `project:read` — List and read projects
* `event:read` — Read issues and events. **Also required by the webhook below.** When a regression arrives, Anyshift uses this same token to read the issue's latest event for its **release version**, **commit SHA**, and **trace id**. Without `event:read` the regression is still recorded, but those fields stay empty and Annie cannot tie it back to the release, commit, and author that caused it.
## Sentry Webhook (real-time event ingestion)
The auth token above lets Annie **read** Sentry on demand. The **webhook** does the opposite: it lets Sentry **push** error **regressions** to Anyshift in real time, so Annie can tie each returning error back to the release and commit that caused it.
> **The webhook needs the auth token too.** The webhook delivery carries the issue, but not its release or commit. Anyshift fills those in using the **auth token from step 2** (which must include `event:read`). So configure the auth token first; a webhook with no `event:read` token records regressions without the release, commit, and author link.
The webhook is delivered by a Sentry **internal integration** that you create inside your own Sentry organization and point at a per-project URL we give you. The integration signs each delivery with its **Client Secret**, which you submit to Anyshift so we can verify it. Each Sentry org provides its own secret; we store it encrypted and use it only to verify incoming signatures.
1. On the [Sentry integration page](https://app.anyshift.io/integrations/incidents-management/sentry), find the **Webhook** section and **copy the webhook URL** shown there — it is unique to your project.
2. In Sentry, go to **Settings → Developer Settings → Custom Integrations → New Internal Integration**.
3. Name it (e.g. `Anyshift`). Under **Permissions**, set **Issue & Event** to **Read**.
4. Under **Webhooks**, enable the **issue** resource and set the **Webhook URL** to the URL you copied in step 1.
5. **Save** the integration — Sentry generates a **Client Secret**. Copy it.
6. Back in Anyshift's **Webhook** section, paste the **Client Secret** and click **Save**. The section will show as configured.
### What gets recorded
Only **regressions** are recorded — a Sentry issue that was previously resolved and has come back (`unresolved`). New or ongoing errors are **not** ingested. When a regression arrives, Anyshift stores a durable record (issue id, title, error type, level, platform, first-seen, environment) and enriches it with the immutable **release version**, **commit SHA**, and a sample **trace id** — so Annie can pivot straight into the offending change and into your APM/logs. Volatile fields (current event count, affected users, status, assignee) are read live via the Sentry API rather than stored.
## How It Works
Once connected, Annie's AI agent can:
* **Investigate errors** — Pull issue details, stack traces, and event payloads
* **Correlate with releases** — Tie errors to the release that introduced them
* **Surface performance regressions** — Identify performance issues that coincide with infrastructure or deploy changes
* **Link to your resource graph** — Map Sentry projects and services to the cloud resources they run on
**Anyshift + Sentry = faster root cause on application-layer incidents.**
# Splunk Integration
Source: https://docs.anyshift.io/pages/integration/splunk
Connect your Splunk instances to analyze logs, metrics, and correlate them with infrastructure changes for comprehensive monitoring and troubleshooting.
# Integrate with Splunk
Connect your Splunk instances to analyze logs, metrics, and correlate them with infrastructure changes for comprehensive monitoring and troubleshooting.
## Setup Guide
1. Go to the [Anyshift integrations page](https://app.anyshift.io/integrations)
2. Navigate to the Monitoring section
3. Select **Splunk**
4. Click **Add Splunk instance**
5. Enter your Splunk instance **Name**, **Host**, and **API Key**.
6. Click **Save Configuration**
## How It Works
Once connected, Anyshift automatically ingests logs and metrics from Splunk. When an incident occurs, Annie’s AI agent:
* Correlates Splunk logs and metrics with your resource graph
* Traces request chains across services
* Surfaces root causes and actionable insights
* Reduces the need to manually jump between dashboards
Ready to get started?
# VictoriaMetrics Integration
Source: https://docs.anyshift.io/pages/integration/victoriametrics
Integrate Annie with VictoriaMetrics for unified observability and intelligent investigation.
# VictoriaMetrics Integration
VictoriaMetrics integration enables Annie to ingest logs and metrics, providing a unified, intelligent view of your infrastructure's health and performance.
## Setup Guide
1. Go to the [Anyshift integrations page](https://app.anyshift.io/integrations)
2. Navigate to the Monitoring section
3. Select **VictoriaMetrics**
4. Enter your **VictoriaMetrics Instance URL**
5. Provide an **API Key** or **API Token** with read access.
6. Click **Connect**
For self-hosted instances not publicly exposed, you can use a [Cloudflare Tunnel](https://www.cloudflare.com/products/tunnel/) to securely connect your VictoriaMetrics instance to Anyshift without exposing it to the internet.
## How It Works
Once connected, Anyshift automatically ingests logs and metrics from VictoriaMetrics. When an incident occurs, Annie’s AI agent:
* Correlates VictoriaMetrics logs and metrics with your resource graph
* Traces request chains across services
* Surfaces root causes and actionable insights
* Reduces the need to manually jump between dashboards
# Integrations
Source: https://docs.anyshift.io/pages/onboarding/overview_integrations
Connect Annie to your infrastructure, monitoring, and communication tools.
Annie learns from your existing tools to build a comprehensive knowledge graph of your infrastructure.
Start with **one integration** to test Annie's capabilities, then add more as needed.
## Code & Infrastructure as Code
Anyshift maps both your application code and your Infrastructure as Code. Connect your repositories, Terraform state, and Kubernetes to power drift detection, impact analysis, and code-to-infra queries. See the [IaC overview](/pages/iac/overview) for how they fit together.
Application code, Terraform modules, and PR history
Application code, repositories, and merge requests
Terraform Cloud state and workspace management
Live cluster state via the Anyshift agent
## Cloud Infrastructure
EC2, RDS, S3, Lambda, and 100+ AWS services
Compute, Cloud SQL, GKE, and GCP resources
Azure resources (coming soon)
Beta
DNS, zones, and edge configuration
## Monitoring & Observability
Metrics, logs, APM traces, and monitors
Dashboards, alerts, and data sources
Log analysis and search
Log indexing and full-text search
Time-series metrics storage
## Analytics
DuckDB cloud analytics and queries
## Incident Management
Incidents, on-call schedules, and escalations
Incident workflows and post-mortems
Errors, releases, and performance regressions
## Knowledge Base
Pages, spaces, and team documentation
Issues, projects, and ticket history
Pages, databases, and team runbooks
Issues, projects, and team context
Cards, collections, and team knowledge
## Communication
Ask Annie questions and receive RCA results directly in Slack
## Need Another Integration?
Let us know what tools you'd like Annie to connect with
# 5-Min Quick Start
Source: https://docs.anyshift.io/pages/onboarding/quick_start
Get started with Annie in four simple steps.
## Get Annie Running in 5 Minutes
Sign up and create your Annie workspace.
Get started for free
Add at least one integration to build your knowledge graph. Start with what's easiest:
Connect a repository
Connect an account
Connect monitoring
For a quick test, connect a **dev account** first. You can add production later.
Ask Annie a question about your infrastructure:
Chat directly in the dashboard
Ask from your terminal
Mention @Annie in Slack
Use in your AI coding assistant
Connect an alerting tool so Annie automatically investigates incidents as they happen. When an alert fires, Annie cross-references recent infrastructure changes and posts a root cause analysis directly in your Slack channel — no manual trigger needed.
Auto-RCA on incident.triggered events
Auto-RCA on monitor alerts
Register alert bots for on-call monitoring
Connect incident management
To enable automatic RCA in Slack, invite **@Annie** to your alert channel and use `/register_annie_on_call ` to register your monitoring bot. See [Slack Integration](/pages/product/integration/slack) for full setup details.
## Example First Questions
Once connected, try asking Annie:
* *"What resources do I have?"*
* *"Show me the dependencies for \[service-name]"*
* *"What changed in the last 24 hours?"*
* *"Why did this alert fire?"*
# What is Anyshift?
Source: https://docs.anyshift.io/pages/overview
How Anyshift gives engineers and AI agents live production context.
Annie is your **AI-SRE**. Incidents fire, questions surface, dashboards multiply. Annie answers in seconds by correlating cloud, code, containers, and monitoring.
The Anyshift platform builds a versioned graph of your stack. Every IAM change, Helm rollout, Terraform apply, and commit lands as a node. Annie reads that graph to investigate, explain, and trace.
## Core capabilities
Automatically pinpoint root causes and get actionable fixes when incidents occur.
Query your infrastructure using natural language and get instant answers.
Track what changed, when, and understand the context of any change.
## Versioned knowledge graph
The graph spans cloud (AWS, GCP), code (Terraform, GitHub, GitLab), containers (Kubernetes), and monitoring (Datadog). Updates land in near real-time. State is queryable across the last 7 days.
## How Annie investigates
How Annie builds a unified view of your infrastructure: cloud, code, containers, and monitoring. Near real-time updates with 7-day history.
How Annie learns from every interaction and coordinates specialized agents to investigate incidents faster.
How Annie connects your declared infrastructure with what's actually running in it.
## Slack-native ingestion
Ask Annie questions directly in Slack. Mention `@Annie` with your question.
Access Annie from your AI coding assistant while you work.
Visual exploration and configuration management.
Slack is the primary surface. [PagerDuty](https://www.pagerduty.com) and [incident.io](https://incident.io) route alerts. Annie listens, investigates, and posts the root cause inline. The on-call engineer never leaves the channel.
## Integration coverage
Annie connects to **AWS**, **GCP**, **GitHub**, **GitLab**, **Terraform**, **Kubernetes**, **Datadog**, **PagerDuty**, **Incident.io**, and more. Each integration is read-only by default. Setup takes about 30 minutes per source. No in-cluster agents, no instrumentation work.
## 30-minute deployment
Set up Annie in under 10 minutes
Sign up for Anyshift
See Annie in action
Sign-up to first investigation runs about 30 minutes. Anyshift is [SOC 2 Type II](/pages/privacy_security/compliance) certified, with read-only access on cloud accounts.
# Production Graph
Source: https://docs.anyshift.io/pages/overview/knowledge_graph
How Anyshift maps and versions your infrastructure.
Annie builds a **unified knowledge graph** of your entire infrastructure, connecting cloud resources, code, containers, and monitoring data into a single, queryable model.
## What Data Annie Has Access To
| Category | What Annie Knows |
| ------------------------------ | ------------------------------------------------------------------------------------------ |
| **Cloud Infrastructure** | Resources, configurations, security policies, IAM, networking, and all their relationships |
| **Containers & Orchestration** | Workloads, services, deployments, RBAC, and cluster topology |
| **Infrastructure as Code** | Code definitions, modules, variables, and how code maps to deployed resources |
| **Application Code** | Source code, configuration files, and recent changes (can run on-prem) |
| **Deployed State** | What's actually running vs. what's defined, detecting drift and orphaned resources |
| **Observability** | What's being monitored, which dashboards exist, and alerting configurations |
Annie automatically discovers **relationships** between these categories. Ask *"Which code manages this instance?"* or *"What monitors are watching this service?"*
## How It All Connects
The knowledge graph links your infrastructure across four layers. Annie can trace relationships in any direction:
Monitors, dashboards, alerts, and hosts
Compute, storage, networking, security, and IAM
Pods, services, deployments, and config maps
Modules, resources, variables, and state
Annie can trace from any layer to any other. Ask *"What code deployed this pod?"* or *"Which monitors watch resources in this module?"*
## How Fresh is the Data?
Infrastructure changes are reflected within seconds
Query the state of any resource at any point in the past week (extendable)
See exactly what changed, when, and in what order
Ask Annie *"What changed in production in the last 2 hours?"* or *"Show me the history of this security group since yesterday."*
## Live Observability Queries
For logs, metrics, and traces, Annie **queries your monitoring tools live**. She doesn't duplicate your observability data.
When investigating an incident, Annie calls your Datadog, Grafana, or other monitoring APIs in real-time, correlating what she finds with infrastructure changes from the knowledge graph.
* **Always fresh:** No sync delays, you get the latest data
* **No duplication:** Your observability data stays where it is
* **Full access:** Annie uses your existing queries and dashboards
## Related
How Annie learns from the graph and coordinates specialized agents.
Code → state → live, and how Annie draws it as a diagram.
Query the graph in plain language.
Walk the graph backwards through the last 7 days.
# Memory and Agents
Source: https://docs.anyshift.io/pages/overview/memory_agents
How Annie learns from every interaction and coordinates specialized agents
Annie isn't just a search engine. She's an **intelligent system** that learns from every interaction and coordinates specialized agents to solve complex problems.
## Multi-Agent Investigation
When Annie investigates an incident, she coordinates multiple specialists working in parallel:
| Agent | Role |
| ------------------------ | --------------------------------------------------------------- |
| **Observability Agent** | Searches logs, metrics, and traces across your monitoring tools |
| **Infrastructure Agent** | Explores topology, dependencies, and recent changes |
| **Code Agent** | Examines source code, configuration files, and recent commits |
These agents share findings with each other, building a complete picture faster than any single investigation could.
* **Parallel investigation:** Multiple agents work simultaneously, dramatically reducing investigation time
* **Deep expertise:** Each agent is optimized for its domain
* **Intelligent coordination:** Agents share context and build on each other's findings
* **Adaptive depth:** Simple questions get quick answers; complex incidents get thorough investigation
## How Annie Learns
After each investigation, Annie:
1. **Reflects** on what worked and what patterns emerged
2. **Curates** learnings into structured knowledge for future use
3. **Applies** relevant context automatically in future investigations
This means Annie remembers things like:
* *"Last time this alert fired, the issue was a security group change"*
* *"Database connection errors below 5/min are normal noise for this service"*
* *"The payment-service depends on Redis in us-east-1"*
## What Annie Remembers
Service relationships, deployment topologies, dependencies
Normal vs anomaly thresholds, error signatures, warning patterns
Effective queries, useful metrics, dashboard locations
Which services power which features, team ownership, critical paths
## Custom Knowledge
Add knowledge Annie can't learn automatically: team conventions, business context, vendor specifics, escalation procedures.
Configure custom instructions and knowledge for your organization
## Related
The unified model of your stack that Annie's agents investigate.
See the multi-agent investigation in action on a live incident.
# Compliance & Certifications
Source: https://docs.anyshift.io/pages/privacy_security/compliance
Our security standards and compliance certifications
## Trust Portal
For comprehensive, real-time security and compliance information, visit our dedicated **[Trust Portal](https://trust.anyshift.io/)**.
This portal provides transparent access to our security posture, compliance status, and operational metrics that demonstrate our commitment to enterprise-grade security standards.
## Security Standards
### SOC 2 Compliance
We are SOC 2 compliant, upholding rigorous standards to ensure:
* **Security**: Protection against unauthorized access
* **Availability**: System reliability and availability
* **Processing Integrity**: Accurate, timely processing
* **Confidentiality**: Information designated as confidential is protected
* **Privacy**: Personal information is collected, used, retained, disclosed, and disposed of properly
## Infrastructure Security
### Cloud Infrastructure
* **AWS Security Standards**
* Regular security assessments
* Automated security monitoring
* Infrastructure-as-code security checks
### Network Security
* **Access Controls**
* Multi-factor authentication
* Role-based access control
## Security Operations
### Continuous Monitoring
* Automated secret scanning in code repositories
* Advanced static code analysis for security vulnerabilities
* Continuous dependency security scanning
* Early detection of potential security issues
## Security Measures
### Data Security
* **Storage**
* Encrypted storage
* Data isolation
* Retention policies
* **Transfer**
* Secure API endpoints
* Certificate management
* Traffic monitoring
## External Providers
For information about external AI providers and models used by Anyshift, please see our [External Providers](/pages/privacy_security/external_providers) page.
## Contact Us
Have questions about security?
Schedule a call to discuss security
Visit our trust portal for detailed security information
# External Providers
Source: https://docs.anyshift.io/pages/privacy_security/external_providers
Information about external AI providers and models used by Anyshift
# External Providers
## AI Models and Providers
In the interest of transparency, Anyshift discloses the external AI models and providers integrated into our platform. We maintain strict data protection standards and agreements with all external providers to ensure your data remains secure and private.
### Claude 4 by Anthropic
**Model**: Claude 4
**Provider**: Anthropic\
**Usage**: Powers our AI Assistant "Annie" for infrastructure analysis and recommendations
#### Data Protection and Compliance
* **Zero Data Retention**: Anyshift has a zero data retention agreement with Anthropic, ensuring that your data is not stored or used for model training
* **Compliance**: Anthropic maintains enterprise-grade security standards and compliance certifications
* **Privacy Policy**: Detailed information about Anthropic's privacy practices can be found in their [privacy policy](https://www.anthropic.com/privacy)
#### Zero Data Retention Agreement
For complete transparency regarding our data handling practices with Anthropic, please refer to their official documentation:
[Zero Data Retention Policy](https://privacy.anthropic.com/en/articles/8956058-i-have-a-zero-data-retention-agreement-with-anthropic-what-products-does-it-apply-to)
This agreement ensures that:
* Your data is not retained by Anthropic after processing
* Your information is not used to train or improve AI models
* Complete data isolation between customer interactions
## Data Processing Principles
### Our Commitments
* **Transparency**: Full disclosure of external providers and their data handling practices
* **Security**: All external integrations maintain enterprise-grade security standards
* **Privacy**: Your data is never used for model training or stored by external providers
* **Control**: You maintain full control over your data and can review our provider agreements
### Provider Selection Criteria
We carefully evaluate all external AI providers based on:
* Security and compliance certifications
* Data protection policies
* Zero data retention capabilities
* Enterprise-grade service level agreements
## Contact
For questions about our external providers or data handling practices:
Schedule a call to discuss security and external providers
Visit our trust portal for detailed security information
# FAQ
Source: https://docs.anyshift.io/pages/privacy_security/faq
Frequently asked questions about data protection and privacy
## Does Anyshift have access to my infrastructure data?
Anyshift requires limited, permission-controlled access to your infrastructure to provide insights. We do not use your data to train AI models.
For more details about our AI providers and data handling practices, see our [External Providers](/pages/privacy_security/external_providers) page.
## What cloud access permissions does Anyshift require?
Anyshift requires read-only access to your cloud resources. We recommend using role-based access with least privilege. For Kubernetes, we use a lightweight agent with minimal permissions. For GitHub/GitLab, you can specify which repositories Anyshift can access.
Policies can be even more fine-grained than read-only. For example, you can grant permissions that only allow listing of instances, as described in our [AWS integration documentation](/pages/integration/aws).
## Does Anyshift have access to the secrets in my Terraform states?
Secrets in your Terraform state files can be anonymized before Anyshift ingests them. With our optional anonymization pipeline, a Lambda function you control removes sensitive data, ensuring secrets are never exposed to Anyshift. The Lambda code is available for audit.
## How does Anyshift isolate customer data?
We use strict data isolation, strong access controls, and encryption in transit and at rest to ensure no customer can access another customer's data.
## How does Anyshift handle AI and data sovereignty?
We have agreements with our AI providers to prevent your data from being used for model training. For strict data residency needs, we offer deployment options that keep sensitive data within your infrastructure.
Learn more about our specific AI provider agreements and zero data retention policies on our [External Providers](/pages/privacy_security/external_providers) page.
## What are Anyshift's outbound IP addresses?
We publish the list of IP addresses used by Anyshift to connect to your infrastructure. If your organization uses firewall rules or IP allowlists, see our [Network Requirements](/pages/privacy_security/network) page for the full list and a downloadable JSON file.
## Does Anyshift support on-premises deployment?
Yes, for customers with strict data residency or IP protection requirements, we offer deployment options including agents that run in your VPC to preserve application code confidentiality. These options are available as part of our Enterprise plan.
For more details, contact us at [contact@anyshift.io](mailto:contact@anyshift.io).
## Is Anyshift SOC 2 compliant?
Yes, Anyshift is SOC 2 compliant, ensuring the highest standards of security and data protection.
For comprehensive information about our security standards and compliance certifications, visit our [Compliance & Certifications](/pages/privacy_security/compliance) page.
## I have more questions about security.
Schedule a call to discuss security
Visit our trust portal for detailed security information
***
### Cookie Policy
Our website uses cookies to enhance your experience and provide analytics:
* Essential cookies for core functionality
* Analytics cookies to improve our service
* Full cookie policy available at [anyshift.io/cookies](https://www.anyshift.io/cookies)
# Multi Factor Authentication (MFA)
Source: https://docs.anyshift.io/pages/privacy_security/mfa
How to set up and use Multi Factor Authentication in Anyshift
## Setting Up MFA
To enroll a new device for Multi Factor Authentication (MFA) in Anyshift, follow these steps:
Log in to your Anyshift account and navigate to the **Profile** page.
Click on **Enable MFA** and choose your preferred method. Currently, only TOTP (authenticator apps) is supported.
Scan the QR code with your authenticator app and enter the verification code to confirm.
You will be required to enter a verification code from your authenticator app each time you log in.
## Enforcing MFA for Your Organization (Org Admins Only)
Organization admins can require all members to use MFA across the entire organization.
You must have MFA enabled on your own account before you can enforce it for others.
Navigate to the **Settings** page.
Under the **Security** section, toggle **Require MFA for all organization members**. This applies to all projects in the organization.
Once enforced, every member and admin in your organization will be required to set up and use MFA to access any project.
MFA enforcement can be combined with [SSO](/pages/privacy_security/sso) for additional security.
# Network Requirements
Source: https://docs.anyshift.io/pages/privacy_security/network
Outbound IP addresses and network configuration for Anyshift
## Outbound IP Addresses
If your organization uses firewall rules or IP allowlists, you may need to allow traffic from Anyshift's outbound IP addresses.
The following IPs are used by Anyshift to connect to your infrastructure:
| IP Address |
| ------------- |
| 52.73.42.120 |
| 18.211.221.82 |
| 18.209.252.79 |
You can download the list as a JSON file for automation: [outbound-ips.json](/outbound-ips.json)
## Questions?
If you have questions about network configuration, contact us at [contact@anyshift.io](mailto:contact@anyshift.io).
# Single Sign-On (SSO)
Source: https://docs.anyshift.io/pages/privacy_security/sso
How to configure SSO for your Anyshift organization
## What SSO Provides
Single Sign-On lets your team sign in to Anyshift using your existing identity provider. This centralizes authentication and enforces your organization's login policies.
## Supported Providers
Anyshift supports SSO with any SAML or OIDC-compatible identity provider, including:
* Okta
* Azure AD (Microsoft Entra ID)
* Google Workspace
## Setting Up SSO
Organization admins can configure SSO from the **Settings** page under the **Security** section.
Choose your provider from the list or select a custom SAML/OIDC configuration.
Follow the guided setup to exchange metadata between Anyshift and your identity provider.
Verify that authentication works correctly before enabling SSO for your organization.
Activate SSO for your organization. Users with your company's email domain will sign in via your identity provider.
## Sign-In Flows
Anyshift supports two SSO sign-in methods:
* **SP-initiated** — users go to the Anyshift sign-in page, enter their email, and are redirected to your identity provider.
* **IdP-initiated** — users click the Anyshift app directly from their identity provider's portal (e.g., Okta dashboard) and are signed in automatically.
Both flows are supported out of the box once SSO is configured.
## User Provisioning
By default, users must be invited to your organization before they can sign in with SSO. Organization admins can change this behavior in the SSO settings.
### Require Invitation (default)
Users must be invited by an admin before they can sign in. If an uninvited user tries to SSO, they will see a message asking them to contact their administrator.
### Auto-Provisioning
When enabled, any user who authenticates through your identity provider is automatically added to the organization as a **member**. No invitation needed.
Auto-provisioned users are:
* Created with **member** role (not admin)
* Assigned to a default project if one is configured (see [Default Project Assignment](#default-project-assignment))
* Immediately active — no email verification step required
To enable auto-provisioning, go to **Settings > Security > SSO** and select **Auto-provision users** under User Provisioning.
## Domain Management
Organization admins can manage email domains from the **Settings > Security > Domains** section. This section shows all email domains present in your organization (based on your members' email addresses).
### Claiming a Domain
When you claim a domain, new users with that email domain cannot create their own separate accounts. Depending on your SSO configuration:
* **SSO with auto-provisioning** — new users with that domain will be redirected to SSO and automatically provisioned into your organization.
* **SSO without auto-provisioning** — new users with that domain must be invited before they can sign in via SSO.
* **No SSO** — new users with that domain must be invited to join your organization.
Consumer email domains (gmail.com, outlook.com, yahoo.com, etc.) cannot be claimed.
### Unclaiming a Domain
Unclaiming a domain allows users with that email to sign up independently again. Existing members are not affected.
## Default Project Assignment
For organizations with multiple projects, admins can configure which project auto-provisioned users are assigned to.
### How It Works
Default project assignment is configured in the **Domains** section of the Security settings. You can set:
* **Org-wide default** — all auto-provisioned users are assigned to this project regardless of their email domain.
* **Per-domain defaults** — users from specific email domains are assigned to specific projects. This is useful when different teams use different email domains.
### Priority Order
When a new user is auto-provisioned, the system determines their project assignment in this order:
1. **Domain-specific default** — if a default project is set for the user's email domain, they are assigned to that project.
2. **Org-wide default** — if no domain-specific default exists but an org-wide default is set, they are assigned to that project.
3. **Single-project org** — if the organization has only one project and no defaults are configured, the user is automatically assigned to it.
4. **No assignment** — if none of the above apply, the user gets organization membership only with no project assignment. An admin must manually add them to a project.
## Important Notes
* **Email matching is case-insensitive.** The email in your identity provider is normalized to lowercase.
* SSO can be combined with [MFA enforcement](/pages/privacy_security/mfa) for additional security.
* Disabling SSO reverts all users to email/password sign-in.
* Auto-provisioned users can be promoted to admin after joining.
# Explore & Ask
Source: https://docs.anyshift.io/pages/product/annie_knowledge
Ask about resources, dependencies, access, and changes across your stack.
## Ask in plain English
Ask in plain English, get an answer in seconds. Annie understands context. Ask *"Why can't I access this RDS?"* and she traces security groups, IAM, VPC config, and network ACLs to the actual blocker.
Answers run on a [versioned knowledge graph](/pages/overview/knowledge_graph) spanning cloud, code, containers, and monitoring. It updates in near real-time and stays queryable across the last 7 days. Reach Annie in [Slack](/pages/product/integration/slack), from your IDE via [Annie Remote MCP](/pages/product/integration/remote_mcp), or the [web dashboard](https://app.anyshift.io/).
## Connected data sources
| Source | Examples | What Annie knows |
| ------------------- | -------------- | ------------------------------------------- |
| **Cloud** | AWS, GCP | Live resource state, configs, relationships |
| **IaC** | GitHub, GitLab | Terraform modules, definitions, variables |
| **Terraform state** | S3, HCP | Deployed state, outputs, dependencies |
| **Monitoring** | Datadog | Monitors, dashboards, host mappings |
| **Containers** | Kubernetes | Pods, deployments, services, RBAC |
## What you can ask
Annie's real power is correlating across these sources. Expand a workflow for example questions:
* *"Show me EC2 instances in AWS that aren't in Terraform"* (find orphaned resources)
* *"Which Datadog monitors are watching this EC2 instance?"* (link cloud to monitoring)
* *"What Terraform module manages this Kubernetes deployment?"* (trace code to containers)
* *"What are our core services and how are they connected?"*
* *"Who is responsible for the payment service?"*
* *"Draw a map of our cloud architecture"*
* *"What changed in production in the last 2 hours?"*
* *"Which services depend on the database that's having issues?"*
* *"Why can't the API reach the database?"*
* *"What would be affected if I update this security group?"*
* *"List all resources that depend on this VPC"*
* *"Show me the blast radius for this change"*
* *"List all S3 buckets with public access"*
* *"Which IAM roles have admin privileges but no MFA?"*
* *"Find security groups allowing 0.0.0.0/0 on port 22"*
* *"Which EC2 instances aren't managed by Terraform?"*
* *"Find resources without cost-center tags"*
* *"List idle resources in staging"*
## Related
The versioned model behind every answer.
Ask Annie to draw the topology she just described.
The same graph, pointed at a live incident.
Save a question you ask often as a recurring report.
# Customization
Source: https://docs.anyshift.io/pages/product/customization
Customize Annie to match your team workflows with automation, custom knowledge, personas, and effort mode.
Annie can be customized to better fit your team's specific needs.
Define automation rules that control what Annie does with each Slack message: investigate, chat, wait for a human, or stay silent. Per-sender and per-channel fallbacks keep subscribed bots from accidentally triggering RCAs.
Teach Annie about your specific infrastructure, patterns, and team conventions.
Control Annie's tone and depth per team member — from terse SRE to patient tutor.
Trade speed against depth — from Quick everyday answers to Deep root-cause reasoning.
# Effort Mode
Source: https://docs.anyshift.io/pages/product/customization/effort_mode
Control how thoroughly Annie reasons — trading speed against depth and quality.
## Overview
Not every question needs the same depth. A quick lookup should be fast. A hard root-cause investigation deserves Annie's most thorough reasoning, even if it takes longer.
**Effort Mode** lets you control that trade-off. It adjusts which model Annie uses and how much it reasons before answering — without changing what Annie can do.
## The Four Modes
Claude Haiku with low reasoning effort. Annie's fastest mode — optimized for speed and cost.
Best for: **simple lookups, quick confirmations, lightweight chat**
Claude Sonnet with low reasoning effort. The fastest mode.
**Recommended.** For most tasks this strikes the right balance between effort and result — you'll rarely need more.
Best for: **everyday questions, quick lookups, simple chat**
Claude Opus with medium reasoning effort — a more capable model and more thinking than Quick. A middle ground between speed and depth.
Best for: **most investigations and multi-step questions**
Claude Opus with high reasoning effort. Annie's most thorough mode — the most capable model reasoning as much as the task needs. Slower, but the highest-quality answers.
Best for: **hard root-cause analysis, complex or ambiguous problems**
Effort Mode applies to both chat and investigations (RCA).
## Setting the Team Default
The team default is set per project in [**Settings → Projects & Teams**](https://app.anyshift.io/settings), just above the team members table. It applies to every request unless overridden for a specific message.
When no default has been set, Annie uses **Quick**.
Any project member can see the default; admins can change it.
## Overriding Per Message
Next to the chat input there is a **Mode** dropdown. Choosing a mode there applies it to that message only — it takes priority over the team default. Leave it on **default** to use the team setting.
This would let you, for example, keep a fast default for routine work and reach for **Deep** only on the questions that need it.
## Get Started
Sign up for Anyshift
See Annie in action
# Annie Automation
Source: https://docs.anyshift.io/pages/product/customization/instructions
Teach Annie how to act on her own: route Slack messages with structured rules, per-sender fallbacks, and a fixed default behavior.
## Overview
Annie Automation (URL: `/automation`, formerly `/instructions`) is where you teach Annie how to act on her own. When a message lands in Slack from a tracked source, Annie runs through your rules top-to-bottom and picks an action: a quick chat reply, a full Root-Cause Analysis (RCA), waiting for a human, or staying silent.
The page is divided into three scopes:
* **Message routing** (live today): the rules engine described in this doc.
* **Scheduled tasks** (coming soon): standups, weekly reports, on-call handoffs.
* **Custom skills** (coming soon): ad-hoc skills triggered by `@Annie, do X`.
## How a message flows through Annie
```
Message lands → Skip duplicates? → Match a rule? → Default behavior
```
1. **Message lands**: a tracked Slack identity posts in a tracked channel, or a teammate `@`-mentions Annie.
2. **Skip duplicates**: if the same alert fired recently (within the duplicate-detection window), Annie links to the existing investigation instead of starting a new one.
3. **Match a rule**: Annie evaluates rules top-to-bottom; the first matching rule wins.
4. **Default behavior**: if no rule matches, Annie reads the message and picks the right response based on context.
## Default behavior
Annie's default behavior is **fixed as "Annie decides"**: when no rule matches, Annie reads the message and chooses between a quick chat reply, a deeper investigation, or staying silent based on context. This is intentionally not configurable. To get a different action for specific cases, **add a rule below** the default behavior card.
## Rules
A rule tells Annie what to do for a specific message. Each rule is built from four steps:
> **WHEN** a Slack message matches **WHO**, **WHAT**, and **WHERE** below, Annie does what you set in **THEN**.
| Step | Field | Description | Empty means |
| ------- | --------------------------- | ----------------------------------------------------------- | -------------------- |
| ① WHO | `source_subscription_ids` | The Slack user or bot Annie should listen to. Multi-select. | Anyone. |
| ② WHAT | `trigger_condition` | A keyword, phrase, or natural-language pattern. | Any message content. |
| ③ WHERE | `slack_channel_mapping_ids` | The Slack channel(s) Annie should watch. Multi-select. | Any channel. |
| ④ THEN | `action_type` | What Annie should do when the message above arrives. | Required. |
Below the stepper, a **live preview chip** reads the values back as a sentence ("Annie will run a full investigation when PagerDuty posts severity:critical in #oncall") so you can sanity-check the rule before saving.
### Action types
| Action | What Annie does | Best for |
| --------------------------------- | -------------------------------------------------------- | ------------------------------------------- |
| **Annie decides** | Reads the message and picks chat, RCA, or silence. | General-purpose rules. |
| **Run investigation (RCA)** | Triggers a full RCA against your connected integrations. | Alerts that always need deep investigation. |
| **Reply with a short answer** | Conversational reply, no RCA. | Validation questions, quick lookups. |
| **Wait for human to trigger RCA** | Posts a "Start investigation" button in the thread. | Low-priority alerts; human-in-the-loop. |
| **Stay silent** | Annie ignores the message entirely. | Known noise, test alerts. |
| **Generate a custom report** | Renders one of your saved report definitions. | Pre-defined investigation playbooks. |
### Templates
The rules section opens with three starter recipes you can click to pre-fill the editor:
* **Auto-investigate critical pages** — `severity:critical` → Run RCA.
* **Mute a noisy bot** — Stay silent. Pick the bot in WHO.
* **Manual RCA in a noisy channel** — Wait for human. Pick the channel in WHERE.
Templates only seed the action and trigger. You fill WHO and WHERE for your project before saving.
### Reordering rules
Each row has a drag handle on the left (grip icon) and ↑/↓ arrows on the right. Reordering matters: Annie evaluates top-to-bottom, first match wins.
### Duplicate
The copy icon on each row opens a new-rule editor pre-filled with that rule's WHO/WHAT/WHERE/THEN. Tweak and save. Useful for forking a rule for a near-identical case without retyping.
## Grouped views
The Rules section has a **3-way pivot** in the top-right (Sender / Channel / Flat).
* **Sender**: one card per subscribed Slack identity. Each card shows that sender's rules and a **per-group fallback dropdown** (see below). A multi-select rule scoped to several senders appears under each of them.
* **Channel**: one card per Slack channel mapping, same shape.
* **Flat**: the linear list, drag-sortable, ordered by `order_index`.
Default pivot is computed from the project's rule shape: clusters of rules sharing a sender → Sender; clusters sharing a channel → Channel; small or all-distinct → Flat. Your override is remembered per project, per user.
### Per-group fallback (the "Jean-Marc fix")
When you subscribe a bot to Annie, every message from that bot is processed automatically. Without the per-group fallback, any message from that bot that didn't match a rule would fall through to Annie's default behavior — sometimes that's the right call, often it's not.
The per-group fallback closes that loop. Each sender card has an **inline dropdown** at the bottom:
> Otherwise (no rule above matched), Annie will \[stay silent ▾]
Subscribed senders default to **stay silent**. Mention-only senders default to **Annie decides**. Channels default to **stay silent**. The dropdown writes through to `PUT /custom-instructions/{projectId}/group-fallbacks/{kind}/{scopeId}` immediately.
Behaviour at evaluation time, when no rule matches:
1. Per-sender override wins if set.
2. Per-channel override wins next.
3. For subscribed senders without an override row, Annie applies the implicit `silent` default (the retroactive fix).
4. Otherwise, Annie's global default behavior fires.
### "Anyone" and "Any channel" rules
Rules with WHO empty (Anyone) or WHERE empty (Any channel) live under a synthetic group at the bottom of each grouped view. Their fallback dropdown is hidden — they already match every message that doesn't get caught by a scoped group above.
## Slack identities
Below the rules, the Slack identities table lists every user and bot Annie can route on. Each row has a status pill:
* **Subscribed**: Annie processes every message from this identity automatically, following any matching rule and the sender-fallback when nothing matches. This is the right setting for alerting bots (PagerDuty, Datadog, Grafana, Amazon Q).
* **Mention-only**: Annie only processes messages from this identity when they tag `@Annie`. This is the default for human teammates so Annie doesn't reply to every sentence.
Click the pill to flip it; the rules that target the identity stay in place. Use **Add identity** to register a Slack user or bot that hasn't been seen yet — automation rules can target any identity, subscribed or not.
## Duplicate alert detection
A time window for suppressing repeated alerts. When enabled, Annie detects if the same alert was already processed recently and links to the existing investigation instead of starting a new one. Configurable per project from the same page.
## Examples
A common pattern for teams using Amazon Q to forward AWS Health Events to Slack:
1. Subscribe Amazon Q from the Slack identities table.
2. Switch the Rules pivot to **Sender** so Amazon Q has its own card.
3. Add one rule inside the card: `WHO=Amazon Q · WHAT=AWS Health Event with RDS · THEN=Reply with a short answer` with instructions: "Validate whether the reported service had a real failure".
4. Leave the per-group fallback at **Stay silent** (the default for subscribed bots).
Annie validates RDS health events and stays silent on everything else from Amazon Q.
`WHO=anyone · WHAT=Alert contains "RDS" or "database" or "postgres" · WHERE=any channel · THEN=Run Investigation`
Investigation instructions:
* Check recent schema migrations in the last 24h
* Review connection pool metrics and active connections
* Look for long-running queries (>30s)
* Check for recent deployments that might have changed queries
`WHO=PagerDuty · WHAT=PagerDuty priority not P1 or P2 · THEN=Wait for human to trigger RCA`
Annie posts a "Start investigation" button instead of investigating automatically. Team members click to investigate when they have time.
`WHO=anyone · WHAT=Alert tags contain "test" · THEN=Stay silent`
Annie ignores test alerts entirely.
For teams that have a single workflow bot forwarding multiple alert kinds:
1. Subscribe the bot.
2. Switch the Rules pivot to **Sender**.
3. Inside the bot's card, add focused rules ordered top-to-bottom (each with `WHO=that bot`).
4. Set the card's per-group fallback to **Stay silent** so anything that didn't match falls quiet instead of triggering Annie's default behavior.
This is the structural fix that prevents "I added a P1 rule but Annie keeps RCA-ing every message from this bot".
## Get Started
Sign up for Anyshift
See Annie Automation in action
# Custom Knowledge
Source: https://docs.anyshift.io/pages/product/customization/knowledge
Teach Annie about your specific infrastructure, patterns, and team conventions using a three-tier knowledge system.
## Overview
Annie automatically learns from your connected integrations (AWS, Terraform, Datadog, etc.), but some knowledge isn't available in those systems — team conventions, business context, runbook locations, on-call contacts, and tribal knowledge.
**Custom Knowledge** lets you add this context so Annie can provide more accurate and relevant responses. It works in three tiers, depending on the size and nature of the information.
## Three Tiers of Knowledge
Short pointers and guidelines injected directly into Annie's context. Best for concise rules, team conventions, and quick references.
**20,000 character limit** across all entries.
Larger structured data that Annie can query on demand. Not injected into context — written to Annie's working directory at the start of each conversation.
CSV with headers and JSON are the recommended formats. **Up to 20 dumps per project.**
For full documentation libraries, connect Annie to your knowledge platform. Annie searches these on demand during investigations.
Examples: [Jira](/pages/integration/jira), [Confluence](/pages/integration/confluence), [Guru](/pages/integration/guru).
## Knowledge Entries
Knowledge entries are injected directly into Annie's context at the start of every conversation. Because they consume context space, they should be kept concise — think pointers and guidelines rather than full documents.
**Best for:**
* Team conventions and naming standards
* Key contacts and escalation paths
* Quick reference rules (e.g., "always check Redis before the database")
* Links to important dashboards or runbooks
### Examples
```markdown theme={null}
# Service Ownership
- Payment service: @payments-team, escalate to payments-oncall@company.com
- Auth service: @platform-team, security issues go to security@company.com
- API Gateway: @infra-team
```
```markdown theme={null}
# Debugging Conventions
- Always check Datadog dashboard "Service Overview" first
- For database issues: check pg_stat_statements before scaling
- Redis issues: check eviction rate, not just memory usage
- Stripe timeouts: check Stripe status page before investigating internally
```
```markdown theme={null}
# Incident Severity
- SEV1: Customer-facing outage, all hands. Escalate to VP after 1 hour.
- SEV2: Degraded service, on-call + team lead. Postmortem within 48h.
- SEV3: Minor issue, on-call only.
- Comms channel: #incidents (Slack), war room auto-created as #incident-{id}
```
## Knowledge Dumps
Knowledge dumps are for larger structured data that Annie can read on demand. They are **not** injected into Annie's context — instead, they are written as files to Annie's working directory. Annie's context includes a summary of each dump (format, size, columns) so it knows what's available and can query the files using `jq` when needed.
**Best for:**
* Service mapping tables
* On-call rosters
* Environment configuration indexes
* Resource inventories
### Recommended Formats
**CSV with headers** and **JSON** are the recommended formats. Annie automatically detects the format and converts CSVs to JSONL for efficient querying.
### Examples
```csv theme={null}
service_name,owner,tier,environment,dependencies,dashboard
payment-api,@payments-team,critical,prod,stripe;redis;dynamodb,Payment Overview
auth-service,@platform-team,critical,prod,auth0;redis;postgres,Auth Health
order-processor,@commerce-team,high,prod,postgres;sqs;payment-api,Order Pipeline
notification-svc,@platform-team,medium,prod,ses;sqs,Notifications
```
```csv theme={null}
team,primary,secondary,escalation_contact,schedule_link
payments,alice@company.com,bob@company.com,payments-oncall@company.com,https://pagerduty.com/schedules/payments
platform,charlie@company.com,diana@company.com,platform-lead@company.com,https://pagerduty.com/schedules/platform
data,eve@company.com,frank@company.com,data-oncall@company.com,https://pagerduty.com/schedules/data
```
```json theme={null}
{
"environments": {
"prod": {
"region": "us-east-1",
"account_id": "123456789",
"vpc_id": "vpc-abc123",
"maintenance_window": "Sundays 2-4 AM UTC"
},
"staging": {
"region": "us-east-1",
"account_id": "987654321",
"vpc_id": "vpc-def456",
"maintenance_window": "No restrictions"
}
}
}
```
## Knowledge Platforms
For full documentation libraries that are too large for knowledge entries or dumps, connect Annie to your knowledge platform. Annie searches these on demand during investigations.
Search tickets, issues, and project documentation.
Search wiki pages, runbooks, and team documentation.
Search verified knowledge cards and team documentation.
## Get Started
Sign up for Anyshift
See Custom Knowledge in action
# Personas
Source: https://docs.anyshift.io/pages/product/customization/personas
Control how Annie communicates — its tone, depth, and assumptions — for different team members.
## Overview
Different team members need different things from Annie. An SRE wants terse, action-oriented answers. A CSM needs business-impact summaries. A junior engineer benefits from step-by-step explanations.
**Personas** let you control how Annie communicates by assigning behavioral profiles to team members. Each persona adjusts Annie's tone, depth, and assumptions without changing what it can do.
## Built-in Personas
Annie ships with four personas ready to use:
Conversational and direct. Assumes the user is a fellow SRE with deep technical knowledge. Provides brief answers, skips basic definitions, and suggests concrete next actions.
Best for: **SREs, DevOps engineers, platform engineers**
Focused exclusively on finding and presenting evidence. Cites every claim with specific data sources. Uses bullet points and structured data instead of prose. Does not speculate beyond what the evidence shows.
Best for: **Incident investigations, compliance reviews, audit trails**
Patient and thorough. Assumes the user is learning the system. Explains concepts step by step, defines technical terms, and provides context about why things work the way they do.
Best for: **Junior engineers, new team members, onboarding**
Non-technical and business-focused. Translates technical details into business language. Focuses on who is affected, what the customer-facing symptoms are, and what the resolution status is.
Best for: **Customer Success Managers, account managers, sales engineers**
## Custom Personas
Need something more specific? Create custom personas tailored to your team's unique roles and workflows.
Navigate to **Annie → Personas** in the sidebar to create custom personas with:
* **Label** — A short name (up to 50 characters), e.g. "Lean SRE" or "Sales Engineer"
* **Instruction** — Behavioral instructions for Annie (up to 1000 characters) describing the tone, depth, and assumptions to use
Custom personas appear alongside built-in ones in all persona selection dropdowns.
### Example Custom Personas
```
Focus on speed and actionability. Skip all context and explanation.
Give me the shortest possible answer: what's broken, what metric
confirms it, and what's the fix. One sentence per point. If you
need to run a tool, just do it — don't ask permission.
```
```
Assist with pre-sales technical discussions. Frame infrastructure
capabilities as business outcomes (uptime, cost savings, compliance).
When reviewing incidents, emphasize MTTR and preventive measures.
Keep language accessible to technical buyers — avoid deep CLI
commands or config details unless asked.
```
## Assigning Personas
Personas are assigned per project in **Settings → Projects & Teams**:
* **Default persona** — Applied when a team member has no individual assignment, or when the user can't be identified (e.g., unlinked Slack users). Set this above the team members table.
* **Per-member persona** — Override the default for specific team members using the Persona column in the members table.
Members can change their own persona. Admins can change anyone's persona.
### Slack Users
Annie identifies Slack users through the Slack user mapping. When a Slack user is linked to their Anyshift account, their assigned persona is applied automatically. Unlinked Slack users receive the project's default persona.
### Per-message override
Next to the chat input there is a **Persona** dropdown. Choosing a persona there applies it to that message only — it takes priority over your assigned persona and the project default. Leave it on **default** to use the persona assigned to you.
## Personas in Proactive Findings
Personas don't only shape conversations — they also set the voice of automated **[Proactive Findings](/pages/product/proactive_annie)**. The persona chosen for a project decides how the report's findings, risks, and recommendations are written: CSM Annie turns it into a business-focused summary, Evidence Annie into a terse, evidence-led one, and a custom persona into whatever voice you defined.
Set it from [**Proactive Findings**](https://app.anyshift.io/proactive) — the **Report persona** control lists every built-in and custom persona. The choice applies to the whole project's Proactive Findings; leave it unset to keep Annie's default voice.
This applies to **Proactive Findings only**. For [custom reports](/pages/product/reports), tone and framing are part of the report definition you author at creation time — not a persona.
## Get Started
Sign up for Anyshift
See Personas in action
# Alert noise
Source: https://docs.anyshift.io/pages/product/graph-api/alert-noise
Use the live production graph to rank noisy monitors and find what is flooding on-call.
Alert volume alone does not tell you which monitor creates the most operational drag. The graph connects alerts to the production resources, workloads, and services behind them.
## Use it to
* Rank monitors by repeated alert activity
* Connect each alert to its affected services and workloads
* Distinguish broad operational risk from one noisy signal
* Feed the same governed context to on-call tooling and agents
Instead of tuning alerts from disconnected dashboards, SRE teams can see which signals matter in the context of the system they protect.
Open the complete video showcase.
# Backstage
Source: https://docs.anyshift.io/pages/product/graph-api/backstage
Power Backstage service pages with live dependencies, monitors, changes, and blast radius.
Most service catalogs start drifting as soon as they are curated. The Anyshift Graph API gives Backstage a live view of production instead.
## What appears on the service page
* Current upstream and downstream dependencies
* Blast radius derived from the live topology
* Active monitors attached to the resources they watch
* Recent changes that may explain an alert
* C4 diagrams generated from production
The platform team gets its curation time back, while engineers see the system as it exists today.
Install and configure the integration.
Open the complete Graph API showcase.
# Configuration churn
Source: https://docs.anyshift.io/pages/product/graph-api/configuration-churn
Trace repeated production configuration changes across Kubernetes, CI, operators, and IaC.
Production configuration can change through kubectl edits, CI pipelines, operators, Terraform, and hotfixes. Those paths are difficult to correlate when the evidence is split across audit logs.
## One query, one ranked answer
Use the graph to count changes, rank the resources with the most churn, and trace the result back to the relevant production object.
The same query can run from the CLI, TypeScript SDK, HTTP API, or MCP, making it easy to add to platform workflows before a repeated change becomes an incident.
Open the complete video showcase.
# Origin reachability
Source: https://docs.anyshift.io/pages/product/graph-api/origin-reachability
Read paths[].originReachability on public exposure results to see whether an ALB or NLB origin is reachable without Cloudflare.
When a public exposure path ends at an AWS load balancer, each path can include `originReachability`. Use it to check whether the origin itself accepts traffic from outside Cloudflare, based on security-group ingress compared to pinned Cloudflare IP ranges.
This is origin-control evidence on the path. It does not change the overall exposure verdict, and it is not a traffic-path failure.
## Try it
```bash theme={null}
annie graph exposure api.example.com --type CLOUDFLARE_HOSTNAME
annie graph exposure api.example.com --type CLOUDFLARE_HOSTNAME --output json \
| jq '.data.exposure.paths[] | {verdict: .originReachability.verdict, reasons: .originReachability.reasons}'
```
Or with Graph Query Language:
```console theme={null}
$ annie graph query "SELECT * FROM exposure WHERE resource = api.example.com"
```
The same field is available from `graph.exposure()` in the [Graph SDK](/pages/product/integration/sdk_capabilities#security-and-exposure). [Graph MCP](/pages/product/integration/graph_mcp) does not compute this verdict; it exposes the underlying topology (load balancer, security group rules, Cloudflare hostnames) through `get_related` and the public exposure recipe in the plugin skill.
## Field shape
`paths[].originReachability` is either an object or JSON `null`.
`null` means the path was not evaluated for origin reachability (for example, no ALB or NLB origin was present on that path).
When present:
```json theme={null}
{
"verdict": "restricted_to_cloudflare",
"reasons": [
"all advertised address families have Cloudflare-only ingress on evaluated listeners"
],
"advertisedFamilies": ["ipv4", "ipv6"],
"coveringRules": [
{
"family": "ipv4",
"cidr": "173.245.48.0/20",
"groupId": "sg-abc",
"permissionIndex": "0",
"fromPort": 443,
"toPort": 443,
"protocol": "tcp",
"coveredByCloudflare": true,
"worldOpen": false
}
],
"uncoveredRules": [],
"missingEvidence": [],
"cfRanges": {
"version": "20260818",
"publishedAt": "2026-08-18T00:00:00.000Z",
"source": "https://www.cloudflare.com/ips/"
}
}
```
| Field | Meaning |
| -------------------- | -------------------------------------------------------------- |
| `verdict` | Origin-control conclusion for this path |
| `reasons` | Human-readable explanation of the verdict |
| `advertisedFamilies` | Address families evaluated (`ipv4`, `ipv6`) |
| `coveringRules` | Ingress rules covered by pinned Cloudflare ranges |
| `uncoveredRules` | Ingress rules that are world-open or outside Cloudflare ranges |
| `missingEvidence` | Inventory pieces that blocked a definitive restricted verdict |
| `cfRanges` | Versioned Cloudflare IP range pin used for the comparison |
## Verdicts
| Verdict | Meaning |
| -------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `restricted_to_cloudflare` | Every advertised address family has complete Cloudflare-only security-group ingress on the evaluated listeners |
| `directly_reachable` | At least one world-open or non-Cloudflare ingress CIDR can reach the origin |
| `unknown` | Evidence is incomplete, stale, partial across address families, or otherwise insufficient |
| `not_applicable` | The origin shape is out of evaluated scope for this path |
Incomplete evidence never becomes `restricted_to_cloudflare`. Prefer reading `unknown` plus `missingEvidence` when inventory is partial.
## What this is not
`originReachability` answers a different question from DNS proxy state:
| Signal | Answers |
| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| Cloudflare DNS `proxied` (orange cloud) | Whether Cloudflare edge is configured to terminate DNS for the hostname |
| Graph relationship `PROXIES_TO` | Stored proxied hostname → origin relationship |
| Graph relationship `RESOLVES_DIRECTLY_TO` | DNS-only bypass path (`proxied=false`) to a reviewed terminal |
| `paths[].originReachability` | Whether the public ALB or NLB origin itself is reachable without Cloudflare, from load-balancer security-group ingress vs pinned Cloudflare ranges |
A hostname can be orange-cloud (`PROXIES_TO`) and still be `directly_reachable` at the origin if the security group allows `0.0.0.0/0`. Conversely, `restricted_to_cloudflare` does not mark the exposure path as failed.
Annie CLI prints origin reachability separately from traffic gaps so it never looks like a missing hop.
## Supported origins
Evaluated today:
* Internet-facing AWS Application Load Balancer with security-group ingress
* Internet-facing AWS Network Load Balancer with attached security groups
Still `not_applicable` or `unknown` without enough preservation evidence:
* NLB shapes without attached security groups, or target-SG-only analysis
* Gateway Load Balancer
* Kubernetes NetworkPolicy source-IP analysis (needs observed client-IP preservation)
Connect [Cloudflare](/pages/integration/cloudflare) and AWS inventory so exposure paths and security-group evidence are present before you treat a restricted verdict as conclusive.
## Related surfaces
* [Annie CLI](/pages/product/integration/cli): `annie graph exposure`
* [Graph MCP](/pages/product/integration/graph_mcp): underlying topology only, via `get_related` and the plugin's public exposure recipe
* [Graph Query Language](/pages/product/integration/graph_query_language#exposure): `SELECT * FROM exposure ...`
* [SDK capabilities](/pages/product/integration/sdk_capabilities#security-and-exposure): `graph.exposure()`
# Graph API
Source: https://docs.anyshift.io/pages/product/graph-api/overview
Query your live production graph from code, CI, internal platforms, and AI agents.
The Anyshift Graph API exposes the relationships between your Kubernetes, cloud, infrastructure as code, APM, and monitoring systems as one read-only API.
Your code, pipelines, and agents query the graph directly instead of copying an entire stack into a prompt. The same query can run through the TypeScript SDK, HTTP API, CLI, or MCP.
Production access stays read-only. Queries return current, governed context without handing write credentials to downstream agents.
## Start building
Give compatible AI agents deterministic, read-only production graph evidence.
Bring live production evidence and a repeatable Graph MCP workflow into your coding agent.
Install `@anyshift/graph-sdk`, authenticate, and run your first typed query.
Browse the complete helper surface across operations, Kubernetes, security, observability, APM, and GitOps.
Browse every deterministic query target, filter, and accepted value.
## Watch the overview
Query production context in milliseconds while keeping access governed and read-only.
## Use cases
Keep catalog pages synchronized with the live production topology.
Rank noisy monitors and protect the on-call rotation.
Find repeated changes before they become incidents.
Bring live dependency context into code review.
See whether an ALB or NLB origin is reachable without Cloudflare.
# Pull request blast radius
Source: https://docs.anyshift.io/pages/product/graph-api/pull-request-blast-radius
Map a proposed code change against live production dependencies before merge.
Tests can tell you whether code passes. They do not know which live workloads, services, datastores, and monitors depend on what the pull request changes.
## Bring production context into review
* Map the proposed change against the live production graph
* Surface every workload and service in the blast zone
* Name the monitors at risk before merge
* Give CI and coding agents the same read-only context
Engineers catch hidden dependencies during review instead of during rollback.
Open the complete video showcase.
# Backstage setup
Source: https://docs.anyshift.io/pages/product/integration/backstage
Install and configure read-only Anyshift production context in Backstage.
The Anyshift Backstage integration adds live infrastructure context to the software catalog you already use. It connects one Anyshift project to:
* A global Anyshift dashboard at `/anyshift`, with estate-wide evidence coverage and Ask Anyshift
* An **Anyshift** tab on matching catalog entities, with runtime context, impact, and recent evidence
* A cloud inventory at `/cloud` and cloud-aware pages for synchronized Resources
* Optional infrastructure Resources and evidence-backed relations in the catalog and architecture diagram
Your Anyshift project ID and API token stay in the Backstage backend. The browser sends authenticated requests only to Backstage and never receives the Anyshift token.
The integration is currently in beta and is published under the `next` npm
tag. It supports Backstage's new frontend and backend systems. There is no
legacy frontend entry point.
## Before You Start
You need:
* A Backstage application using the new frontend system
* Backstage 1.52 or 1.53
* One Anyshift project with graph data
* An API token that can read that project
* A Backstage permission policy
## Install the Core Integration
Install the frontend plugin in your app workspace and the backend plugin in your backend workspace:
```bash theme={null}
yarn workspace app add @anyshift/backstage-plugin-anyshift@next
yarn workspace backend add @anyshift/backstage-plugin-anyshift-backend@next
```
Register the backend plugin in `packages/backend/src/index.ts`:
```ts theme={null}
backend.add(import("@anyshift/backstage-plugin-anyshift-backend"));
```
The frontend package is discoverable. Enable package discovery in your Backstage configuration:
```yaml theme={null}
app:
packages: all
```
You do not need to edit `App.tsx` or `EntityPage.tsx`. Backstage discovers the global page, navigation item, API factory, and entity content from the installed package.
## Configure Anyshift
Add one Anyshift project to your Backstage configuration:
```yaml theme={null}
anyshift:
baseUrl: https://graph.anyshift.io
projectId: ${ANYSHIFT_PROJECT_ID}
token: ${ANYSHIFT_TOKEN}
timeout: 60s
cache:
ttl: 60s
ask:
enabled: false
query:
enabled: false
catalog:
mode: disabled
topologyMode: disabled
```
Set `ANYSHIFT_PROJECT_ID` and `ANYSHIFT_TOKEN` in the environment used by your Backstage backend. Do not put the token in frontend configuration or commit it to your repository.
Ask Anyshift and the query console are disabled by default. Enable Ask for viewers who need guided, evidence-backed answers. Leave the query console disabled unless operators need to run deterministic, read-only Graph queries from Backstage.
## Configure Permissions
The backend enforces three permissions:
| Permission | Grants |
| ----------------------- | ---------------------------------------------------------------------------- |
| `anyshift.view` | Read dashboards, entity context, cloud evidence, and use Ask Anyshift |
| `anyshift.query` | Run deterministic, read-only Graph queries when the query console is enabled |
| `anyshift.catalog.sync` | Start an immediate catalog reconciliation |
Install the common package directly in the backend workspace if your permission policy imports these constants:
```bash theme={null}
yarn workspace backend add @anyshift/backstage-plugin-anyshift-common@next
```
Import the permissions into your existing Backstage policy:
```ts theme={null}
import { AuthorizeResult } from "@backstage/plugin-permission-common";
import {
anyshiftCatalogSyncPermission,
anyshiftQueryPermission,
anyshiftViewPermission,
} from "@anyshift/backstage-plugin-anyshift-common";
```
For a read-only rollout, grant `anyshift.view` to the intended users and deny `anyshift.query` and `anyshift.catalog.sync`. A typical policy decision inside `handle()` looks like this:
```ts theme={null}
if (request.permission.name === anyshiftViewPermission.name) {
return {
result: user ? AuthorizeResult.ALLOW : AuthorizeResult.DENY,
};
}
if (request.permission.name === anyshiftQueryPermission.name) {
return { result: AuthorizeResult.DENY };
}
if (request.permission.name === anyshiftCatalogSyncPermission.name) {
const isOperator = user?.info.ownershipEntityRefs.includes(
"group:default/platform-operators",
);
return {
result: isOperator ? AuthorizeResult.ALLOW : AuthorizeResult.DENY,
};
}
```
Replace `group:default/platform-operators` with the group that operates your catalog. The frontend hides actions a user cannot perform, but the backend permission checks remain authoritative.
An allow-all Backstage policy grants all three permissions to every signed-in
user. Replace it with an explicit production policy before enabling the query
console or manual reconciliation.
## Match Catalog Entities
The Anyshift tab appears on entities with either of these annotations:
* `anyshift.io/target`
* `github.com/project-slug`
When `anyshift.io/target` is absent, the plugin uses the repository name from `github.com/project-slug` as the runtime target. Add an explicit target when the repository and deployed workload use different names:
```yaml theme={null}
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: checkout
annotations:
github.com/project-slug: example-org/checkout
anyshift.io/target: checkout-api
spec:
type: service
lifecycle: production
owner: group:default/checkout-team
```
After the entity is ingested, open it in the catalog and select the **Anyshift** tab.
## Ask About Your Estate
Ask Anyshift provides a single-question, read-only experience on the global dashboard and supported entity pages. Use it to investigate dependencies, changes, impact, inventory, and evidence coverage without writing a Graph query.
Enable it in the backend configuration:
```yaml theme={null}
anyshift:
ask:
enabled: true
```
Users with `anyshift.view` can then enter a question such as:
```text theme={null}
What depends on checkout-api?
```
On an entity page, the scope chip makes the current Component or Resource explicit. Keep the chip to ask about that entity, or remove it before submitting to ask across the configured project. The answer shows how the question was interpreted and presents supported evidence as typed dependency, timeline, impact, inventory, coverage, ranking, or ambiguity details.
Ask displays one current answer and does not provide conversation history. Questions and answers are not persisted by the plugin or written to its default logs. The Anyshift token remains in the Backstage backend.
Ask uses `anyshift.view`; it does not require `anyshift.query`. The entity
scope helps compose the question but does not create a separate authorization
boundary outside the configured Anyshift project.
## Understand Entity Evidence
The **Anyshift** tab brings current graph evidence into the service page:
* **Why now?** summarizes active alerts, suspected runtime conditions, and available deployment correlation. A nearby deployment is not presented as the cause unless the evidence supports that conclusion.
* **Affected footprint** groups potentially affected workloads, downstream services, datastores, external dependencies, monitors, and SLOs. Related catalog entities are linked when a match exists.
* **Architecture** shows observed and configured service dependencies. Select a service-to-service edge marked `HTTP · N` to inspect its HTTP operation evidence.
Recent deployment activity can come from specialized rollout evidence or normalized producer deployment events. The integration uses the available source automatically and keeps its evidence limitations visible.
The HTTP operation inspector can show multiple observations on one edge. Each entry includes the available HTTP method, templated path, APM source, and observation time. Method-only and path-only observations remain useful and are displayed without inventing the missing value.
Operation metadata is optional. An edge without `HTTP · N` remains a valid dependency and renders as before; missing operation evidence does not mean there was no traffic. The inspector uses the topology response already loaded for the diagram and does not make a request for each edge.
HTTP operation details require Graph API v0.2.42 or later and an APM source
that supplies operation evidence. Datadog, Tempo, and Dynatrace source names
use the same Backstage presentation.
The global Anyshift dashboard also includes **Evidence coverage**. It compares connected and expected sources, reports graph size and event coverage, and identifies observability blind spots. Use it before drawing conclusions from an empty result.
## Synchronize Infrastructure Resources
Catalog synchronization is optional. Use it when you want infrastructure Resources and runtime relations next to the Components already owned by GitHub.
Install the catalog module:
```bash theme={null}
yarn workspace backend add @anyshift/backstage-plugin-catalog-backend-module-anyshift@next
```
Register it in `packages/backend/src/index.ts`:
```ts theme={null}
backend.add(
import("@anyshift/backstage-plugin-catalog-backend-module-anyshift"),
);
```
### Start in Shadow Mode
Shadow mode reads the graph and reports proposed matches, collisions, and Resources without writing them to the catalog:
```yaml theme={null}
anyshift:
baseUrl: https://graph.anyshift.io
projectId: ${ANYSHIFT_PROJECT_ID}
token: ${ANYSHIFT_TOKEN}
catalog:
mode: shadow
topologyMode: shadow
fallbackOwner: group:default/anyshift-unowned
relationshipConcurrency: 25
inventoryTypes: [deployment, statefulset, configmap]
workloadTypes: [deployment]
resourceNamePatterns: []
schedule:
frequency: 30m
timeout: 5m
```
Review the `Anyshift catalog sync report` entries in your Backstage logs. Confirm that component targets, owners, proposed Resources, and collisions are correct before enabling writes.
Set `fallbackOwner` to a Group that exists in your catalog. The example uses a dedicated holding group for infrastructure that does not yet have an evidence-backed owner.
`catalog.mode` controls infrastructure Resource publication. `catalog.topologyMode` independently controls Component relationship enrichment. Set both explicitly so you can review cloud inventory and service relations separately.
### Enable Active Mode Gradually
Switch to active mode with a reviewed target allowlist:
```yaml theme={null}
anyshift:
baseUrl: https://graph.anyshift.io
projectId: ${ANYSHIFT_PROJECT_ID}
token: ${ANYSHIFT_TOKEN}
catalog:
mode: active
topologyMode: active
fallbackOwner: group:default/anyshift-unowned
inventoryTypes: [deployment, statefulset, configmap]
workloadTypes: [deployment]
activeTargets: [checkout-api, payments-api]
schedule:
frequency: 30m
timeout: 5m
```
`activeTargets` limits Component enrichment to the listed runtime targets. Omit it only when every matched Component should be eligible. If you configure it, the list must contain at least one target.
Mark an individual Component as intentionally unmanaged when it should never be synchronized:
```yaml theme={null}
metadata:
annotations:
anyshift.io/catalog-sync: excluded
```
### Add Configured Runtime Dependencies
Observed APM topology is not the only useful source of a dependency. For ECS services, you can declare reviewed endpoint aliases so Anyshift can confirm dependencies found in task-definition configuration without returning environment values.
```yaml theme={null}
metadata:
annotations:
anyshift.io/target: checkout-api
anyshift.io/runtime-resource-id:
anyshift.io/configuration-dependencies: payments-api=payments.internal
```
On the dependency Component, use `anyshift.io/configuration-endpoints` to list the endpoint aliases that identify it:
```yaml theme={null}
metadata:
annotations:
anyshift.io/target: payments-api
anyshift.io/configuration-endpoints: payments.internal
```
The catalog module creates a relation only when the configured alias is supported by graph evidence. `anyshift.io/runtime-resource-id` lets configuration evidence resolve a stable cloud identity while `anyshift.io/target` continues to identify the APM service.
For provider-generated Resources, place the same reviewed identities in `catalog.runtimeMappings` because those Resources do not inherit annotations from a separate Component:
```yaml theme={null}
anyshift:
catalog:
runtimeMappings:
- target: checkout-api
runtimeResourceId:
configurationDependencies:
- service: payments-api
endpoint: payments.internal
- target: payments-api
configurationEndpoints:
- payments.internal
```
### Cloud Resource Types
The default inventory types are Kubernetes-oriented. For an AWS-backed project, select the resource labels you want to publish:
```yaml theme={null}
anyshift:
catalog:
mode: shadow
inventoryTypes:
- ECS_SERVICE
- ECS_CLUSTER
- LAMBDA_FUNCTION
- RDS_DB
- DYNAMODB_TABLE
- S3_BUCKET
- SQS_QUEUE
- SNS_TOPIC
- ECR_REPOSITORY
- ELASTICLOADBALANCING_LOADBALANCER
workloadTypes: [ECS_SERVICE, LAMBDA_FUNCTION]
```
Use `resourceNamePatterns` to limit the imported inventory further with case-insensitive regular expressions.
### Explore Cloud Resources
When cloud Resources are synchronized, the discoverable frontend adds a **Cloud** navigation item at `/cloud`. Open a Resource to review:
* Provider, account, region, ARN, and a cloud-console link when available
* Direct catalog dependencies and dependents
* Typed potential impact through supported graph relationships
* Normalized cloud changes and their evidence limitations
* Terraform code-to-state-to-cloud provenance and supported drift comparisons
* Ask Anyshift scoped to the visible Resource
The **Cloud** and **Anyshift** tabs use the same cloud-aware view. Cloud Resources do not show Kubernetes safeguards that do not apply to them.
Potential impact describes graph reachability, not a confirmed outage or cause. Empty cloud-change, infrastructure-as-code, drift, or impact sections mean that evidence is unavailable for the selected Resource or window. They do not prove that the Resource is healthy, unmanaged, or disconnected.
## Ownership and Failure Behavior
GitHub remains authoritative for Components, Users, Groups, owners, lifecycle, and repository metadata. The Anyshift module:
* Creates infrastructure Resources
* Adds service-to-service, Component-to-Resource, and Resource-to-Resource relations supported by graph evidence
* Enriches matched Components without recreating them
* Preserves the previous complete Resource set when a synchronization attempt fails
Generated Resources carry the `anyshift.io/managed-by: catalog-provider` annotation. In active mode, the module also maintains `resource:default/anyshift-catalog-sync`, which records the result, trigger, completion time, and a bounded failure reason for the latest attempt.
Users with `anyshift.catalog.sync` can select **Reconcile now** on the global Anyshift page. Scheduled and manual requests that overlap are combined into one provider run.
## Verify the Installation
1. Start the Backstage backend with the Anyshift environment variables set.
2. Sign in as a user with `anyshift.view`.
3. Open `/anyshift` and confirm the global dashboard and Evidence coverage card load.
4. Open a Component with `anyshift.io/target` or `github.com/project-slug`.
5. Select the **Anyshift** tab and confirm the runtime target, Why now?, affected footprint, and architecture evidence resolve independently.
6. If Ask is enabled, submit one estate-wide question and one entity-scoped question. Confirm the visible scope matches the intended entity.
7. If an architecture edge is marked `HTTP · N`, select it and confirm its method or path, APM source, and observation time appear.
8. If catalog synchronization is enabled, review the sync report and the `anyshift-catalog-sync` Resource before moving either catalog mode from `shadow` to `active`.
9. Open `/cloud`, select a synchronized Resource, and confirm its identity, relations, evidence sections, and scoped Ask use the intended resource.
## Troubleshooting
Confirm that the frontend package is installed in the app workspace, the
app uses Backstage's new frontend system, and `app.packages` is set to
`all`. Restart the frontend after changing dependencies or configuration.
Add `anyshift.io/target` or `github.com/project-slug` to the entity
annotations. Use `anyshift.io/target` when the repository name does not match
the runtime workload.
Set `anyshift.ask.enabled` to `true`, restart the backend and frontend, and
confirm the signed-in user has `anyshift.view`. Ask is independent of the
Advanced Query setting and does not require `anyshift.query`.
Check your Backstage permission policy. Dashboard, entity data, cloud
evidence, and Ask require `anyshift.view`; queries require `anyshift.query`;
manual reconciliation requires `anyshift.catalog.sync`.
Operation evidence is optional. Confirm that the Graph API is v0.2.42 or later
and that the APM source supplies operation metadata for this edge. An unmarked
edge still represents a dependency; missing operation details do not prove
that no traffic exists.
Confirm that the catalog module is installed and registered. `disabled`
creates nothing, while `shadow` reports proposed changes without applying
them. In `active`, verify that `inventoryTypes`, `activeTargets`, and
`resourceNamePatterns` include the intended resources.
Check Evidence coverage and the freshness shown beside each capability. Empty
changes, impact, infrastructure-as-code, deployment, or operation evidence
means unknown for that entity and time window. It does not mean healthy,
disconnected, or unmanaged. Retry only the failed capability when the page
offers a section-level retry.
A quiet source or status caveat means the event evidence is derived or
incomplete. It provides context rather than a health alert. Identity warnings
remain actionable when the Resource itself cannot be resolved.
Find the latest `Anyshift catalog sync report` in the backend logs and
inspect `resource:default/anyshift-catalog-sync`. A failed attempt leaves
the last complete infrastructure Resource set in place.
## Packages
The beta packages are available from npm:
* [`@anyshift/backstage-plugin-anyshift`](https://www.npmjs.com/package/@anyshift/backstage-plugin-anyshift)
* [`@anyshift/backstage-plugin-anyshift-backend`](https://www.npmjs.com/package/@anyshift/backstage-plugin-anyshift-backend)
* [`@anyshift/backstage-plugin-anyshift-common`](https://www.npmjs.com/package/@anyshift/backstage-plugin-anyshift-common)
* [`@anyshift/backstage-plugin-catalog-backend-module-anyshift`](https://www.npmjs.com/package/@anyshift/backstage-plugin-catalog-backend-module-anyshift)
For direct TypeScript access to the same infrastructure graph, see the [Graph SDK guide](/pages/product/integration/sdk).
# CLI
Source: https://docs.anyshift.io/pages/product/integration/cli
Query your production context from the terminal, scripts, and CI.
Ask questions, pipe in logs, or run production investigations without leaving the terminal.
## Quickstart
```bash theme={null}
brew install anyshift-io/tap/annie
```
```bash theme={null}
yay -S anyshift-annie-bin
```
Download the archive for your platform:
```bash theme={null}
# macOS, Apple Silicon
curl -sL https://annie-cli.anyshift.io/releases/latest/annie-darwin-arm64.tar.gz | tar xz
sudo mv annie /usr/local/bin/
# macOS, Intel
curl -sL https://annie-cli.anyshift.io/releases/latest/annie-darwin-amd64.tar.gz | tar xz
sudo mv annie /usr/local/bin/
# Linux, amd64
curl -sL https://annie-cli.anyshift.io/releases/latest/annie-linux-amd64.tar.gz | tar xz
sudo mv annie /usr/local/bin/
# Linux, arm64
curl -sL https://annie-cli.anyshift.io/releases/latest/annie-linux-arm64.tar.gz | tar xz
sudo mv annie /usr/local/bin/
```
```bash theme={null}
annie auth login
```
Your browser opens for authentication and the CLI selects your default project.
```bash theme={null}
annie ask "why is checkout slow?"
```
## Common workflows
Start a terminal chat with session history and markdown output:
```bash theme={null}
annie
```
```bash theme={null}
annie ask "what changed in production?"
annie ask "list services" --output json
```
```bash theme={null}
kubectl get events -A | annie ask "anything unusual?"
kubectl logs -n prod -l app=backend --tail=200 | annie
```
Run a root-cause analysis with ranked hypotheses:
```bash theme={null}
annie ask --rca "why are database connections exhausted?"
```
Use deterministic, read-only commands for scripts and automation:
```bash theme={null}
annie graph search checkout
annie graph blast checkout
annie graph path checkout checkout-postgres --scope operational
annie graph alerts --provider pagerduty --status firing
annie graph incidents --provider pagerduty --status active
annie graph incidents --provider pagerduty --responder "Jane Doe"
annie graph oncall --at now
annie graph oncall --person "Jane Doe" --at now
annie graph triage checkout --since 2h
annie graph query 'SELECT * FROM incident_context WHERE target = checkout AND since = 30d LIMIT 10'
annie graph query 'SELECT * FROM connections WHERE resource = checkout'
```
Use `annie graph` for repeatable lookups. Use `annie ask` when you want an explanation or recommendation.
Coding agents can call the CLI directly:
```text theme={null}
Use the annie CLI to list the EC2 instances in .
```
For Claude Code, install the [CLI skills plugin](/pages/product/integration/skills). For Annie investigations inside an agent, use [Annie Remote MCP](/pages/product/integration/remote_mcp). For deterministic Production Graph evidence, use [Graph MCP](/pages/product/integration/graph_mcp) or the [Plugin](/pages/product/integration/production_intelligence_agent_plugin).
## Stay up to date
Stable Annie CLI releases tell you when a newer version is available in an interactive terminal. The TUI keeps the available version in its status bar, and successful human-readable commands may show one reminder every 24 hours.
Check synchronously whenever you need the current release status:
```bash theme={null}
annie update check
annie update check --output json
```
The JSON form reports the installed version, latest version, update availability, check time, and release URL. Annie does not download or install the update.
Passive checks stay silent for JSON output, pipes, redirected streams, CI, help, version, shell completion, development builds, and prereleases. Network failures do not change command output or exit status. Disable passive checks and reminders without disabling the explicit command:
```bash theme={null}
annie config set update_check false
# Or for one process
ANNIE_UPDATE_CHECK=off annie
```
## Investigate GCP changes
Use deterministic graph commands when you need retained GCP evidence in a terminal, script, or CI
job. List recent events, narrow them to one provider operation, then inspect the affected inventory:
```bash theme={null}
annie graph cloud-events --provider gcp --scope gcp/checkout-prod --since 24h
annie graph cloud-events --provider gcp --operation operation-123 --diff
annie graph cloud-resources --type COMPUTE_INSTANCES --max-age 24h
```
If a fuzzy topology selector matches several equally authoritative resources, Annie exits `2` with
`RESOURCE_AMBIGUOUS` and lists at most ten stable-ID candidates. JSON keeps the same candidates at
`.error.details.candidates`. Select one `id` or `anyshiftID` and retry; Annie never traverses from an
arbitrary first match.
`--operation` groups activity by the GCP-native operation identifier. `--correlation` selects the
broader Anyshift event story. They are separate identifiers. Text output keeps the main evidence
fields; use JSON when automation needs warnings, availability, before and after values, pagination,
or provenance references:
```bash theme={null}
annie graph cloud-events --provider gcp --operation operation-123 --output json \
| jq '.data.cloudEvents.items[] | {type, evidence, correlation}'
annie graph cloud-resources --provenance unknown --freshness unknown --output json \
| jq '.data.cloudResources.items[] | {id, provenance, freshness}'
```
Normal `annie graph cloud-events` browsing uses bounded page mode. Text output reports the number
shown, whether more results exist, and the next cursor without calculating or claiming an exact
full-window total. Use `--exact-stats` only when you need the exact total and event-type breakdown;
that opt-in can be slower on large accounts. In page-mode JSON, `total` is `null`, `byType` is empty,
and `statistics` reports `{ "mode": "none", "exact": false }`.
An unknown status is not success. Unknown provenance does not mean unmanaged, and unknown freshness
does not mean stale. If a response contains `nextCursor`, pass it back with `--cursor` to continue
that result page.
## Repository context
Add an `.annie.yaml` file to a repository when you want every question from that workspace to use the same Anyshift project, metadata, and runbooks:
```yaml .annie.yaml theme={null}
version: 1
project: production
context:
service: checkout
environment: production
files:
- runbooks/checkout.md
```
Annie finds the nearest `.annie.yaml` by walking up from your current directory. Repository settings apply only to that invocation and do not change your global default project.
Use project-scoped personal context when a value should follow you across repositories:
```bash theme={null}
annie context show
annie context set team=payments region=us-east-1
annie context add-file runbooks/on-call.md
annie context preview
```
These commands manage your personal context for the selected project. They do not edit the repository's `.annie.yaml`.
Invocation flags take precedence over TUI session context, repository context, and personal project context:
```bash theme={null}
annie ask "what changed?" \
--project production \
--context service=checkout \
--file runbooks/checkout.md
```
Files are included only when you name them. Annie blocks files outside the repository, unsafe symlinks, binary and oversized files, common secret filenames, private keys, token-like content, and Kubernetes Secret manifests. The limits are 32 KiB per file and 96 KiB across one request. Run `annie context preview` to check file status without printing file contents.
## Structured output
Pass a local JSON Schema when a script or CI job needs a predictable object instead of prose:
```json service-risk.schema.json theme={null}
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["risk"],
"properties": {
"risk": {
"type": "string",
"enum": ["low", "medium", "high"]
}
},
"additionalProperties": false
}
```
```bash theme={null}
annie ask "assess the deployment risk for checkout" \
--schema ./service-risk.schema.json \
--output json | jq -r '.answer.content.risk'
```
The CLI validates the schema before sending the request. `--schema` requires `--output json` and supports JSON Schema Draft 7 and Draft 2020-12 with an object at the root. Remote schema references are rejected.
## Conversation history
Resume a previous investigation with its transcript instead of starting over:
```bash theme={null}
# Find and inspect a conversation
annie conversation list
annie conversation show
# Restore the transcript and continue in the TUI
annie conversation resume
# Continue with a one-shot question
annie ask --conversation "what changed since then?"
# Export the transcript
annie conversation export --output markdown
```
Resume state is scoped to the active project. Annie verifies that the conversation belongs to that project before restoring it. `annie conversation delete ` requires confirmation and may be restricted to administrators.
## Reference
```bash theme={null}
# Include extra context
annie ask "what changed?" --context env=prod --context team=payments
# Attach an explicit repository file
annie ask "check this runbook" --file runbooks/checkout.md
# Select a project for one query
annie ask --project "Production" "list S3 buckets"
# Continue interactively after the answer
annie ask "what is failing?" --follow
# Machine-readable output
annie ask "list services" --output json
# Custom timeout
annie ask "list all EC2 instances" --timeout 20m
```
| Command | Result |
| ---------------------------------------- | ----------------------------------------------------------------------------- |
| `annie graph search ` | Find matching resources |
| `annie graph show ` | Inspect one exact current resource and its direct relationships |
| `annie graph deps ` | Show direct dependencies |
| `annie graph path ` | Find an infrastructure or operational path |
| `annie graph blast ` | Calculate transitive impact |
| `annie graph tree ` | Expand downstream dependencies |
| `annie graph diagram ` | Generate Mermaid topology |
| `annie graph timeline ` | Show changes and incident propagation |
| `annie graph triage ` | Combine symptoms, causes, impact, and optional stored `incident_context` hops |
| `annie graph posture [resource]` | Find reliability and security gaps |
| `annie graph check [resource]` | Enforce posture in CI |
| `annie graph top` | Rank current hotspots |
| `annie graph explore` | Browse the graph interactively |
| `annie graph exposure [resource]` | Trace public-edge exposure paths, controls, and origin reachability |
| `annie graph cloud-events [resource]` | Inspect AWS, Azure, or GCP change evidence |
| `annie graph cloud-resources [resource]` | Inspect cloud inventory, freshness, lifecycle, and provenance |
| `annie graph query ` | Run a validated Graph API query |
All non-interactive graph commands support `--project ` and `--output text|json`. Run `annie graph --help` for command-specific flags.
Inspect public exposure for a Cloudflare hostname or a Kubernetes service:
```bash theme={null}
annie graph exposure api.example.com --type CLOUDFLARE_HOSTNAME
annie graph exposure checkout --type K8S_SERVICE --namespace payments
annie graph exposure --id 'cf://accounts/a/zones/z/hostnames/api.example.com'
```
Each path may include nullable `originReachability` for internet-facing ALB or NLB security-group evidence versus pinned Cloudflare IP ranges. That field is not DNS `proxied` / `RESOLVES_DIRECTLY_TO`, and text output prints it separately from traffic gaps. See [Origin reachability](/pages/product/graph-api/origin-reachability).
`graph triage` is deterministic evidence, not AI. It optionally queries `incident_context` for the
resource (`target` + `since` + `LIMIT`). Returned hops are `incident`, `alerts`, `service`,
`onCall`, `responders`, and `history`. Empty hops are omitted from findings. History cites reviewed
resolution evidence only (`confirmed_fix`, `explicit_reference`, or `unknown`), never
temporal-only association. Raw queries use
[`incident_context`](/pages/product/integration/graph_query_language#incident-context); PagerDuty
setup is on the [PagerDuty integration](/pages/integration/pagerduty#grouped-incident-context) page.
`graph show` accepts a `hashedID` or `anyshiftID` returned by graph discovery. It uses the
project-scoped Graph API and never guesses from a display name. Resolve a name first, then inspect
the selected identity:
```bash theme={null}
annie graph resolve "checkout"
annie graph show '' --output json
```
The result includes the resource's safe properties and bounded incoming and outgoing relationships.
Text and JSON make relationship truncation explicit. Historical `graph show --at` reads are not
supported until the Graph API has snapshot semantics; use `annie graph history` for retained change
evidence instead.
Discover the query language without authentication:
```bash theme={null}
annie graph query --list
annie graph query --describe blast_radius
```
See the complete [Graph Query Language reference](/pages/product/integration/graph_query_language).
JSON output uses the `annie.cli/v1` envelope. Natural-language answers are returned under `.answer.content`, while Graph results are returned under `.data`.
Require a schema-validated answer with:
```bash theme={null}
annie ask "assess checkout risk" \
--schema ./service-risk.schema.json \
--output json
```
| Code | Meaning |
| ---- | ----------------------------------------------------- |
| `0` | Success |
| `1` | Internal CLI error |
| `2` | Invalid usage or schema |
| `3` | Authentication or authorization failure |
| `4` | Backend or network failure |
| `5` | Timeout or cancellation |
| `6` | Annie analysis failed |
| `7` | Requested output schema not satisfied |
| `8` | A graph check found a gap, risk, or incomplete result |
```bash theme={null}
# Resume the latest session
annie --resume
# Resume a specific session
annie --conversation
```
Manage persistent project context:
```bash theme={null}
annie context show
annie context set service=checkout environment=production
annie context unset environment
annie context add-file runbooks/checkout.md
annie context remove-file runbooks/checkout.md
annie context preview
annie context clear
```
Essential commands:
| Command | Action |
| -------------------------------- | --------------------------------------- |
| `/rca ` | Run a root-cause analysis |
| `/report ` | Generate a structured report |
| `/project` | Switch project |
| `/copy` | Copy the latest answer |
| `/export [path]` | Export the conversation |
| `/context` | Show resolved context and files |
| `/context set ` | Add context to future prompts |
| `/context add-file ` | Attach a file to future prompts |
| `/context preview` | Preview context sources and file status |
| `/context clear` | Clear session context and files |
| `/clear` | Clear the screen |
| `/quit` | Exit |
Use `Tab` for command completion, `Page Up/Down` to scroll, and `Ctrl+C` to cancel.
```bash theme={null}
# Root-cause analyses
annie rca list
annie rca get
# Generate and save a report
annie ask --report --save-as "Weekly SRE Digest" "weekly SRE digest"
# Manage reports
annie report list
annie report list --instances
annie report get
annie report generate
```
IDs accept an eight-character prefix.
```bash theme={null}
annie project list
annie project current
annie project switch "Production"
```
For a single command, use `--project `.
For local use:
```bash theme={null}
annie auth login
annie auth status
annie auth logout
```
For CI, create an access token in **Settings → Access tokens**, store it as a secret, and set:
```bash theme={null}
export ANNIE_TOKEN=anys_api_...
export ANNIE_PROJECT_ID=
annie ask "summarize the latest deployment"
```
`ANNIE_PROJECT_ID` is only required when the token can access multiple projects. Use personal tokens locally and shared tokens for team automation. Token authentication cannot perform administrative operations.
```bash theme={null}
annie feedback up
annie feedback down
annie feedback hypothesis up
```
In the TUI, use `/rate up`, `/rate down`, or `/rate hypothesis up|down`.
```bash theme={null}
annie config set
annie config get
annie config list
```
Configuration lives in `~/.annie/config.yaml`. Disable anonymous telemetry with:
```bash theme={null}
annie config set telemetry false
```
The CLI also respects `NO_COLOR`.
Start using Anyshift
See the CLI in action
# Graph MCP
Source: https://docs.anyshift.io/pages/product/integration/graph_mcp
Give AI agents read-only access to your Anyshift production graph: live topology and change events.
Graph MCP connects compatible AI agent clients directly to your Anyshift event graph. Use it when an agent needs current topology, dependencies, exposure, change history, or correlated events while reviewing code, preparing a deployment, or investigating an incident.
The endpoint is read-only and project-scoped. It uses Streamable HTTP and OAuth login, so no API token goes into your MCP configuration.
Graph MCP supplies graph evidence to an agent that is already performing a task. It does not run Annie's AI SRE investigation workflow. Use [Annie Remote MCP](/pages/product/integration/remote_mcp) when you want Annie to analyze evidence, develop hypotheses, and recommend next steps.
## Connect
The production endpoint is:
```text theme={null}
https://api.anyshift.io/mcp/graph
```
The endpoint moved on 2026-09-08. `https://graph.anyshift.io/mcp` still serves the previous tool set for older installs, but it is deprecated. Point your client at the new URL and authorize once; existing authorizations are bound to the old endpoint and are not reused.
### Claude Code
```bash theme={null}
claude mcp add --transport http --scope user anyshift-graph https://api.anyshift.io/mcp/graph
claude mcp login anyshift-graph
```
Or install the [plugin](/pages/product/integration/production_intelligence_agent_plugin), which bundles the endpoint with the skill.
### Codex
```bash theme={null}
codex mcp add anyshift-graph --url https://api.anyshift.io/mcp/graph
codex mcp login anyshift-graph
```
The second command opens your browser. Sign in to Anyshift and select the project the agent may read.
### Other MCP clients
Add an HTTP MCP server to your client's configuration:
```json theme={null}
{
"mcpServers": {
"anyshift-graph": {
"type": "http",
"url": "https://api.anyshift.io/mcp/graph"
}
}
}
```
The configuration shape and OAuth user experience vary by client. The client must support Streamable HTTP and browser-based OAuth for remote MCP servers.
## Tools
| Tool | Use it to |
| ----------------------- | -------------------------------------------------------------------------------------------------------- |
| `describe_schema` | List this project's labels, relationship types, event types and sources. Call it first in every session. |
| `find_resources` | Find resources by name, label or property filter and get their stable `hashedID`. |
| `get_resource_details` | Read one resource's properties and bounded relationships. |
| `get_related` | Walk a resource's neighbours, filtered by direction and relationship type, with completeness signals. |
| `get_resource_events` | Time-bounded change history for one or more resources. |
| `get_recent_events` | Recent change events across the project, filtered by type, source or resource kind. |
| `get_correlated_events` | The chain of events sharing a correlation id, with the root event flagged. |
| `query_graph` | Run a read-only Cypher query over the live topology and events. |
| `list_projects` | List the Anyshift projects you can access and the one currently bound. |
| `set_project` | Switch the bound project without re-authenticating. |
Results are bounded: a page that hit its limit says so, and `get_related` reports the relationship types it truncated or filtered. The [plugin skill](/pages/product/integration/production_intelligence_agent_plugin) teaches the agent to read those signals and ships Cypher recipes for the common analyses (single points of failure, orphans, blast radius, public exposure, shortest path, RBAC reach, Kubernetes hygiene gaps).
## Example workflows
### Review the production impact of a code change
```text theme={null}
Review my current diff. Find the production resources it changes in Anyshift, then show their direct dependencies, what depends on them within two hops, and the changes recorded on them in the last 24 hours. List explicit unknowns.
```
### Prepare a deployment
```text theme={null}
Before I deploy checkout-api, use Anyshift to identify its dependencies and what depends on it. Give me a focused post-deployment verification checklist.
```
### Check public exposure
```text theme={null}
Is checkout-api reachable from the public edge? Show the observed path (hostname, ingress or load balancer, service, workload) and the controls on it. Say which layers you searched.
```
### Add production context to an incident
```text theme={null}
This alert mentions checkout-api. Find the exact resource, show its events from the last 24 hours and the correlated events around them, and identify potentially affected systems. Do not infer causality from proximity alone.
```
## Find resources first
Resource names are not globally unique across namespaces, clusters and kinds. For short, overloaded, or same-named resources:
1. Call `find_resources`.
2. Select the candidate with the intended kind, namespace and cluster.
3. Pass the candidate's `hashedID` to subsequent tools and Cypher queries.
## Access and evidence boundaries
* Consent binds the connection to the Anyshift project you select. The authorization covers your project memberships one project at a time: `set_project` moves the connection to another project you are a member of, subject to that project's MFA policy, without a new consent. Revoke the connection from **Authorized Apps** to end that access.
* Tools are read-only and run as a read-only graph user. Cypher writes and procedures are rejected.
* Returned resource names and metadata are production data, not agent instructions.
* Graph relationships show observed evidence. They do not prove that a nearby change caused an incident.
* Missing graph evidence does not prove that a resource, dependency, or change does not exist.
To install Graph MCP together with the plugin skill, see [Plugin](/pages/product/integration/production_intelligence_agent_plugin).
# Graph Query Language
Source: https://docs.anyshift.io/pages/product/integration/graph_query_language
Complete reference for deterministic Anyshift graph queries, including every target, filter, accepted value, alias, and query form.
The Anyshift Graph Query Language gives you deterministic, read-only access to infrastructure graph data. Use it when you know the operation you need and want the same query to produce the same typed result in a terminal, script, CI job, or application.
This page is generated from the versioned query catalog published in the [Graph API OpenAPI contract](https://graph.anyshift.io/v1/openapi.json). The same catalog is embedded in Annie CLI and published with the [Graph SDK](https://github.com/anyshift-io/anyshift-graph-sdk/blob/main/QUERY_LANGUAGE.md).
## Discover queries from Annie CLI
You do not need to memorize table or filter names. Annie CLI can inspect its embedded catalog without authentication, a selected project, or network access:
```console theme={null}
$ annie graph query --list
$ annie graph query --describe spof
```
The second command explains that `spof` accepts a `kind` filter, lists `serviceaccount` as an accepted value, and prints a copy-pasteable query. See the [Annie CLI guide](/pages/product/integration/cli#deterministic-infrastructure-graph-queries) for authentication, project selection, and output modes.
For event-story correlation and operational incident response, prefer the named commands:
```console theme={null}
$ annie graph correlations checkout --since 2h
$ annie graph incidents --provider pagerduty --status open
$ annie graph triage checkout --since 2h
```
`correlations` reconstructs Anyshift event groups. `incidents` reads provider response cases; the raw v1 query target for those cases is `response_incidents`. Grouped stored hops for one incident or mapped service use [`incident_context`](#incident-context); `annie graph triage` includes those hops when present.
## Syntax
```sql theme={null}
SELECT <*|count(*)> FROM [WHERE k = v [AND ...]] [LIMIT n] [OFFSET n]
```
Selectors: `*`, `count(*)`. Accepted selector aliases: `count(1)`. Values may be bare words or single- or double-quoted strings.
Filters use equality and can be combined with `AND`. A target only accepts the filters and enum values documented below. `LIMIT` and `OFFSET` are listed per target because not every result supports both modifiers.
## Query targets
| Target | Purpose | Filters | Modifiers |
| ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- |
| [`resolve`](#resolve) | Resolve a resource name or fragment to ranked current graph resources. | `term` | `LIMIT` |
| [`resource_details`](#resource-details) | Read one current graph resource by exact stable ID with safe properties and bounded relationships. | `id` | `LIMIT` |
| [`events`](#events) | Read the infrastructure change-event timeline. | `type`, `target`, `namespace`, `noise`, `since` | `LIMIT`, `OFFSET` |
| [`cloud_events`](#cloud-events) | Read evidence-backed AWS, Azure, and GCP change events without parsing summaries. | `provider`, `scope`, `region`, `category`, `type`, `resource`, `actor`, `correlation`, `operation`, `stats`, `noise`, `diff`, `since`, `cursor` | `LIMIT` |
| [`cloud_resources`](#cloud-resources) | Inspect current or recently deleted AWS, Azure, and GCP resources with freshness and provenance. | `provider`, `scope`, `region`, `type`, `resource`, `lifecycle`, `provenance`, `freshness`, `max_age`, `cursor` | `LIMIT` |
| [`delivery_events`](#delivery-events) | Read commit, CI, release, and deployment evidence from the delivery graph. | `stage`, `type`, `resource`, `actor`, `source`, `since`, `cursor` | `LIMIT` |
| [`provenance`](#provenance) | Trace a resource to stored release, commit, and actor evidence. | `resource` | `LIMIT` |
| [`ownership`](#ownership) | Resolve observed GitHub user or team code ownership and contact identities. | `resource` | `LIMIT` |
| [`graph_coverage`](#graph-coverage) | Inspect current node, relationship, bridge, and event evidence by graph source. | `source` | None |
| [`resources`](#resources) | Count and sample current resources of one graph resource type. | `type`, `source` | `LIMIT`, `OFFSET` |
| [`operational_impact`](#operational-impact) | Find potential operational impact through reviewed directional graph relationships. | `resource`, `depth` | `LIMIT`, `OFFSET` |
| [`connections`](#connections) | Inspect direct upstream and downstream relationships for a resource. | `resource` | `LIMIT` |
| [`hotspots`](#hotspots) | Rank noisy resources, namespaces, alert rules, or alerting workloads. | `type`, `by`, `namespace`, `noise`, `since` | `LIMIT` |
| [`correlations`](#correlations) | Reconstruct a correlated Anyshift event group around a target or correlation identifier. | `target`, `id`, `type`, `since` | None |
| [`incidents`](#incidents) | Deprecated alias for correlations. Reconstruct a correlated Anyshift event group around a target or correlation identifier. | `target`, `id`, `type`, `since` | None |
| [`failures`](#failures) | Read recent failure-class infrastructure events. | `target`, `namespace`, `since` | `LIMIT`, `OFFSET` |
| [`deployments`](#deployments) | Read recent workload deployments and image changes. | `target`, `namespace`, `since` | `LIMIT`, `OFFSET` |
| [`audit`](#audit) | Read configuration, identity, and infrastructure audit events. | `target`, `namespace`, `type`, `since` | `LIMIT`, `OFFSET` |
| [`nodes`](#nodes) | Read node lifecycle and capacity events. | `target`, `since` | `LIMIT`, `OFFSET` |
| [`deploy_impact`](#deploy-impact) | Join recent deployments to the failures that followed them. | `target`, `since` | `LIMIT` |
| [`common_cause`](#common-cause) | Find shared infrastructure or dependencies behind recent failures. | `namespace`, `since` | `LIMIT` |
| [`blast_radius`](#blast-radius) | Calculate the transitive workloads, pods, and services affected by a resource. | `resource` | `LIMIT` |
| [`spof`](#spof) | Rank highly shared ConfigMaps, service accounts, or nodes by fan-in. | `kind`, `namespace` | `LIMIT` |
| [`orphans`](#orphans) | Find unused or dangling Kubernetes resources. | `kind`, `namespace` | `LIMIT` |
| [`coverage`](#coverage) | Find service, monitor, or metrics coverage gaps. | `kind`, `namespace` | `LIMIT` |
| [`access`](#access) | Inspect RBAC reach or rank over-privileged service accounts. | `resource`, `mode` | `LIMIT` |
| [`exposure`](#exposure) | Trace bidirectional stored public-exposure routes and attached controls for one resource. | `resource`, `resource_id`, `resource_type`, `resource_namespace`, `resource_cluster`, `cursor` | `LIMIT` |
| [`tenancy`](#tenancy) | Find workloads co-located with a resource on the same node. | `resource` | `LIMIT` |
| [`sharedconfig`](#sharedconfig) | Find workloads coupled through shared configuration. | `resource` | `LIMIT` |
| [`path`](#path) | Find the shortest infrastructure or operational path between two resources; both scopes include reviewed Cloudflare traffic edges. | `from`, `from_exact`, `from_id`, `from_type`, `from_namespace`, `from_cluster`, `to`, `to_exact`, `to_id`, `to_type`, `to_namespace`, `to_cluster`, `scope` | None |
| [`cascade`](#cascade) | Trace an incident correlation group in propagation order. | `target`, `id`, `since` | None |
| [`alert_impact`](#alert-impact) | Find monitors and SLOs affected by a resource failure. | `resource` | `LIMIT` |
| [`monitor`](#monitor) | Resolve a monitor to the infrastructure it observes. | `target` | None |
| [`datastore`](#datastore) | Inspect datastore dependencies or rank widely used datastores. | `target`, `source` | `LIMIT` |
| [`flow`](#flow) | Inspect stream producers and consumers or rank busy streams. | `target`, `source` | `LIMIT` |
| [`external_dep`](#external-dep) | Inspect external dependencies or rank high-fan-in external hosts. | `target`, `source` | `LIMIT` |
| [`alerts`](#alerts) | List normalized operational alerts while retaining legacy Datadog firing-monitor fields. | `target`, `provider`, `status`, `severity`, `service_id`, `service`, `service_type`, `service_namespace`, `service_cluster`, `provider_service_id`, `since`, `from`, `to`, `at`, `cursor` | `LIMIT` |
| [`response_incidents`](#response-incidents) | List provider-neutral response incidents that coordinate alert handling. | `provider`, `status`, `service_id`, `service`, `service_type`, `service_namespace`, `service_cluster`, `provider_service_id`, `since`, `from`, `to`, `at`, `cursor`, `responder`, `urgency` | `LIMIT` |
| [`oncall`](#oncall) | List effective on-call responsibility for a point in time or bounded window. | `provider`, `status`, `service_id`, `service`, `service_type`, `service_namespace`, `service_cluster`, `provider_service_id`, `from`, `to`, `at`, `cursor`, `person`, `schedule` | `LIMIT` |
| [`incident_context`](#incident-context) | Group stored incident, alert, service, on-call, responder, and reviewed history hops without live provider calls. | `id`, `target`, `provider`, `since` | `LIMIT` |
| [`alert_noise`](#alert-noise) | Rank flapping or stuck monitors. | `target`, `kind`, `since` | `LIMIT` |
| [`calls`](#calls) | Inspect APM service callers, callees, and HTTP route evidence or rank call-graph fan-in. | `target`, `source` | `LIMIT` |
| [`servicetree`](#servicetree) | Expand a service's downstream services, datastores, and external dependencies. | `target`, `source` | `LIMIT` |
| [`alert_cause`](#alert-cause) | Join a firing service or workload to recent Kubernetes changes. | `target`, `since` | `LIMIT` |
| [`slo`](#slo) | Inspect one SLO or rank breaching and at-risk SLOs. | `target` | `LIMIT` |
| [`alertrules`](#alertrules) | Inspect Grafana and VictoriaMetrics alert-rule coverage and inventory. | `subject`, `namespace`, `target` | `LIMIT` |
| [`iac`](#iac) | Inspect Terraform code-to-state-to-cloud provenance and linkage coverage. | `resource`, `status`, `freshness` | `LIMIT`, `OFFSET` |
| [`iac_drift`](#iac-drift) | Compare last-applied Terraform state with fresh observed cloud properties. | `resource`, `status`, `freshness` | `LIMIT`, `OFFSET` |
| [`gitops`](#gitops) | Inspect GitOps drift, unmanaged workloads, or resource ownership. | `subject`, `namespace`, `resource` | `LIMIT` |
| [`image`](#image) | Inspect image usage, workload containers, or container hygiene gaps. | `target`, `workload`, `digest`, `kind`, `namespace` | `LIMIT` |
| [`netpol`](#netpol) | Inspect NetworkPolicy coverage, policies, or east-west reach. | `mode`, `namespace`, `target` | `LIMIT` |
| [`priority`](#priority) | Inspect scheduling priority gaps, the class ladder, or one target's priority. | `kind`, `namespace`, `target` | `LIMIT` |
| [`storage`](#storage) | Inspect workload storage and find orphaned or unclaimed volumes. | `mode`, `workload`, `resource`, `class`, `namespace` | `LIMIT` |
| [`pdb`](#pdb) | Find workloads without PodDisruptionBudgets or inspect one workload or PDB. | `target`, `workload`, `pdb` | `LIMIT` |
| [`scaling`](#scaling) | Find workloads without HPAs, list autoscaled workloads, or inspect one target. | `mode`, `namespace`, `target` | `LIMIT` |
| [`topology`](#topology) | Build a typed service topology at a selected level. | `service`, `level`, `source`, `endpoint`, `dependency` | None |
## resolve
Resolve a resource name or fragment to ranked current graph resources.
Result intent: `resolve`
Aliases: `search`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ------ | ------ | -------- | --------------- | ------------------------------------- |
| `term` | string | Yes | Any string | Resource name or fragment to resolve. |
### Resolve resources
Return ranked candidates for a resource name or fragment.
```console theme={null}
$ annie graph query "SELECT * FROM resolve WHERE term = checkout LIMIT 10"
```
## resource\_details
Read one current graph resource by exact stable ID with safe properties and bounded relationships.
Result intent: `resource`
Aliases: `resource_detail`, `details`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ------ | ------ | -------- | --------------- | ------------------------------ |
| `id` | string | Yes | Any string | Exact hashedID or Anyshift ID. |
### Exact resource details
Return one resource by stable graph identity; names and fuzzy selectors are not accepted.
```console theme={null}
$ annie graph query "SELECT * FROM resource_details WHERE id = 'pagerduty/escalation-policy/PQ3UO6W' LIMIT 100"
```
## events
Read the infrastructure change-event timeline.
Result intent: `events`
Aliases: `event`
Modifiers: `LIMIT`, `OFFSET`
| Filter | Type | Required | Accepted values | Description |
| ----------- | -------- | -------- | ------------------------------------------------------------------------------ | ---------------------------------------------------- |
| `type` | string | No | Any string | Event type or type fragment, such as oom or scaling. |
| `target` | string | No | Any string | Resource name or fragment. |
| `namespace` | string | No | Any string | Kubernetes namespace. |
| `noise` | enum | No | `signal` (aliases: `false`, `exclude`)
`all` (aliases: `true`, `include`) | Whether to include noisy events. |
| `since` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
### Recent resource events
Read recent events for a resource inside a time window.
```console theme={null}
$ annie graph query "SELECT * FROM events WHERE target = checkout AND since = 2h LIMIT 20"
```
## cloud\_events
Read evidence-backed AWS, Azure, and GCP change events without parsing summaries.
Result intent: `cloudevents`
Aliases: `cloudevents`, `cloud_event`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ------------- | -------- | -------- | ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| `provider` | enum | No | `aws`
`azure`
`gcp` | Cloud provider. |
| `scope` | string | No | Any string | Provider scope: AWS account, Azure subscription, or GCP project. |
| `region` | string | No | Any string | Cloud region or location. |
| `category` | enum | No | `security`
`identity`
`lifecycle`
`configuration`
`capacity`
`backup`
`other` | Normalized cloud-change category. |
| `type` | string | No | Any string | Exact normalized event type. Underscores are preserved. |
| `resource` | string | No | Any string | Exact ARN, ARM ID, graph id, or unambiguous resource name. |
| `actor` | string | No | Any string | Actor identity, name, or graph id. |
| `correlation` | string | No | Any string | Anyshift event-story correlation id. |
| `operation` | string | No | Any string | Provider-native operation id. |
| `stats` | enum | No | `exact`
`none` | Whether to calculate exact full-window statistics. |
| `noise` | enum | No | `signal` (aliases: `false`, `exclude`)
`all` (aliases: `true`, `include`, `raw`) | Whether to include high-noise evidence. |
| `diff` | enum | No | `false` (aliases: `no`, `none`)
`true` (aliases: `yes`, `include`) | Whether to include sanitized before/after values. |
| `since` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
| `cursor` | string | No | Any string | Opaque seek cursor returned by the previous page. |
### Recent cloud changes
Read a bounded provider-neutral cloud-change timeline.
```console theme={null}
$ annie graph query "SELECT * FROM cloud_events WHERE provider = aws AND category = security AND since = 24h LIMIT 50"
```
## cloud\_resources
Inspect current or recently deleted AWS, Azure, and GCP resources with freshness and provenance.
Result intent: `cloudresources`
Aliases: `cloudresources`, `cloud_inventory`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ------------ | -------- | -------- | ------------------------------------------ | -------------------------------------------------------------------- |
| `provider` | enum | No | `aws`
`azure`
`gcp` | Cloud provider. |
| `scope` | string | No | Any string | Provider scope: AWS account, Azure subscription, or GCP project. |
| `region` | string | No | Any string | Cloud region or location. |
| `type` | string | No | Any string | Provider resource type, such as EC2\_INSTANCE or COMPUTE\_INSTANCES. |
| `resource` | string | No | Any string | Exact native id, graph id, or unambiguous resource name. |
| `lifecycle` | enum | No | `alive`
`deleted`
`all` | Resource lifecycle. Defaults to alive. |
| `provenance` | enum | No | `managed`
`configured`
`unknown` | IaC provenance status. |
| `freshness` | enum | No | `fresh`
`stale`
`unknown` | Freshness verdict relative to max\_age. |
| `max_age` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
| `cursor` | string | No | Any string | Opaque seek cursor returned by the previous page. |
### Current cloud inventory
List provider resources with explicit freshness and provenance evidence.
```console theme={null}
$ annie graph query "SELECT * FROM cloud_resources WHERE provider = aws AND type = EC2_INSTANCE LIMIT 50"
```
## delivery\_events
Read commit, CI, release, and deployment evidence from the delivery graph.
Result intent: `deliveryevents`
Aliases: `deliveryevents`, `delivery`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ---------- | -------- | -------- | --------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| `stage` | enum | No | `commit`
`ci` (aliases: `pipeline`)
`release`
`deploy` (aliases: `deployment`) | Delivery stage. |
| `type` | string | No | Any string | Exact event type, such as event\_release or argocd\_synced. |
| `resource` | string | No | Any string | Exact graph id or unambiguous target name. |
| `actor` | string | No | Any string | Actor identity, name, or graph id. |
| `source` | string | No | Any string | Persisted event source. |
| `since` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
| `cursor` | string | No | Any string | Opaque seek cursor returned by the previous page. |
### Recent delivery activity
Read a bounded software-delivery timeline without inferring missing actors or commits.
```console theme={null}
$ annie graph query "SELECT * FROM delivery_events WHERE stage = release AND since = 7d LIMIT 50"
```
## provenance
Trace a resource to stored release, commit, and actor evidence.
Result intent: `provenance`
Aliases: `release_provenance`, `delivery_provenance`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ---------- | ------ | -------- | --------------- | ---------------------------------------------------------- |
| `resource` | string | Yes | Any string | Resource, repository, release, image, or service to trace. |
### Release provenance
Return only stored release-to-commit-to-actor evidence.
```console theme={null}
$ annie graph query "SELECT * FROM provenance WHERE resource = checkout LIMIT 20"
```
## ownership
Resolve observed GitHub user or team code ownership and contact identities.
Result intent: `ownership`
Aliases: `owners`, `code_ownership`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ---------- | ------ | -------- | --------------- | -------------------------------------------------------- |
| `resource` | string | Yes | Any string | Repository or resource whose observed owner is required. |
### Observed code ownership
Return OWNS\_CODE evidence and any linked people; missing edges remain unknown.
```console theme={null}
$ annie graph query "SELECT * FROM ownership WHERE resource = anyshift-io/checkout LIMIT 20"
```
## graph\_coverage
Inspect current node, relationship, bridge, and event evidence by graph source.
Result intent: `graphcoverage`
Aliases: `graphcoverage`, `source_coverage`
Modifiers: None
| Filter | Type | Required | Accepted values | Description |
| -------- | ---- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
| `source` | enum | No | `kubernetes` (aliases: `k8s`)
`cloud`
`github` (aliases: `scm`)
`datadog`
`tempo`
`dynatrace`
`victoria`
`grafana` | Source universe. |
### Graph source coverage
Report only observed graph evidence; absent does not imply configuration state.
```console theme={null}
$ annie graph query "SELECT * FROM graph_coverage"
```
## resources
Count and sample current resources of one graph resource type.
Result intent: `inventory`
Aliases: `resource`, `inventory`
Modifiers: `LIMIT`, `OFFSET`
| Filter | Type | Required | Accepted values | Description |
| -------- | ------ | -------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| `type` | string | Yes | Any string | Graph resource type, such as service or deployment. |
| `source` | enum | No | `cloud_api`
`terraform_state`
`evaluation`
`unknown` | Stored inventory provenance. The filter is applied before canonical deduplication. |
### Resource inventory
Return the inventory for one resource type.
```console theme={null}
$ annie graph query "SELECT * FROM resources WHERE type = deployment LIMIT 50"
```
## operational\_impact
Find potential operational impact through reviewed directional graph relationships.
Result intent: `impact`
Aliases: `potential_impact`
Modifiers: `LIMIT`, `OFFSET`
| Filter | Type | Required | Accepted values | Description |
| ---------- | ------- | -------- | --------------- | ----------------------------------------------------- |
| `resource` | string | Yes | Any string | Root resource whose potential impact to evaluate. |
| `depth` | integer | No | Any string | Maximum propagation depth from 1 to 3. Defaults to 2. |
### Potential operational impact
Return resources reachable through reviewed operational impact relationships.
```console theme={null}
$ annie graph query "SELECT * FROM operational_impact WHERE resource = checkout-db AND depth = 2 LIMIT 50"
```
## connections
Inspect direct upstream and downstream relationships for a resource.
Result intent: `connections`
Aliases: `connection`, `deps`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ---------- | ------ | -------- | --------------- | ---------------------------- |
| `resource` | string | Yes | Any string | Resource name or identifier. |
### Direct connections
Return the resource and its direct graph neighbors.
```console theme={null}
$ annie graph query "SELECT * FROM connections WHERE resource = checkout LIMIT 50"
```
## hotspots
Rank noisy resources, namespaces, alert rules, or alerting workloads.
Result intent: `hotspots`
Aliases: `hotspot`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ----------- | -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
| `type` | string | No | Any string | Event type or type fragment. |
| `by` | enum | No | `resource` (aliases: `resources`)
`namespace` (aliases: `namespaces`, `ns`)
`alertrule` (aliases: `alertrules`, `rule`)
`alertworkload` (aliases: `alertworkloads`, `workload`) | Ranking dimension. |
| `namespace` | string | No | Any string | Kubernetes namespace scope. |
| `noise` | enum | No | `signal` (aliases: `false`, `exclude`)
`all` (aliases: `true`, `include`) | Whether to include noisy events. |
| `since` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
### Resource hotspots
Rank resources by recent event activity.
```console theme={null}
$ annie graph query "SELECT * FROM hotspots WHERE by = resource AND since = 24h LIMIT 10"
```
## correlations
Reconstruct a correlated Anyshift event group around a target or correlation identifier.
Result intent: `correlations`
Aliases: `correlation`
Modifiers: None
| Filter | Type | Required | Accepted values | Description |
| -------- | -------- | -------- | --------------- | ------------------------------------------------ |
| `target` | string | No | Any string | Resource name or fragment. |
| `id` | string | No | Any string | Correlation identifier. |
| `type` | string | No | Any string | Optional event type filter. |
| `since` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
### Correlation by target
At least one of target or id is required; since bounds target resolution.
```console theme={null}
$ annie graph query "SELECT * FROM correlations WHERE target = checkout AND since = 2h"
```
### Correlation by id
Load one exact correlation group.
```console theme={null}
$ annie graph query "SELECT * FROM correlations WHERE id = incident-123"
```
## incidents
Deprecated alias for correlations. Reconstruct a correlated Anyshift event group around a target or correlation identifier.
Result intent: `incident`
Aliases: `incident`
Modifiers: None
> **Deprecated since v1.** Use `correlations` for new queries.
| Filter | Type | Required | Accepted values | Description |
| -------- | -------- | -------- | --------------- | ------------------------------------------------ |
| `target` | string | No | Any string | Resource name or fragment. |
| `id` | string | No | Any string | Correlation identifier. |
| `type` | string | No | Any string | Optional event type filter. |
| `since` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
### Incident by target
Deprecated. Prefer correlations. At least one of target or id is required; since bounds target resolution.
```console theme={null}
$ annie graph query "SELECT * FROM incidents WHERE target = checkout AND since = 2h"
```
### Incident by correlation id
Deprecated. Prefer correlations. Load one exact correlation group.
```console theme={null}
$ annie graph query "SELECT * FROM incidents WHERE id = incident-123"
```
## failures
Read recent failure-class infrastructure events.
Result intent: `failures`
Aliases: None
Modifiers: `LIMIT`, `OFFSET`
| Filter | Type | Required | Accepted values | Description |
| ----------- | -------- | -------- | --------------- | ------------------------------------------------ |
| `target` | string | No | Any string | Resource name or fragment. |
| `namespace` | string | No | Any string | Kubernetes namespace. |
| `since` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
### Recent failures
Read failures for a target, namespace, or the whole project.
```console theme={null}
$ annie graph query "SELECT * FROM failures WHERE namespace = commerce AND since = 2h LIMIT 20"
```
## deployments
Read recent workload deployments and image changes.
Result intent: `deployments`
Aliases: `deployment`, `rollouts`
Modifiers: `LIMIT`, `OFFSET`
| Filter | Type | Required | Accepted values | Description |
| ----------- | -------- | -------- | --------------- | ------------------------------------------------ |
| `target` | string | No | Any string | Workload name or fragment. |
| `namespace` | string | No | Any string | Kubernetes namespace. |
| `since` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
### Recent deployments
Read deployments for a target, namespace, or the whole project.
```console theme={null}
$ annie graph query "SELECT * FROM deployments WHERE namespace = commerce AND since = 24h LIMIT 20"
```
## audit
Read configuration, identity, and infrastructure audit events.
Result intent: `audit`
Aliases: `changes`
Modifiers: `LIMIT`, `OFFSET`
| Filter | Type | Required | Accepted values | Description |
| ----------- | -------- | -------- | --------------- | ------------------------------------------------ |
| `target` | string | No | Any string | Resource name or fragment. |
| `namespace` | string | No | Any string | Kubernetes namespace. |
| `type` | string | No | Any string | Audit event type or fragment, such as rbac. |
| `since` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
### RBAC audit
Read recent RBAC-related changes.
```console theme={null}
$ annie graph query "SELECT * FROM audit WHERE type = rbac AND since = 24h LIMIT 20"
```
## nodes
Read node lifecycle and capacity events.
Result intent: `nodes`
Aliases: `node`
Modifiers: `LIMIT`, `OFFSET`
| Filter | Type | Required | Accepted values | Description |
| -------- | -------- | -------- | --------------- | ------------------------------------------------ |
| `target` | string | No | Any string | Node name or fragment. |
| `since` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
### Node activity
Read recent node events.
```console theme={null}
$ annie graph query "SELECT * FROM nodes WHERE since = 6h LIMIT 20"
```
## deploy\_impact
Join recent deployments to the failures that followed them.
Result intent: `deployimpact`
Aliases: `impact`, `risky`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| -------- | -------- | -------- | --------------- | ------------------------------------------------ |
| `target` | string | No | Any string | Workload name or fragment. |
| `since` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
### Deployment impact
Rank recent deployment fallout or inspect one workload.
```console theme={null}
$ annie graph query "SELECT * FROM deploy_impact WHERE target = checkout AND since = 24h LIMIT 10"
```
## common\_cause
Find shared infrastructure or dependencies behind recent failures.
Result intent: `commoncause`
Aliases: `commoncause`, `cause`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ----------- | -------- | -------- | --------------- | ------------------------------------------------ |
| `namespace` | string | No | Any string | Kubernetes namespace scope. |
| `since` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
### Shared failure causes
Intersect recent failures by node, workload, datastore, and external dependency.
```console theme={null}
$ annie graph query "SELECT * FROM common_cause WHERE namespace = commerce AND since = 2h LIMIT 10"
```
## blast\_radius
Calculate the transitive workloads, pods, and services affected by a resource.
Result intent: `blast`
Aliases: `blast`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ---------- | ------ | -------- | --------------- | ------------------------------------- |
| `resource` | string | Yes | Any string | Starting resource name or identifier. |
### Resource blast radius
Walk impact outward from one resource.
```console theme={null}
$ annie graph query "SELECT * FROM blast_radius WHERE resource = shared-runtime-sa LIMIT 100"
```
## spof
Rank highly shared ConfigMaps, service accounts, or nodes by fan-in.
Result intent: `spof`
Aliases: `spofs`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ----------- | ------ | -------- | --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
| `kind` | enum | No | `configmap` (aliases: `configmaps`, `cm`)
`serviceaccount` (aliases: `serviceaccounts`, `sa`)
`node` (aliases: `nodes`) | Resource kind to rank. Defaults to configmap. |
| `namespace` | string | No | Any string | Kubernetes namespace scope. |
### Shared service accounts
Rank service accounts by dependent workloads and pods.
```console theme={null}
$ annie graph query "SELECT * FROM spof WHERE kind = serviceaccount LIMIT 10"
```
## orphans
Find unused or dangling Kubernetes resources.
Result intent: `orphans`
Aliases: `orphan`, `unused`, `dangling`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ----------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
| `kind` | enum | No | `configmap` (aliases: `configmaps`, `cm`)
`serviceaccount` (aliases: `serviceaccounts`, `sa`)
`role` (aliases: `roles`)
`replicaset` (aliases: `replicasets`, `rs`) | Resource kind to inspect. Defaults to configmap. |
| `namespace` | string | No | Any string | Kubernetes namespace scope. |
### Orphaned roles
Find roles with no observed consumers.
```console theme={null}
$ annie graph query "SELECT * FROM orphans WHERE kind = role AND namespace = commerce LIMIT 20"
```
## coverage
Find service, monitor, or metrics coverage gaps.
Result intent: `coverage`
Aliases: `blindspots`, `unmonitored`, `uncovered`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ----------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
| `kind` | enum | No | `service` (aliases: `services`, `workload`, `workloads`)
`monitor` (aliases: `monitors`)
`metrics` (aliases: `metric`) | Coverage dimension. Defaults to service. |
| `namespace` | string | No | Any string | Kubernetes namespace scope. |
### Monitoring gaps
Find unmonitored services in one namespace.
```console theme={null}
$ annie graph query "SELECT * FROM coverage WHERE kind = service AND namespace = commerce LIMIT 20"
```
## access
Inspect RBAC reach or rank over-privileged service accounts.
Result intent: `access`
Aliases: `rbac`, `permissions`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ---------- | ------ | -------- | ------------------------- | -------------------------------------------------------------------------------- |
| `resource` | string | No | Any string | Subject or role name in reach mode; optional namespace scope in privileged mode. |
| `mode` | enum | No | `reach`
`privileged` | Access analysis mode. Defaults to reach. |
### Subject reach
Reach mode requires resource.
```console theme={null}
$ annie graph query "SELECT * FROM access WHERE resource = ci-deployer"
```
### Privileged identities
Privileged mode can optionally scope resource to a namespace.
```console theme={null}
$ annie graph query "SELECT * FROM access WHERE mode = privileged LIMIT 10"
```
## exposure
Trace bidirectional stored public-exposure routes and attached controls for one resource.
Result intent: `exposure`
Aliases: `exposed`, `attack_surface`
Modifiers: `LIMIT`
Selector: exactly one of `resource`, `resource_id`; non-empty: `resource`, `resource_id`, `resource_type`, `resource_namespace`, `resource_cluster`, `cursor`.
| Filter | Type | Required | Accepted values | Description |
| -------------------- | ------ | -------- | ---------------- | ------------------------------------------------------------------------------------------------ |
| `resource` | string | No | Non-empty string | Non-empty resource name or FQDN; exactly one of resource and resource\_id is required. |
| `resource_id` | string | No | Non-empty string | Non-empty stable graph or provider id; cannot be combined with resource or name qualifiers. |
| `resource_type` | string | No | Non-empty string | Non-empty name-only qualifier; requires resource and sets exact selection. |
| `resource_namespace` | string | No | Non-empty string | Non-empty name-only qualifier; requires resource and sets exact selection. |
| `resource_cluster` | string | No | Non-empty string | Non-empty name-only qualifier; requires resource and sets exact selection. |
| `cursor` | string | No | Non-empty string | Non-empty opaque seek cursor bound to the subject and perspective of the previous exposure page. |
### Public exposure by name
Resolve one name or FQDN and select the traversal perspective from that subject.
```console theme={null}
$ annie graph query "SELECT * FROM exposure WHERE resource = api.example.com"
```
### Public exposure by stable id
Bypass name resolution with one stable graph or provider identity.
```console theme={null}
$ annie graph query "SELECT * FROM exposure WHERE resource_id = 'cf://accounts/a/zones/z/hostnames/api.example.com'"
```
### Qualified exact public exposure
Use name-only qualifiers to force exact typed subject selection.
```console theme={null}
$ annie graph query "SELECT * FROM exposure WHERE resource = checkout AND resource_type = K8S_SERVICE AND resource_namespace = payments"
```
## tenancy
Find workloads co-located with a resource on the same node.
Result intent: `tenancy`
Aliases: `colocation`, `colocated`, `neighbors`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ---------- | ------ | -------- | --------------- | ---------------------------- |
| `resource` | string | Yes | Any string | Workload, pod, or node name. |
### Noisy neighbors
Inspect resources sharing a node with the target.
```console theme={null}
$ annie graph query "SELECT * FROM tenancy WHERE resource = checkout LIMIT 20"
```
## sharedconfig
Find workloads coupled through shared configuration.
Result intent: `sharedconfig`
Aliases: `shared_config`, `configsiblings`, `config_siblings`, `configcoupled`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ---------- | ------ | -------- | --------------- | ---------------------------------------- |
| `resource` | string | Yes | Any string | Workload or configuration resource name. |
### Shared configuration
Find workloads sharing configuration with the target.
```console theme={null}
$ annie graph query "SELECT * FROM sharedconfig WHERE resource = checkout LIMIT 20"
```
## path
Find the shortest infrastructure or operational path between two resources; both scopes include reviewed Cloudflare traffic edges.
Result intent: `path`
Aliases: `paths`
Modifiers: None
| Filter | Type | Required | Accepted values | Description |
| ---------------- | ------ | -------- | ----------------------------------- | -------------------------------------------------------------------------- |
| `from` | string | No | Any string | Starting resource name. Required unless from\_id is supplied. |
| `from_exact` | string | No | Any string | Set true for exact-name matching instead of legacy fuzzy resolution. |
| `from_id` | string | No | Any string | Exact starting hashedID or anyshiftID. |
| `from_type` | string | No | Any string | Exact starting resource label, such as K8S\_DEPLOYMENT. |
| `from_namespace` | string | No | Any string | Exact starting Kubernetes namespace. |
| `from_cluster` | string | No | Any string | Exact starting cluster name. |
| `to` | string | No | Any string | Destination resource name. Required unless to\_id is supplied. |
| `to_exact` | string | No | Any string | Set true for exact-name matching instead of legacy fuzzy resolution. |
| `to_id` | string | No | Any string | Exact destination hashedID or anyshiftID. |
| `to_type` | string | No | Any string | Exact destination resource label, such as TEMPO\_DATASTORE. |
| `to_namespace` | string | No | Any string | Exact destination Kubernetes namespace. |
| `to_cluster` | string | No | Any string | Exact destination cluster name. |
| `scope` | enum | No | `infrastructure`
`operational` | Relationships available to the path traversal. Defaults to infrastructure. |
### Shortest path
Each endpoint requires a name or id. Typed selectors resolve same-named resources deterministically.
```console theme={null}
$ annie graph query "SELECT * FROM path WHERE from = checkout-api AND from_type = K8S_DEPLOYMENT AND to = postgresql AND to_type = TEMPO_DATASTORE AND scope = operational"
```
## cascade
Trace an incident correlation group in propagation order.
Result intent: `cascade`
Aliases: `cascades`
Modifiers: None
| Filter | Type | Required | Accepted values | Description |
| -------- | -------- | -------- | --------------- | ------------------------------------------------ |
| `target` | string | No | Any string | Resource name or fragment. |
| `id` | string | No | Any string | Correlation identifier. |
| `since` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
### Cascade by target
At least one of target or id is required; since bounds target resolution.
```console theme={null}
$ annie graph query "SELECT * FROM cascade WHERE target = checkout AND since = 2h"
```
### Cascade by correlation id
Trace one exact correlation group.
```console theme={null}
$ annie graph query "SELECT * FROM cascade WHERE id = incident-123"
```
## alert\_impact
Find monitors and SLOs affected by a resource failure.
Result intent: `alertimpact`
Aliases: `alertimpact`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ---------- | ------ | -------- | --------------- | ----------------------------- |
| `resource` | string | Yes | Any string | Infrastructure resource name. |
### Alert impact
Map an infrastructure resource to affected observability objects.
```console theme={null}
$ annie graph query "SELECT * FROM alert_impact WHERE resource = checkout"
```
## monitor
Resolve a monitor to the infrastructure it observes.
Result intent: `monitor`
Aliases: `monitors`
Modifiers: None
| Filter | Type | Required | Accepted values | Description |
| -------- | ------ | -------- | --------------- | ------------------------- |
| `target` | string | Yes | Any string | Monitor name or fragment. |
### Monitor infrastructure
Map one monitor to its service, workload, and node.
```console theme={null}
$ annie graph query "SELECT * FROM monitor WHERE target = checkout-latency"
```
## datastore
Inspect datastore dependencies or rank widely used datastores.
Result intent: `datastore`
Aliases: `datastores`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| -------- | ------ | -------- | --------------------------------------------------- | ---------------------------------------- |
| `target` | string | No | Any string | Service or datastore name. |
| `source` | enum | No | `auto`
`datadog`
`tempo`
`dynatrace` | APM dependency source. Defaults to auto. |
### Rank datastores
Omit target to rank datastore fan-in.
```console theme={null}
$ annie graph query "SELECT * FROM datastore LIMIT 10"
```
### Datastore dependencies
Inspect services connected to one datastore or datastores used by one service.
```console theme={null}
$ annie graph query "SELECT * FROM datastore WHERE target = checkout-postgres"
```
## flow
Inspect stream producers and consumers or rank busy streams.
Result intent: `flow`
Aliases: `flows`, `stream`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| -------- | ------ | -------- | --------------------------------------------------- | ---------------------------------------- |
| `target` | string | No | Any string | Service, topic, queue, or stream name. |
| `source` | enum | No | `auto`
`datadog`
`tempo`
`dynatrace` | APM dependency source. Defaults to auto. |
### Stream dependencies
Inspect producers and consumers for a stream.
```console theme={null}
$ annie graph query "SELECT * FROM flow WHERE target = checkout-events"
```
## external\_dep
Inspect external dependencies or rank high-fan-in external hosts.
Result intent: `externaldep`
Aliases: `externaldep`, `external`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| -------- | ------ | -------- | --------------------------------------------------- | ---------------------------------------- |
| `target` | string | No | Any string | Service or external dependency name. |
| `source` | enum | No | `auto`
`datadog`
`tempo`
`dynatrace` | APM dependency source. Defaults to auto. |
### External dependencies
Inspect services depending on one external host.
```console theme={null}
$ annie graph query "SELECT * FROM external_dep WHERE target = payments.example.com"
```
## alerts
List normalized operational alerts while retaining legacy Datadog firing-monitor fields.
Result intent: `alerts`
Aliases: `alert`, `firing`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| --------------------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| `target` | string | No | Any string | Legacy Datadog service or workload name. |
| `provider` | enum | No | `pagerduty` (aliases: `pd`)
`datadog` (aliases: `dd`)
`grafana`
`victoria`
`dynatrace`
`newrelic` (aliases: `new_relic`)
`incidentio` (aliases: `incident_io`) | Operational evidence provider. |
| `status` | enum | No | `firing` (aliases: `open`, `triggered`)
`recovered` (aliases: `resolved`)
`suppressed`
`unknown`
`all` | Canonical alert state. Defaults to firing. |
| `severity` | enum | No | `critical`
`warning`
`info`
`unknown` | Canonical alert severity. |
| `service_id` | string | No | Any string | Exact stable identity of a canonical graph service. |
| `service` | string | No | Any string | Exact canonical graph service name. |
| `service_type` | string | No | Any string | Exact canonical graph service label. |
| `service_namespace` | string | No | Any string | Exact canonical service namespace. |
| `service_cluster` | string | No | Any string | Exact canonical service cluster. |
| `provider_service_id` | string | No | Any string | Exact provider-native service identifier. |
| `since` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
| `from` | string | No | Any string | Absolute RFC3339 lower time bound. |
| `to` | string | No | Any string | Absolute RFC3339 upper time bound. |
| `at` | string | No | Any string | Absolute RFC3339 point in time, or now. |
| `cursor` | string | No | Any string | Opaque keyset cursor returned by a previous page. |
### Current alerts
List firing operational alerts; legacy Datadog fields remain additive siblings.
```console theme={null}
$ annie graph query "SELECT * FROM alerts WHERE status = firing LIMIT 20"
```
## response\_incidents
List provider-neutral response incidents that coordinate alert handling.
Result intent: `responseincidents`
Aliases: `response_incident`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| --------------------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| `provider` | enum | No | `pagerduty` (aliases: `pd`)
`datadog` (aliases: `dd`)
`grafana`
`victoria`
`dynatrace`
`newrelic` (aliases: `new_relic`)
`incidentio` (aliases: `incident_io`) | Operational evidence provider. |
| `status` | enum | No | `active`
`open` (aliases: `triggered`)
`acknowledged` (aliases: `acked`)
`resolved` (aliases: `closed`)
`unknown`
`all` | Canonical response-incident state. Defaults to open and acknowledged. |
| `service_id` | string | No | Any string | Exact stable identity of a canonical graph service. |
| `service` | string | No | Any string | Exact canonical graph service name. |
| `service_type` | string | No | Any string | Exact canonical graph service label. |
| `service_namespace` | string | No | Any string | Exact canonical service namespace. |
| `service_cluster` | string | No | Any string | Exact canonical service cluster. |
| `provider_service_id` | string | No | Any string | Exact provider-native service identifier. |
| `since` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
| `from` | string | No | Any string | Absolute RFC3339 lower time bound. |
| `to` | string | No | Any string | Absolute RFC3339 upper time bound. |
| `at` | string | No | Any string | Absolute RFC3339 point in time, or now. |
| `cursor` | string | No | Any string | Opaque keyset cursor returned by a previous page. |
| `responder` | string | No | Any string | Exact display name, canonical person ID or email, or provider user ID. |
| `urgency` | string | No | Any string | Provider urgency value; preserved as provider-specific evidence. |
### Active response incidents
List open or acknowledged incidents from stored graph evidence.
```console theme={null}
$ annie graph query "SELECT * FROM response_incidents WHERE provider = pagerduty LIMIT 50"
```
## oncall
List effective on-call responsibility for a point in time or bounded window.
Result intent: `oncall`
Aliases: `on_call`, `oncalls`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| --------------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| `provider` | enum | No | `pagerduty` (aliases: `pd`)
`datadog` (aliases: `dd`)
`grafana`
`victoria`
`dynatrace`
`newrelic` (aliases: `new_relic`)
`incidentio` (aliases: `incident_io`) | Operational evidence provider. |
| `status` | enum | No | `scheduled`
`active`
`ended`
`all` | Canonical on-call window state. |
| `service_id` | string | No | Any string | Exact stable identity of a canonical graph service. |
| `service` | string | No | Any string | Exact canonical graph service name. |
| `service_type` | string | No | Any string | Exact canonical graph service label. |
| `service_namespace` | string | No | Any string | Exact canonical service namespace. |
| `service_cluster` | string | No | Any string | Exact canonical service cluster. |
| `provider_service_id` | string | No | Any string | Exact provider-native service identifier. |
| `from` | string | No | Any string | Absolute RFC3339 lower time bound. |
| `to` | string | No | Any string | Absolute RFC3339 upper time bound. |
| `at` | string | No | Any string | Absolute RFC3339 point in time, or now. |
| `cursor` | string | No | Any string | Opaque keyset cursor returned by a previous page. |
| `person` | string | No | Any string | Exact source identity or canonical person identity. |
| `schedule` | string | No | Any string | Exact provider schedule identifier. |
### Current on-call
List effective on-call windows at the selected point in time.
```console theme={null}
$ annie graph query "SELECT * FROM oncall WHERE at = now LIMIT 50"
```
## incident\_context
Group stored incident, alert, service, on-call, responder, and reviewed history hops without live provider calls.
Result intent: `incidentcontext`
Aliases: `incidentcontext`
Modifiers: `LIMIT`
Selector: exactly one of `id`, `target`; non-empty: `id`, `target`.
| Filter | Type | Required | Accepted values | Description |
| ---------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| `id` | string | No | Non-empty string | Exact provider incident ID or Anyshift incident ID. |
| `target` | string | No | Non-empty string | Exact canonical resource name, Anyshift ID, hashed ID, or provider service identity. |
| `provider` | enum | No | `pagerduty` (aliases: `pd`)
`datadog` (aliases: `dd`)
`grafana`
`victoria`
`dynatrace`
`newrelic` (aliases: `new_relic`)
`incidentio` (aliases: `incident_io`) | Operational evidence provider. |
| `since` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
### Incident context by provider id
Exactly one of id or target is required. History uses stored similar incidents and reviewed resolution evidence.
```console theme={null}
$ annie graph query "SELECT * FROM incident_context WHERE id = Q2Q5QBE019PJM5 LIMIT 10"
```
### Incident context by mapped service
Resolve the latest stored incident that AFFECTS a PagerDuty service with RESOLVES\_TO the named resource.
```console theme={null}
$ annie graph query "SELECT * FROM incident_context WHERE target = checkout AND since = 30d LIMIT 10"
```
## alert\_noise
Rank flapping or stuck monitors.
Result intent: `alertnoise`
Aliases: `alertnoise`, `noise`, `flapping`, `noisy`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| -------- | -------- | -------- | ----------------------------------------- | ------------------------------------------------ |
| `target` | string | No | Any string | Monitor or service name. |
| `kind` | enum | No | `flapping` (aliases: `flap`)
`stuck` | Noise pattern. |
| `since` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
### Flapping alerts
Rank recently flapping monitors.
```console theme={null}
$ annie graph query "SELECT * FROM alert_noise WHERE kind = flapping AND since = 1d LIMIT 10"
```
## calls
Inspect APM service callers, callees, and HTTP route evidence or rank call-graph fan-in.
Result intent: `calls`
Aliases: `call`, `callgraph`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| -------- | ------ | -------- | --------------------------------------------------- | ---------------------------------------- |
| `target` | string | No | Any string | Service name. |
| `source` | enum | No | `auto`
`datadog`
`tempo`
`dynatrace` | APM dependency source. Defaults to auto. |
### Service calls
Inspect callers, callees, and available templated HTTP operations for one service.
```console theme={null}
$ annie graph query "SELECT * FROM calls WHERE target = checkout"
```
## servicetree
Expand a service's downstream services, datastores, and external dependencies.
Result intent: `servicetree`
Aliases: `service_tree`, `footprint`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| -------- | ------ | -------- | --------------------------------------------------- | ---------------------------------------- |
| `target` | string | No | Any string | Root service name. |
| `source` | enum | No | `auto`
`datadog`
`tempo`
`dynatrace` | APM dependency source. Defaults to auto. |
### Service tree
Expand the downstream footprint of one service.
```console theme={null}
$ annie graph query "SELECT * FROM servicetree WHERE target = checkout LIMIT 50"
```
## alert\_cause
Join a firing service or workload to recent Kubernetes changes.
Result intent: `alertcause`
Aliases: `alertcause`, `rootcause`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| -------- | -------- | -------- | --------------- | ------------------------------------------------ |
| `target` | string | Yes | Any string | Service or workload name. |
| `since` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
### Alert cause
Find recent infrastructure changes behind a firing target.
```console theme={null}
$ annie graph query "SELECT * FROM alert_cause WHERE target = checkout AND since = 2h LIMIT 20"
```
## slo
Inspect one SLO or rank breaching and at-risk SLOs.
Result intent: `slo`
Aliases: `slos`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| -------- | ------ | -------- | --------------- | --------------------- |
| `target` | string | No | Any string | SLO name or fragment. |
### SLO health
Inspect one SLO by name.
```console theme={null}
$ annie graph query "SELECT * FROM slo WHERE target = 'checkout availability'"
```
## alertrules
Inspect Grafana and VictoriaMetrics alert-rule coverage and inventory.
Result intent: `alertrules`
Aliases: `alert_rules`, `grafana`, `victoria`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ----------- | ------ | -------- | --------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| `subject` | enum | No | `coverage`
`inventory` (aliases: `inventories`)
`target` (aliases: `targets`) | Alert-rule view. Defaults to coverage. |
| `namespace` | string | No | Any string | Namespace scope for coverage or inventory. |
| `target` | string | No | Any string | Service or workload name. Required when subject is target. |
### Alert-rule coverage
Find services or workloads without alert rules.
```console theme={null}
$ annie graph query "SELECT * FROM alertrules WHERE subject = coverage AND namespace = commerce LIMIT 20"
```
### Rules for a target
Target subject requires target.
```console theme={null}
$ annie graph query "SELECT * FROM alertrules WHERE subject = target AND target = checkout"
```
## iac
Inspect Terraform code-to-state-to-cloud provenance and linkage coverage.
Result intent: `iac`
Aliases: `terraform`, `iac_provenance`
Modifiers: `LIMIT`, `OFFSET`
| Filter | Type | Required | Accepted values | Description |
| ----------- | -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| `resource` | string | No | Any string | Terraform address or Terraform, state, or cloud graph identifier. |
| `status` | enum | No | `managed`
`unlinked`
`missing_cloud` (aliases: `missingcloud`, `state_only`)
`ambiguous`
`stale`
`invalid` | IaC linkage status. |
| `freshness` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
### IaC coverage
Summarize Terraform code-to-state-to-cloud linkage and return a bounded resource page.
```console theme={null}
$ annie graph query "SELECT * FROM iac LIMIT 50"
```
### Resource provenance
Show one resource's Terraform, state, and cloud evidence. Exact state/cloud identifiers select their relationship chain; a generic Terraform declaration keeps all instances.
```console theme={null}
$ annie graph query "SELECT * FROM iac WHERE resource = aws_instance.api_server"
```
### IaC linkage gaps
List resources with one evidence-backed linkage status.
```console theme={null}
$ annie graph query "SELECT * FROM iac WHERE status = unlinked LIMIT 50"
```
## iac\_drift
Compare last-applied Terraform state with fresh observed cloud properties.
Result intent: `iacdrift`
Aliases: `terraform_drift`, `drift`
Modifiers: `LIMIT`, `OFFSET`
| Filter | Type | Required | Accepted values | Description |
| ----------- | -------- | -------- | --------------------------------------------------------------------- | ----------------------------------------------------------------- |
| `resource` | string | No | Any string | Terraform address or Terraform, state, or cloud graph identifier. |
| `status` | enum | No | `drifted`
`in_sync` (aliases: `insync`, `synced`)
`unknown` | Drift verdict. |
| `freshness` | duration | No | Any string | Relative lookback such as 30m, 2h, 1d, or today. |
### Current IaC drift
List supported state-to-cloud differences, excluding unknown evidence by default.
```console theme={null}
$ annie graph query "SELECT * FROM iac_drift WHERE status = drifted LIMIT 50"
```
### Resource drift
Evaluate one Terraform resource using its state and cloud evidence.
```console theme={null}
$ annie graph query "SELECT * FROM iac_drift WHERE resource = aws_instance.api_server"
```
## gitops
Inspect GitOps drift, unmanaged workloads, or resource ownership.
Result intent: `gitops`
Aliases: `argocd`, `gitops_drift`, `argocd_drift`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ----------- | ------ | -------- | --------------------------------------------------------------------------------- | ---------------------------------------------- |
| `subject` | enum | No | `drift` (aliases: `drifted`)
`unmanaged`
`owner` (aliases: `ownership`) | GitOps view. Defaults to drift. |
| `namespace` | string | No | Any string | Namespace scope for drift or unmanaged views. |
| `resource` | string | No | Any string | Workload name. Required when subject is owner. |
### GitOps drift
List drifted applications, optionally scoped to a namespace.
```console theme={null}
$ annie graph query "SELECT * FROM gitops WHERE subject = drift AND namespace = commerce LIMIT 20"
```
### Resource owner
Owner subject requires resource.
```console theme={null}
$ annie graph query "SELECT * FROM gitops WHERE subject = owner AND resource = checkout"
```
## image
Inspect image usage, workload containers, or container hygiene gaps.
Result intent: `image`
Aliases: `images`, `containers`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ----------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------- |
| `target` | string | No | Any string | Image, service, or workload name. |
| `workload` | string | No | Any string | Workload whose container resources should be inspected. |
| `digest` | string | No | Any string | Exact running image digest (sha256, repository digest, or runtime image ID). |
| `kind` | enum | No | `nomemlimit` (aliases: `no_mem_limit`, `nomemorylimit`)
`nocpurequest` (aliases: `no_cpu_request`)
`skew` (aliases: `versionskew`, `version_skew`) | Container hygiene scan. |
| `namespace` | string | No | Any string | Namespace scope for a hygiene scan. |
### Runtime digest usage
Find live containers and owning workloads running an exact image digest.
```console theme={null}
$ annie graph query "SELECT * FROM image WHERE digest = 'sha256:776129790f01a675bb6e98447c2a28d43a07144d5410691823dbf9a21d256b1e' LIMIT 50"
```
### Image usage
Inspect who runs an image or what image a target runs.
```console theme={null}
$ annie graph query "SELECT * FROM image WHERE target = checkout"
```
### Container hygiene
Kind selects a hygiene scan and namespace optionally scopes it.
```console theme={null}
$ annie graph query "SELECT * FROM image WHERE kind = nomemlimit AND namespace = commerce LIMIT 20"
```
## netpol
Inspect NetworkPolicy coverage, policies, or east-west reach.
Result intent: `netpol`
Aliases: `netpols`, `networkpolicy`, `segmentation`, `defaultallow`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ----------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| `mode` | enum | No | `uncovered` (aliases: `coverage`, `default_allow`, `defaultallow`)
`policy` (aliases: `policies`)
`segmentation` (aliases: `segment`) | Network policy view. Defaults to uncovered. |
| `namespace` | string | No | Any string | Namespace scope for uncovered or policy views. |
| `target` | string | No | Any string | Workload or policy name. Required for segmentation. |
### NetworkPolicy gaps
Find default-allow namespaces.
```console theme={null}
$ annie graph query "SELECT * FROM netpol WHERE mode = uncovered LIMIT 20"
```
### East-west reach
Segmentation mode requires target.
```console theme={null}
$ annie graph query "SELECT * FROM netpol WHERE mode = segmentation AND target = checkout"
```
## priority
Inspect scheduling priority gaps, the class ladder, or one target's priority.
Result intent: `priority`
Aliases: `priorityclass`, `preemption`, `nopriority`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ----------- | ------ | -------- | ------------------------------------------------------------------------------------------- | -------------------------------------------------------- |
| `kind` | enum | No | `nopriority` (aliases: `unprioritized`, `none`)
`ladder` (aliases: `classes`, `class`) | Priority view. |
| `namespace` | string | No | Any string | Namespace scope for missing-priority checks. |
| `target` | string | No | Any string | Workload or pod name whose priority should be inspected. |
### Missing priority classes
Find workloads without a priority class.
```console theme={null}
$ annie graph query "SELECT * FROM priority WHERE kind = nopriority AND namespace = commerce LIMIT 20"
```
### Target priority
Inspect the priority class for one workload or pod.
```console theme={null}
$ annie graph query "SELECT * FROM priority WHERE target = checkout"
```
## storage
Inspect workload storage and find orphaned or unclaimed volumes.
Result intent: `storage`
Aliases: `volumes`, `pv`, `pvc`, `storageclass`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ----------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------- |
| `mode` | enum | No | `footprint` (aliases: `workload`)
`orphanpv` (aliases: `orphanpvs`, `orphaned`, `orphan`)
`unclaimedpvc` (aliases: `unclaimedpvcs`, `unclaimed`)
`byclass` (aliases: `class`, `storageclass`) | Storage view. Defaults to footprint. |
| `workload` | string | No | Any string | Workload or pod name. Required in footprint mode. |
| `resource` | string | No | Any string | Alias for workload in footprint mode. |
| `class` | string | No | Any string | StorageClass filter for orphanpv or byclass mode. |
| `namespace` | string | No | Any string | Namespace scope for unclaimedpvc mode. |
### Workload storage
Footprint mode requires workload or resource.
```console theme={null}
$ annie graph query "SELECT * FROM storage WHERE workload = checkout"
```
### Unclaimed PVCs
Find unclaimed claims, optionally scoped to a namespace.
```console theme={null}
$ annie graph query "SELECT * FROM storage WHERE mode = unclaimedpvc AND namespace = commerce LIMIT 20"
```
## pdb
Find workloads without PodDisruptionBudgets or inspect one workload or PDB.
Result intent: `pdb`
Aliases: `pdbs`, `unprotected`, `disruption`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ---------- | ------ | -------- | --------------- | ------------------------- |
| `target` | string | No | Any string | Workload or PDB name. |
| `workload` | string | No | Any string | Workload name. |
| `pdb` | string | No | Any string | PodDisruptionBudget name. |
### PDB coverage gaps
Omit filters to list workloads without PDB protection.
```console theme={null}
$ annie graph query "SELECT * FROM pdb LIMIT 20"
```
### Target PDB coverage
Inspect one workload or PDB by target, workload, or pdb.
```console theme={null}
$ annie graph query "SELECT * FROM pdb WHERE workload = checkout"
```
## scaling
Find workloads without HPAs, list autoscaled workloads, or inspect one target.
Result intent: `scaling`
Aliases: `hpa`, `hpas`, `autoscaling`, `autoscalers`
Modifiers: `LIMIT`
| Filter | Type | Required | Accepted values | Description |
| ----------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- |
| `mode` | enum | No | `nohpa` (aliases: `no_hpa`, `unscaled`, `fixed`, `coverage`)
`autoscaled` (aliases: `hpa`, `scaled`)
`target` | Autoscaling view. Defaults to nohpa. |
| `namespace` | string | No | Any string | Namespace scope for nohpa or autoscaled views. |
| `target` | string | No | Any string | Workload or HPA name. Required in target mode. |
### Autoscaling gaps
Find workloads without HPAs.
```console theme={null}
$ annie graph query "SELECT * FROM scaling WHERE mode = nohpa AND namespace = commerce LIMIT 20"
```
### Target autoscaling
Target mode requires target.
```console theme={null}
$ annie graph query "SELECT * FROM scaling WHERE target = checkout"
```
## topology
Build a typed service topology at a selected level.
Result intent: `topology`
Aliases: `diagram`, `c4`
Modifiers: None
| Filter | Type | Required | Accepted values | Description |
| ------------ | ------ | -------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------- |
| `service` | string | Yes | Any string | Service or workload name. |
| `level` | enum | No | `context`
`container`
`component`
`dynamic` | Topology level. Defaults to container. |
| `source` | enum | No | `auto`
`datadog`
`tempo`
`dynatrace`
`configuration` | Topology evidence source. Defaults to auto-discovered APM evidence. |
| `endpoint` | string | No | Any string | Explicit endpoint alias used to prove a configured dependency. |
| `dependency` | string | No | Any string | Catalog service name represented by the endpoint alias. |
### Service topology
Service is required; level selects the topology depth.
```console theme={null}
$ annie graph query "SELECT * FROM topology WHERE service = checkout AND level = context"
```
## Use the catalog programmatically
The OpenAPI document exposes this catalog under the root `x-anyshift-query-language` extension. Tooling can read that versioned object to generate completion, validation, documentation, or custom query builders without duplicating the language by hand.
For typed TypeScript helpers, see [Graph SDK Capabilities](/pages/product/integration/sdk_capabilities). For raw query execution and error handling, see the [Graph SDK guide](/pages/product/integration/sdk#raw-sql).
# Plugin
Source: https://docs.anyshift.io/pages/product/integration/production_intelligence_agent_plugin
Give coding agents read-only production context from Anyshift's live graph.
The **plugin** gives your coding agent read-only production context while it reviews code, prepares a deployment, investigates an incident, or explains architecture. It combines [Graph MCP](/pages/product/integration/graph_mcp) with an Agent Skill that teaches the agent how to gather and interpret that evidence, plus Cypher recipes for the common analyses.
The package follows [Agent Plugins `1.0.0`](https://agent-plugins.org/) and connects to Graph MCP over [MCP `2026-07-28`](https://modelcontextprotocol.io/specification/2026-07-28). It contains no API token, project identifier, authorization header, or database name.
**v0.3.0 (2026-09-08) changes the MCP endpoint and the tool set.** The plugin now connects to `https://api.anyshift.io/mcp/graph` and exposes ten tools over the live event graph. Older installs keep working against the previous endpoint but do not receive the new tools. To update: Codex users re-add the marketplace at `--ref v0.3.0` and run `codex mcp login agent-plugin`; Cursor users run `git pull --ff-only` in their checkout, which also updates the packaged MCP entry; Claude Code users on the earlier manual setup must switch to the native install below (or re-register the endpoint: `claude mcp remove agent-plugin`, then `claude mcp add --transport http --scope user agent-plugin https://api.anyshift.io/mcp/graph` and `claude mcp login agent-plugin`), because `git pull` only refreshes the skill and leaves the old MCP entry in place. In every case authorize once: the new endpoint is a new MCP entry.
## Install
Choose your coding agent below. Compatible Agent Plugins clients install the package directly; clients such as Claude Code load the same Agent Skill and Graph MCP connection separately. During the first Graph MCP connection, sign in to Anyshift, select the project the agent may read, and approve access. The client stores the resulting credentials.
Update Codex CLI before installing:
```bash theme={null}
codex plugin marketplace add anyshift-io/agent-plugin --ref v0.3.0
codex plugin add agent-plugin@anyshift
codex mcp add agent-plugin --url https://api.anyshift.io/mcp/graph
codex mcp login agent-plugin
```
`codex mcp add` only registers the server; `codex mcp login` starts the Graph MCP OAuth flow. Sign in, select the Anyshift project the agent may read, and start a new Codex task so the skill and MCP tools load together.
Codex currently requires the explicit `codex mcp add` command because installing a plugin-owned remote MCP entry does not start its OAuth flow automatically.
VS Code supports the Agent Plugins `1.0.0` package directly. Update VS Code, make sure GitHub Copilot Chat is enabled, and check that `chat.plugins.enabled` is set to `true`.
1. Open the Command Palette:
* macOS: `Shift+Command+P`
* Windows and Linux: `Ctrl+Shift+P`
2. Run **Chat: Install Plugin From Source**.
3. Paste the public repository URL:
```text theme={null}
https://github.com/anyshift-io/agent-plugin
```
4. Review the source and select **Install**.
5. Follow the browser prompt when VS Code starts Graph MCP.
VS Code discovers the packaged `plugin.json`, `mcp.json`, and `agent-plugin` skill. You do not need to copy the skill or add the MCP endpoint separately.
To verify the installation:
1. Run **Chat: Open Customizations** and confirm that `agent-plugin` is enabled under **Plugins**.
2. Check that `agent-plugin` appears under **Skills**.
3. Run **MCP: List Servers** and confirm that `agent-plugin` is running.
Invoke the skill directly in Copilot Chat when you want to force the evidence workflow:
```text theme={null}
/agent-plugin:agent-plugin
Before I deploy checkout-api, resolve the exact resource, inspect its direct
dependencies and transitive blast radius, and correlate relevant changes
from the last 24 hours. Separate graph evidence from inference.
```
Copilot can also select the skill automatically when a request concerns production dependencies, deployments, incidents, recent changes, or blast radius. See the [VS Code Agent Plugins guide](https://code.visualstudio.com/docs/agent-customization/agent-plugins) for plugin management and updates.
Cursor supports the Agent Plugins standard without package changes. Install the current package into Cursor's local plugin directory:
```bash theme={null}
git clone --depth 1 \
https://github.com/anyshift-io/agent-plugin.git \
~/.cursor/plugins/local/agent-plugin
```
Run **Developer: Reload Window**, then open **Customize** and confirm that the plugin, `agent-plugin` skill, and Graph MCP server are enabled. Follow the browser prompt to authorize the Anyshift project.
The package loads its skill and remote MCP configuration together. Do not also add the same Graph MCP endpoint to `~/.cursor/mcp.json`, because that registers the server twice.
For a centrally managed rollout, a Cursor administrator can import the same GitHub repository into a Team Marketplace and distribute it at user or project scope. See Cursor's [Plugins guide](https://cursor.com/docs/plugins) for Agent Plugin installation, management, and team distribution.
If local plugin loading is unavailable in your Cursor deployment, use the standalone Graph MCP configuration in the troubleshooting section. That fallback provides the tools but does not install the agent-plugin skill.
Install through Claude Code's plugin manager; it bundles the skill and the Graph MCP connection:
```text theme={null}
/plugin marketplace add anyshift-io/agent-plugin
/plugin install anyshift-graph@anyshift
```
Then run `/mcp`, select `plugin:anyshift-graph:Anyshift` and choose **Authenticate** (or, from a shell, `claude mcp login plugin:anyshift-graph:Anyshift`). Sign in and select the project the agent may read. Start a new session, then invoke `/anyshift-graph:agent-plugin` or ask a production-impact question and let Claude select the skill automatically. Update later with `/plugin update anyshift-graph@anyshift`.
If you installed the earlier manual way (a clone under `~/.claude/agent-plugin` with a symlinked skill and a `claude mcp add` entry), remove that skill symlink and MCP entry before installing the plugin, otherwise the skill and the tools appear twice.
See Anthropic's guides for [Agent Skills](https://docs.anthropic.com/en/docs/agents-and-tools/agent-skills/overview) and [remote MCP servers](https://docs.anthropic.com/en/docs/claude-code/mcp).
End-to-end production verification of v0.3.0 covers Claude Code (native plugin install and OAuth) and the endpoint itself. For other clients, confirm authentication, discovery of the ten tools, one authenticated read-only call, and uninstall behavior against the version your team deploys.
## What the plugin gives your agent
Use the plugin to:
* review a code or infrastructure change against current production dependencies;
* identify direct dependencies and bounded blast radius before a deployment;
* trace public-edge exposure paths, observed controls, and explicit evidence gaps;
* correlate recent changes with topology during an incident;
* explain how a repository fits into the current production architecture; and
* produce focused post-deployment checks from observed graph evidence.
Graph MCP supplies read-only tools over the live event graph: schema discovery, resource lookup and details, relationship walks, resource and project-wide change events, correlated event chains, project switching, and read-only Cypher. The packaged skill teaches the agent to discover the project's vocabulary first, read the completeness signals the tools return, separate observed evidence from inference and unknowns, and ships Cypher recipes for single points of failure, orphans, blast radius, public exposure, shortest paths, RBAC reach and Kubernetes hygiene gaps.
This is not an autonomous SRE agent or an incident-response loop. For Annie's full AI SRE investigation workflow, use [Annie Remote MCP](/pages/product/integration/remote_mcp).
## Try it
After installation, ask the agent to combine the code in your workspace with production evidence:
```text theme={null}
Review my current changes. Identify the production resources they affect using
Anyshift, then summarize direct dependencies, bounded blast radius, recent
related changes, post-deployment checks, and explicit unknowns.
```
Other useful starting points:
```text theme={null}
Before I change this database schema, identify the services that currently
depend on this datastore.
```
```text theme={null}
Explain how this repository fits into the current production architecture:
runtime resources, direct dependencies, datastores, and evidence timestamps.
```
## More clients
Kiro supports Agent Skills and remote HTTP MCP servers with browser OAuth. Configure the two components separately.
First, open **Agent Steering & Skills** in the Kiro panel, select **Import a skill**, choose **GitHub**, and paste:
```text theme={null}
https://github.com/anyshift-io/agent-plugin/tree/main/skills/agent-plugin
```
Then run **Kiro: Open user MCP config (JSON)** from the Command Palette and merge this entry into `~/.kiro/settings/mcp.json`:
```json theme={null}
{
"mcpServers": {
"agent-plugin": {
"url": "https://api.anyshift.io/mcp/graph",
"disabled": false
}
}
}
```
Save the file. Kiro reconnects automatically and opens the Anyshift authorization page when Graph MCP requests OAuth. Verify the connection in the **MCP servers** panel, then invoke `/agent-plugin` or ask a production-impact question.
See Kiro's [Agent Skills](https://kiro.dev/docs/skills/) and [MCP configuration](https://kiro.dev/docs/mcp/configuration/) guides.
This setup is for the xAI Grok Build coding agent, not the consumer Grok chat or bot.
```bash theme={null}
grok plugin install anyshift-io/agent-plugin
grok plugin install anyshift-io/agent-plugin --trust
grok mcp add --transport http agent-plugin \
https://api.anyshift.io/mcp/graph
grok inspect
```
Review the source and the capabilities Grok displays before using `--trust`. Start a new Grok session and complete browser OAuth on the first Graph MCP use. The skill is available as `/agent-plugin`. Run `grok mcp doctor agent-plugin` if the server does not connect.
See the Grok Build guides for [plugins](https://docs.x.ai/build/features/skills-plugins-marketplaces) and [MCP servers](https://docs.x.ai/build/features/mcp-servers).
Install the repository from inside a GitHub Copilot CLI session:
```text theme={null}
/plugins install anyshift-io/agent-plugin
/mcp show agent-plugin
```
If the server is listed as `needs-auth`, start the browser flow:
```text theme={null}
/mcp auth agent-plugin
```
If your Copilot version installs the skill but does not load the portable MCP entry, add the endpoint explicitly from your shell:
```bash theme={null}
copilot mcp add --transport http agent-plugin \
https://api.anyshift.io/mcp/graph
```
Start a new session after installation. Invoke `/agent-plugin/agent-plugin`, or ask Copilot to inspect production impact and let it select the skill automatically.
See GitHub's guides for [Copilot plugins](https://docs.github.com/en/copilot/concepts/agents/about-plugins) and [MCP servers](https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/add-mcp-servers).
OpenClaw loads the skill and remote MCP connection separately. Clone the current package, then install its skill for all local agents:
```bash theme={null}
git clone --depth 1 \
https://github.com/anyshift-io/agent-plugin.git
openclaw skills install \
./agent-plugin/skills/agent-plugin \
--global
```
Register and authorize Graph MCP:
```bash theme={null}
openclaw mcp add agent-plugin \
--url https://api.anyshift.io/mcp/graph \
--transport streamable-http \
--auth oauth
openclaw mcp login agent-plugin
openclaw mcp doctor agent-plugin --probe
```
Restart the relevant agent or Gateway if it was already running. Run `openclaw skills list` to confirm the skill loaded, then invoke `/agent-plugin` or ask the agent for production evidence.
See OpenClaw's [Skills](https://docs.openclaw.ai/tools/skills) and [MCP](https://docs.openclaw.ai/cli/mcp) guides.
Hermes supports Agent Skills and OAuth-authenticated HTTP MCP servers, but loads the two components separately. Clone the current package into a stable location:
```bash theme={null}
git clone --depth 1 \
https://github.com/anyshift-io/agent-plugin.git \
~/.hermes/agent-plugin
```
Merge these entries into `~/.hermes/config.yaml`:
```yaml theme={null}
skills:
external_dirs:
- ~/.hermes/agent-plugin/skills
mcp_servers:
agent-plugin:
url: "https://api.anyshift.io/mcp/graph"
auth: oauth
```
Complete OAuth and verify the connection from a fresh terminal:
```bash theme={null}
hermes mcp login agent-plugin
hermes mcp test agent-plugin
```
Start `hermes chat` and invoke `/agent-plugin`, or ask a production-impact question and let Hermes load the skill automatically.
See Hermes' [Skills](https://hermes-agent.nousresearch.com/docs/user-guide/features/skills) and [MCP](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) guides.
Load the public repository root in a client that supports Agent Plugins and the `streamable-http` MCP transport:
```text theme={null}
https://github.com/anyshift-io/agent-plugin
```
The client should discover `plugin.json`, `mcp.json`, and the packaged skill. Treat the client as unverified until you have tested installation, OAuth, discovery of the expected tools, one authenticated call, and uninstall behavior with the exact version you deploy.
## Verify the connection
A complete installation has all four of these signals:
1. The `agent-plugin` skill is visible to the agent.
2. `agent-plugin` is connected and authenticated.
3. The client discovers the ten tools: `describe_schema`, `find_resources`, `get_resource_details`, `get_related`, `get_resource_events`, `get_recent_events`, `get_correlated_events`, `query_graph`, `list_projects`, and `set_project`.
4. A read-only request returns project-scoped evidence with an evidence timestamp.
Use this focused verification prompt:
```text theme={null}
Use Anyshift to find checkout-api. Report the selected resource kind, namespace
and cluster, then list its direct relationships with their types and observation
timestamps. Do not infer missing relationships.
```
## Manage access and updates
* Update with your client's plugin manager: Codex `codex plugin marketplace add anyshift-io/agent-plugin --ref ` then `codex plugin add agent-plugin@anyshift`; Claude Code `/plugin update anyshift-graph@anyshift`; VS Code from **Chat: Open Customizations**. For manual Git checkouts (Cursor, Kiro, OpenClaw, Hermes), run `git pull --ff-only` in the package directory, then restart the client.
* A release that changes the MCP endpoint (such as v0.3.0) is a new MCP entry: authorize once after updating. Your previous authorization stays listed under **Authorized Apps** and can be revoked there.
* The installed version is the `version` field of the package's `plugin.json`; releases are listed at [`anyshift-io/agent-plugin`](https://github.com/anyshift-io/agent-plugin/releases).
* Start a new agent session after installing or updating so the current skill and MCP tools are loaded.
* Keep only one Graph MCP registration per client. Installing the package and configuring the same endpoint manually can create duplicate tools and separate OAuth state.
* View or revoke authorized MCP connections from your Anyshift [profile page](https://app.anyshift.io/my-profile) under **Authorized Apps**.
## Troubleshooting
Start authentication again from the MCP client and use the newly generated browser page. OAuth callback URLs are tied to the active client attempt; an old page can no longer complete a later connection.
Copy the fresh authorization URL shown by the client into a browser where you can sign in to Anyshift. This is common when the agent client runs over SSH or in a remote development environment. Keep the client process running until authorization completes.
Confirm that `agent-plugin` is enabled, complete OAuth, and start a new agent session. If the server still does not appear, use the client's MCP diagnostics to inspect its connection state.
Remove the standalone MCP entry when the Agent Plugin already supplies Graph MCP. Keep the package installation if you want both the tools and the agent-plugin skill.
Use Cursor's standalone Graph MCP entry as a fallback:
```bash theme={null}
cursor --add-mcp '{"name":"agent-plugin","url":"https://api.anyshift.io/mcp/graph"}'
```
Complete browser OAuth and start a new Agent chat. This fallback provides the Graph tools but does not install the agent-plugin skill.
Ask the agent to call `list_projects` and then `set_project` with the intended project; the switch applies to the existing connection without re-authenticating. To change the project a connection was consented for, revoke it from **Authorized Apps** on your Anyshift profile and authenticate again.
The package source, releases, validation instructions, and compatibility evidence are available in [`anyshift-io/agent-plugin`](https://github.com/anyshift-io/agent-plugin).
# Annie Remote MCP
Source: https://docs.anyshift.io/pages/product/integration/remote_mcp
Run Annie investigations from an AI coding assistant.
Annie Remote MCP lets AI coding assistants run Annie investigations over HTTP with OAuth authentication. No local dependencies or API tokens are required. Your editor handles login automatically.
Use Annie Remote MCP when you want the AI SRE agent to investigate infrastructure, analyze logs, debug incidents, and produce recommendations. If your agent needs fast, deterministic production graph evidence while it performs another task, use [Graph MCP](/pages/product/integration/graph_mcp) instead.
## Setup
### One-command install
Install across all your editors at once using [add-mcp](https://github.com/neondatabase/add-mcp):
```bash theme={null}
npx add-mcp https://api.anyshift.io/mcp/remote -n annie -g
```
This auto-detects your installed editors (Claude Code, Cursor, Windsurf, VS Code, Claude Desktop, etc.) and configures them all.
### Manual configuration
Add to your editor's MCP config file (e.g. `.cursor/mcp.json`, `~/.claude.json`, `claude_desktop_config.json`):
```json theme={null}
{
"mcpServers": {
"annie": {
"type": "http",
"url": "https://api.anyshift.io/mcp/remote"
}
}
}
```
## First Use
On your first Annie tool call, your editor will open a browser window:
1. Log in with your Anyshift account
2. The connection is established automatically
3. No tokens to copy — your editor stores the credentials
That's it. All subsequent tool calls are authenticated automatically.
## Available Tools
### Asking Annie
| Tool | Description |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ask_annie` | Ask a question about your cloud infrastructure. Pass `mode="rca"` to run a multi-step root-cause investigation instead of a chat. Pass `hint="report"` to format the answer as report blocks, or `hint="diagram"` for a Mermaid diagram. |
| `get_annie_response` | Poll for Annie's answer (called automatically by your editor) |
| `list_projects` | List your Anyshift projects |
| `set_project` | Switch the active project for queries |
### Custom Reports
After an `ask_annie` call with `hint="report"`, you can save the answer as a reusable report definition and re-run it later.
| Tool | Description |
| ------------------------- | -------------------------------------------------------------------------------------------- |
| `save_report_definition` | Save a report-shaped answer as a named definition |
| `list_report_definitions` | List the report definitions in the active project |
| `list_report_instances` | List past runs of a specific definition |
| `get_report_instance` | Fetch a generated report as markdown or JSON |
| `generate_report` | Trigger a fresh run of a definition. The backend dedupes if a generation is already pending. |
### Feedback
Ratings flow back into Annie so future investigations can take your judgment into account.
| Tool | Description |
| ---------------------------- | ------------------------------------------------------------------------------------------------------ |
| `submit_answer_feedback` | Thumbs up or down on a chat or RCA answer |
| `submit_hypothesis_feedback` | Thumbs up or down on a single hypothesis inside an RCA. The rating reaches the agent as a live update. |
## Pre-built skills for Claude Code
If your agent runs in [Claude Code](https://docs.anthropic.com/en/docs/claude-code), install the [Annie Skills plugin](/pages/product/integration/skills) to skip the prompt-engineering work. The plugin ships ready-made skills that teach Claude Code when to call which MCP tool, how to chain calls, and how to recover from auth or staleness failures. Source: [`anyshift-io/annie-skills`](https://github.com/anyshift-io/annie-skills).
This is separate from the [Plugin](/pages/product/integration/production_intelligence_agent_plugin), which packages Graph MCP and a portable production-evidence workflow for compatible agent clients.
## Example Prompts
```text theme={null}
Use Annie to investigate the spike in 5xx errors on the payments service
```
```text theme={null}
Ask Annie what changed in our infrastructure in the last 24 hours
```
```text theme={null}
Ask Annie to trace the dependency chain for the prod RDS instance
```
```text theme={null}
Ask Annie why the Lambda function can't connect to the database
```
Annie typically takes 30 seconds to a few minutes depending on the complexity of the question. Your editor will poll automatically until the answer is ready.
## Managing Access
You can view and revoke authorized MCP connections from your [profile page](https://app.anyshift.io/my-profile) under **Authorized Apps**.
## Troubleshooting
If your session expires, reset the connection and try again:
```bash theme={null}
# Claude Code
claude mcp reset annie
```
Your next Annie tool call will re-open the browser for login.
Make sure your default browser is set in your OS settings. If using a remote/SSH session, you may need to use the local stdio server instead.
This is normal — Annie is still working. The `get_annie_response` tool is called automatically by your editor until the answer is ready. Complex investigations can take a few minutes.
# Graph SDK
Source: https://docs.anyshift.io/pages/product/integration/sdk
Use the Anyshift Graph API from TypeScript applications, automation, and developer tools.
The Anyshift Graph SDK gives TypeScript applications a small, typed client for querying your infrastructure graph. Use it for dashboards, incident workflows, CI checks, deployment automation, or any service that needs direct graph answers without going through the Annie chat interface.
The first public SDK release is TypeScript. Python and Go SDKs will follow.
## Install
```bash theme={null}
npm install @anyshift/graph-sdk
```
The SDK works in Node.js 18+ and modern runtimes that provide `fetch`.
## Authenticate
Create an API token in Anyshift, then pass it with the project you want to query:
```ts theme={null}
import { GraphAnswer } from "@anyshift/graph-sdk";
const graph = new GraphAnswer({
token: process.env.ANYSHIFT_TOKEN!,
project: process.env.ANYSHIFT_PROJECT_ID!,
});
```
By default the SDK connects to `https://graph.anyshift.io`.
## Resolve a Resource
Use `graph.resolve()` to find current resources matching a name or fragment before running a resource-scoped helper. Results are ranked deterministically and include enough identity context to distinguish resources with similar names.
```ts theme={null}
const result = await graph.resolve({ term: "checkout", limit: 10 });
if (result.intent === "resolve") {
for (const candidate of result.resolve?.candidates ?? []) {
console.log(candidate.name, candidate.type, candidate.namespace);
}
}
```
Each candidate includes `id`, `anyshiftID`, `name`, `type`, `namespace`, and `cluster`. After selecting a candidate, pass its stable `id` to helpers such as `graph.connections()`, `graph.path()`, or `graph.blast()`.
Topology helpers fail closed when a fuzzy term has multiple equally authoritative matches. They do
not select the first candidate. Catch `BadQueryError`, show its bounded candidate set, and retry with
an explicit identity:
```ts theme={null}
import { BadQueryError } from "@anyshift/graph-sdk";
try {
await graph.connections({ resource: "three-tier-app" });
} catch (error) {
if (error instanceof BadQueryError && error.selectionCode === "ambiguous_resource") {
console.error(error.candidates);
// Retry after the caller selects a candidate.id.
}
}
```
For interactive terminal discovery, use [`annie graph explore`](/pages/product/integration/cli#deterministic-infrastructure-graph-queries).
## Query the Graph
Use typed helpers for common graph questions:
```ts theme={null}
const events = await graph.events({ since: "1h", limit: 10 });
console.log(events.summary);
```
```ts theme={null}
const blast = await graph.blast({ resource: "checkout" });
console.log(blast.summary);
```
```ts theme={null}
const path = await graph.path({ from: "checkout", to: "checkout-postgres" });
console.log(path.summary);
```
## Investigate GCP Operations
Use `cloudEvents()` to retrieve one provider-native operation without conflating it with the
broader Anyshift event story:
```ts theme={null}
const result = await graph.cloudEvents({
provider: "gcp",
operation: "operation-123",
diff: true,
});
if (result.intent === "cloudevents") {
for (const event of result.cloudEvents?.items ?? []) {
console.log({
operation: event.correlation.providerOperationId,
story: event.correlation.id,
source: event.evidence.source,
status: event.evidence.status,
});
}
}
```
Inspect current GCP inventory with explicit observation and IaC evidence:
```ts theme={null}
const inventory = await graph.cloudResources({
provider: "gcp",
lifecycle: "alive",
maxAge: "24h",
});
```
Provider operation IDs group provider-native activity. Anyshift correlation IDs group the broader
retained story. `audit`, `snapshot`, and `reconciliation` are distinct evidence sources. Current
producers exclude provider-rejected mutations because they did not change provider state, so their
absence does not prove that no rejected calls occurred. A retained legacy row can still be
`failed`; missing outcome evidence remains `unknown`, never inferred as success. Unknown provenance
does not mean unmanaged, and unknown freshness does not mean stale.
## Render Topology
Topology queries return graph nodes and edges. Convert them to Mermaid when you want to embed a diagram in a report, pull request, runbook, or incident update:
```ts theme={null}
import { GraphAnswer, toMermaid } from "@anyshift/graph-sdk";
const graph = new GraphAnswer({
token: process.env.ANYSHIFT_TOKEN!,
project: process.env.ANYSHIFT_PROJECT_ID!,
});
const topology = await graph.topology({
service: "checkout",
level: "container",
});
console.log(toMermaid(topology));
```
Use `level: "dynamic"` to render a sequence diagram. Other topology levels render as flowcharts.
## Raw SQL
For advanced use cases, call the Graph API query endpoint directly with Anyshift graph SQL:
```ts theme={null}
const result = await graph.query(
"SELECT * FROM connections WHERE resource = checkout"
);
console.log(result.summary);
```
Use the [Graph Query Language reference](/pages/product/integration/graph_query_language) to find every query target, filter, accepted value, alias, modifier, and valid form.
## Capabilities
The SDK covers dependency analysis, operational timelines, topology diagrams, Kubernetes safety, security exposure, observability gaps, service dependencies, and GitOps ownership.
See [Graph SDK Capabilities](/pages/product/integration/sdk_capabilities) for the developer-oriented overview, the [Graph Query Language reference](/pages/product/integration/graph_query_language) for raw query syntax, or the canonical [`CAPABILITIES.md`](https://github.com/anyshift-io/anyshift-graph-sdk/blob/main/CAPABILITIES.md) matrix in GitHub for every helper, intent, parameter family, and output category.
## Error Handling
The SDK throws typed errors for authentication, bad queries, and unexpected API responses:
```ts theme={null}
import { AuthError, BadQueryError, GraphAnswerError } from "@anyshift/graph-sdk";
try {
await graph.query("SELECT * FROM connections WHERE resource = checkout");
} catch (error) {
if (error instanceof AuthError) {
// Refresh or replace the API token.
} else if (error instanceof BadQueryError) {
// Fix the graph SQL or helper parameters.
} else if (error instanceof GraphAnswerError) {
// Inspect error.status, error.code, and error.message.
}
}
```
## Examples and Source
The SDK source, examples, and OpenAPI contract are available in the public GitHub repository: [`anyshift-io/anyshift-graph-sdk`](https://github.com/anyshift-io/anyshift-graph-sdk).
To add the same infrastructure context to a software catalog without building a custom interface, use the [Backstage integration](/pages/product/integration/backstage).
## Troubleshooting
Check that `ANYSHIFT_TOKEN` is set and that the token has access to the selected project.
Check that `ANYSHIFT_PROJECT_ID` points to the project you intend to query and that the project has completed ingestion.
Start with a broader helper such as `graph.events({ since: "24h" })` or `graph.connections({ resource: "" })`, then narrow the query once you confirm the exact service or resource name.
# SDK capabilities
Source: https://docs.anyshift.io/pages/product/integration/sdk_capabilities
What developers can build with the Graph API and TypeScript SDK.
The Graph SDK is a programmable interface to Anyshift's infrastructure graph. Use it when you need graph answers inside automation, dashboards, CI checks, incident workflows, deployment gates, or developer tools.
For the exhaustive source-of-truth matrix, see [`CAPABILITIES.md`](https://github.com/anyshift-io/anyshift-graph-sdk/blob/main/CAPABILITIES.md) in the SDK repository.
## Resource Discovery
| Goal | SDK helper | Use it for |
| ----------------------- | ------------------------- | ------------------------------------------------------------------------------- |
| Resolve a resource name | `graph.resolve({ term })` | Rank current resources matching a name or fragment before opening a drill-down. |
`graph.resolve()` returns the `resolve` intent with typed candidates containing resource identity, type, namespace, and cluster context. Use the selected candidate's stable `id` with resource-scoped helpers such as `graph.connections()`, `graph.path()`, or `graph.blast()`. If a fuzzy helper selector remains ambiguous, the SDK throws `BadQueryError` with `selectionCode: "ambiguous_resource"` and the bounded retry candidates instead of choosing one silently.
## Dependency and Impact Analysis
| Goal | SDK helper | Use it for |
| ----------------------------- | ---------------------- | ------------------------------------------------------------------------------------ |
| Find direct neighbors | `graph.connections()` | Show what is directly connected to a service, workload, node, config, or dependency. |
| Compute blast radius | `graph.blast()` | Estimate what is affected if a resource changes or fails. |
| Trace a path | `graph.path()` | Explain how two resources are connected. |
| Expand a service footprint | `graph.serviceTree()` | Build a downstream dependency tree for service reviews or incident prep. |
| Explain shared failure causes | `graph.commonCause()` | Find shared nodes or workloads behind recent failures. |
| Check deployment fallout | `graph.deployImpact()` | Rank risky recent deploys or inspect one workload's rollout impact. |
For dependencies derived from APM data, pass `source: "auto" | "datadog" | "tempo"` to `graph.serviceTree()`. Typed `graph.path()` selectors can connect an exact Kubernetes workload to a Tempo service or datastore with `scope: "operational"`. The equivalent terminal workflows are documented in the [Annie CLI guide](/pages/product/integration/cli#deterministic-infrastructure-graph-queries).
## Timelines and Change Feeds
| Goal | SDK helper | Use it for |
| --------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| Read recent graph events | `graph.events()` | Pull recent changes for a namespace, resource, event type, or time window. |
| Read cloud-provider changes | `graph.cloudEvents({ provider, operation })` | Filter AWS, Azure, or GCP evidence by exact provider operation while preserving Anyshift story correlation, source, status, and sanitized diffs. |
| Inspect cloud inventory | `graph.cloudResources({ provider })` | Read current or retained resources with lifecycle, observation freshness, and stored IaC provenance. |
| Find noisy resources | `graph.hotspots()` | Rank noisy resources, namespaces, alert rules, or alerting workloads. |
| Read failure events | `graph.failures()` | Feed failure timelines into automation or reports. |
| Read deployment events | `graph.deployments()` | Track rollouts and deployment activity. |
| Read audit activity | `graph.audit()` | Inspect config, identity, or infrastructure changes. |
| Trace incident cascades | `graph.cascade()` | Follow a correlated incident from trigger to impacted resources. |
For GCP activity, `operation` is the provider-native identifier and is distinct from the Anyshift
correlation ID returned on each event. Missing status, freshness, or provenance evidence stays
`unknown`; the SDK does not convert it into success, stale, or unmanaged.
## Topology and Diagrams
| Goal | SDK helper | Use it for |
| ---------------------- | ------------------ | -------------------------------------------------------------------------- |
| Build service topology | `graph.topology()` | Get typed graph nodes and edges for a service neighborhood. |
| Render Mermaid | `toMermaid()` | Embed topology diagrams in PRs, incident reports, runbooks, or dashboards. |
Topology supports `context`, `container`, `component`, and `dynamic` levels plus `source: "auto" | "datadog" | "tempo"`. Dynamic topology renders as a sequence diagram; the other levels render as flowcharts.
## Kubernetes Safety and Hygiene
| Goal | SDK helper | Use it for |
| ----------------------------- | ------------------ | ------------------------------------------------------------------------------------ |
| Find single points of failure | `graph.spof()` | Rank highly shared ConfigMaps, service accounts, or nodes. |
| Find orphaned resources | `graph.orphans()` | Detect unused ConfigMaps, service accounts, roles, or ReplicaSets. |
| Check PDB coverage | `graph.pdb()` | Find workloads that are unsafe during voluntary disruptions. |
| Check autoscaler coverage | `graph.scaling()` | Find workloads without HPAs or inspect what an HPA scales. |
| Check scheduling priority | `graph.priority()` | Find workloads without priority classes or inspect the preemption ladder. |
| Inspect persistent storage | `graph.storage()` | Trace PVC/PV/StorageClass usage and find orphaned or unclaimed storage. |
| Inspect image usage | `graph.image()` | Find who runs an image, inspect a workload's images, or run container hygiene scans. |
## Security and Exposure
| Goal | SDK helper | Use it for |
| ------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Inspect RBAC reach | `graph.access()` | Understand what a subject can do or who can reach a role. |
| Find over-privileged identities | `graph.access({ mode: "privileged" })` | Rank service accounts with broad or risky grants. |
| Inspect NetworkPolicy coverage | `graph.netpol()` | Detect default-allow namespaces, inspect policies, or model east-west reach. |
| Inspect public exposure | `graph.exposure()` | Map ingresses to services/workloads or find which ingress exposes a resource. Each path may include nullable `originReachability` for ALB/NLB security-group control vs Cloudflare ranges. See [Origin reachability](/pages/product/graph-api/origin-reachability). |
## Observability and Alerting
| Goal | SDK helper | Use it for |
| ------------------------------ | --------------------- | ------------------------------------------------------------------------------------------------------------ |
| Find monitoring gaps | `graph.coverage()` | Find workloads missing Datadog presence, monitors, or metrics shipping. |
| Map alert impact | `graph.alertImpact()` | Find which monitors and SLOs would fire if a resource is impacted. |
| Map monitors to infrastructure | `graph.monitor()` | Resolve a monitor to the service, workload, and node it watches. |
| Read active alerts | `graph.alerts()` | Pull normalized stored alerts across providers, optionally scoped to a canonical or provider-native service. |
| Read response incidents | `graph.incidents()` | Inspect active or historical incident coordination, responders, urgency, and service context. |
| Read on-call responsibility | `graph.onCall()` | Find effective on-call windows for a person, schedule, service, or point in time. |
| Find noisy alerts | `graph.alertNoise()` | Rank flapping or stuck monitors. |
| Explain alert cause | `graph.alertCause()` | Link a firing service to recent Kubernetes changes. |
| Inspect SLO health | `graph.slo()` | Rank breaching or at-risk SLOs, or inspect one named SLO. |
| Inspect Grafana/Victoria rules | `graph.alertRules()` | Find alert-rule coverage gaps, inventory rules, or inspect one target's rules. |
Operational-response helpers query evidence already stored in the graph; they do not call PagerDuty or another provider API. Coverage, freshness, unresolved identity, and unavailable responder evidence stay explicit in the typed response.
## Service Dependencies and Ownership
| Goal | SDK helper | Use it for |
| ------------------------------ | --------------------- | ----------------------------------------------------------------------------------------- |
| Inspect datastore dependencies | `graph.datastore()` | Find services using a datastore, or rank heavily used datastores. |
| Inspect stream dependencies | `graph.flow()` | Find producers and consumers for topics or streams. |
| Inspect external dependencies | `graph.externalDep()` | Find services depending on an external host. |
| Inspect service calls | `graph.calls()` | Find callers and callees for a service, or rank high-traffic services. |
| Inspect GitOps drift | `graph.gitops()` | Find drifted ArgoCD apps, unmanaged workloads, or a workload's owning app and repository. |
`graph.datastore()`, `graph.flow()`, `graph.externalDep()`, and `graph.calls()` also accept `source: "auto" | "datadog" | "tempo"`. Tempo mode reads services, calls, datastores, messaging destinations, external endpoints, and Kubernetes identity bridges derived from Grafana Tempo traces. It does not expose individual trace or span search.
## Choosing the Right Entry Point
Use typed helpers when you need deterministic automation. Use `graph.query()` when you want to compose a precise query from the [documented targets and filters](/pages/product/integration/graph_query_language). Use `graph.ask()` when the caller has a natural-language question and can accept server-side routing.
For full helper parameter details and underlying intent names, use the SDK repository's [`CAPABILITIES.md`](https://github.com/anyshift-io/anyshift-graph-sdk/blob/main/CAPABILITIES.md). For raw Graph Query Language syntax, use the [complete query reference](/pages/product/integration/graph_query_language).
# Slack
Source: https://docs.anyshift.io/pages/product/integration/slack
Ask questions and investigate incidents from Slack.
Annie is your infrastructure copilot, available directly in Slack. Ask questions about your cloud resources, get automatic incident analysis when alerts fire, and keep your team in the loop, all without leaving the conversation.
## Installation
Go to **Integrations → Slack** on the [Slack Integrations page](https://app.anyshift.io/integrations/messaging/slack).
Click **Install Slack App**, then authorize Annie in your workspace.
Annie discovers the channels it's added to. Invite it wherever you'd like it available.
If your organization uses **Channel Access** (see below), Annie only joins channels on the allowlist.
Assign each channel one Anyshift [project](/pages/product/project_management/overview) so Annie knows which integrations and knowledge to use.
If your organization runs multiple projects, assign one project per channel: Annie prompts users in Slack, or you set it from the Anyshift UI. Use `/switch-project` to change a channel's project directly in Slack. You can also connect multiple Slack workspaces to a single Anyshift organization.
## What you can do
Mention **@Annie** in any mapped channel to ask about cloud resources, Terraform, dependencies, and more. Annie answers in a thread, drawing on the integrations connected to that channel's project.
When a monitoring bot (Datadog, PagerDuty, etc.) posts an alert in a channel where Annie is registered on-call, Annie investigates and posts a threaded analysis: a summary, a timeline of related changes, the likely root cause, and recommended fixes. See [Root Cause Analysis](/pages/product/root_cause_analysis).
While Annie investigates, it posts real-time progress in the thread so your team can follow along without waiting for the final analysis.
Tailor Annie's responses with [Annie Automation](/pages/product/customization/instructions) rules, and use its **Slack identities** list to choose which users and bots Annie auto-processes vs. only answers when tagged. Keep Annie in focused channels (for example `#infra-alerts`) for a high signal-to-noise ratio.
## Register on-call bots
For Annie to investigate alerts automatically, register your monitoring bots (Datadog, PagerDuty, etc.) from any channel where Annie is present:
```bash theme={null}
/register_annie_on_call
```
The Slack ID can be a user (`U01234ABCDE`), bot (`B01234ABCDE`), or user group (`S01234ABCDE`). To find one, click the profile picture → **⋮** → **Copy member ID**.
* **Reply in a thread:** post **@Annie listen** under any bot's message and Annie resolves the bot automatically.
* **In the app:** add it to the **Annie On-Call Registry** on the [Slack Configuration page](https://app.anyshift.io/integrations/messaging/slack).
Only Organization and Project Admins can register bots (see [Permissions](#permissions)).
## Other settings
The rest lives on the [Slack Configuration page](https://app.anyshift.io/integrations/messaging/slack), which manages channels, channel access, the on-call registry, on-call engineers, webhook investigation notifications, and report delivery per workspace.
When Annie investigates an alert from a webhook source ([PagerDuty](/pages/integration/pagerduty), [incident.io](/pages/integration/incident-io), and similar), you can control when and where Slack gets notified. Open **Integrations → Slack**, then find **Webhook investigation notifications**.
Settings are **per project**. If you have more than one project, the card includes a project selector that starts on your navbar default project; change it only when you want to edit a different project's config.
Use the master switch to enable notifications for the project, then choose which events fire under **Notify on** (start, complete, fail). Under **Destinations**:
* **Channel from the incident**: Post to the Slack channel the source attached when it provides one (for example an incident.io webhook with `slack_channel_id`). This is not a channel picker; the channel comes from the integration or incident.
* **Default notify channel**: Fallback when the incident has no Slack channel (for example PagerDuty). The toggle defaults **off**. Turn it on, then pick a channel from the project's mapped Slack channels. That choice is saved as the project's default notify channel.
If both destinations would resolve to the same channel, Annie posts once (no duplicate).
Defaults when unset: notify-on events and **Channel from the incident** are on; **Default notify channel** stays off until you opt in.
Limit which Slack channels Annie may join and read from. Useful when you want Annie in specific incident or infra channels without exposing the rest of the workspace.
1. Open **Integrations → Slack** and expand the workspace.
2. In **Channel Access**, turn on **Restrict Annie to selected channels**.
3. Search and check the channels Annie should use, then click **Save**.
**Public channels** appear in search immediately. **Private channels** must be on the allowlist before you invite Annie — add the channel here first, then invite `@Annie` once so it appears in the list.
When restriction is on:
* Invites to channels outside the allowlist are rejected.
* Annie ignores messages in unauthorized channels and leaves them automatically when possible.
* You cannot save with the restriction on and zero channels selected (that would lock Annie out everywhere).
To auto-remove Annie from unauthorized **private** channels, reinstall the Slack app so it can grant `groups:write`. Without it, Annie still ignores those channels but may remain a member until removed manually.
When Channel Access is off, behavior is unchanged: Annie works in any channel you invite it to.
In the **On-Call Engineers** section, set who Annie should tag per project when it detects an incident.
Link your Slack identity to your [Anyshift account](https://app.anyshift.io/) for personalized responses and access control. Annie prompts you to connect the first time you interact with it.
## Reports & insights
Annie pushes [proactive](/pages/product/proactive_annie) and [custom](/pages/product/reports) reports into Slack: to a shared channel, to DMs with each project member, or both. Each report keeps its context, so any thread reply continues the discussion with Annie.
### Pause report DMs for yourself
Each project member can control their own report DMs without changing delivery for anyone else. Weekly proactive reports and custom reports have separate preferences, and shared channel posts are unaffected.
Go to [**My Profile**](https://app.anyshift.io/my-profile), then find **Slack Connection → Report notifications**.
If you belong to multiple projects, select the project whose report DMs you want to change. The project selector is hidden when you only have one project.
Turn **Weekly proactive reports** or **Custom reports** on or off. Changes save immediately.
You can also opt out directly from a report DM. Click **Stop weekly report DMs** or **Stop custom report DMs** at the bottom of the message. The message confirms that DMs are paused and shows a **Resume** button if you want to turn them back on.
These personal preferences apply per project. An administrator's **Send via DM** setting controls whether the project sends report DMs at all; your profile switches control whether you personally receive each report category when project DM delivery is enabled.
On the [Slack Integrations page](https://app.anyshift.io/integrations/messaging/slack), in your project's **Insights** section:
* **Send via DM** *(default: on):* every member who linked their Slack account gets the report in a DM.
* **Post to a channel** *(default: off):* pick a channel Annie is in; the report posts with vote buttons and a "View Full Report" link.
Both can be on at once.
Link your Slack account once: DM **@Annie** anything to get a one-time link, click it, and sign in. You'll then appear as Slack-mapped in your project, and Annie DMs you each new report. Link once per workspace.
Each proactive finding has **Relevant** and **Ignore** buttons. Votes save against the finding, update every Slack copy (channel post and DMs), and stay in sync with the Anyshift UI. Custom reports use the **View Full Report** link and thread replies instead.
Reply in any pushed report's thread. Annie opens a chat tied to that report's session, so it already knows the findings, timeline, and integrations without re-pasting context.
## Permissions
Only **Organization** and **Project Admins** can register bots, remap a channel's project, set on-call engineers, or configure **Channel Access**. Everyone else can ask questions and view results. See [Roles & Permissions](/pages/product/project_management/roles).
## Privacy & security
Annie only reads channels it's explicitly added to, and only data from the mapped project's connected integrations. If **Channel Access** is enabled, Annie is further limited to the channels on your allowlist — it won't join or respond elsewhere.
Remove Annie from a channel, or uninstall the app, to revoke access immediately.
Workspace tokens are encrypted at rest, and every Slack-to-Anyshift request is verified with Slack's signing secret.
## Get Started
Install the Slack app and start using Annie in your workspace.
See Annie in action with a personalized walkthrough from our team.
# Proactive Detection
Source: https://docs.anyshift.io/pages/product/proactive_annie
Find production risks before they become incidents.
# Proactive
Proactive runs on a schedule instead of waiting for an alert. Annie investigates your stack on its own and writes a report. It covers what already broke and what's likely to break next, so you see problems before the pager goes off.
Reports live under [**Proactive**](https://app.anyshift.io/proactive) in the sidebar. Export any report to markdown or PDF, or open it in a conversation with **Ask Annie**.
## What's in a report
Each report starts with a severity count, then lists two kinds of finding:
* **Issues investigated:** incidents Annie already root-caused this period, ranked by severity.
* **Proactive risks:** failures that haven't happened yet. Each risk has a category (`capacity_outage`, `degradation`, `cost`, …) and a trend. It shows where things stand now, what happens if nothing changes, the fix to apply, and the monitoring gap that hid it.
- Retry storms and cascading failures
- Hidden monitoring gaps
- Node disruption and restart risks
- Telemetry and logging pipeline degradation
- Connection pool saturation
- Infra misconfigurations, before customer impact
## When it runs
Proactive is enabled per project. It runs on a schedule (weekly in the demo workspace), and each report appears under [**Proactive**](https://app.anyshift.io/proactive). Need a different cadence or scope? Define a [Custom Report](/pages/product/reports) and schedule it daily, weekly, monthly, or yearly.
## Related
Annie investigates the moment an alert fires.
Build your own recurring report on the cadence and scope you choose.
The versioned model behind every risk and fix.
Click Ask Annie on any item to investigate it in a conversation.
# Multiple Projects
Source: https://docs.anyshift.io/pages/product/project_management/multiproject
Running multiple isolated projects within a single Anyshift organization
## Overview
Every Anyshift organization can create multiple projects. Organization admins can create new projects at any time from the **Settings** page.
## How It Works
Each project is fully independent:
* **Integrations** — each project connects to its own cloud accounts, monitoring tools, and repositories.
* **Knowledge graph** — each project builds its own infrastructure knowledge graph.
* **Team members** — users are assigned to projects individually with their own roles.
Organization admins are automatically added to every project with admin access. You do not need to assign them individually.
## When to Use Multiple Projects
Common use cases include:
* **Environment separation** — production, staging, and development in separate projects.
* **Team boundaries** — different teams manage different infrastructure stacks.
* **Security isolation** — restrict access to sensitive infrastructure to specific team members.
## SSO and Multiple Projects
When [SSO auto-provisioning](/pages/privacy_security/sso#auto-provisioning) is enabled, admins can configure which project new users are assigned to. This is managed per email domain in the **Settings > Security > Domains** section.
For example, you can route `@engineering.acme.com` users to your Engineering project and `@ops.acme.com` users to the Ops project. See [Default Project Assignment](/pages/privacy_security/sso#default-project-assignment) for details.
## Getting Started
Go to the **Settings** page and create a new project.
Set up integrations for the new project — each project needs its own connections.
Add users to the project and assign their roles.
# Projects & Team Management
Source: https://docs.anyshift.io/pages/product/project_management/overview
How to create and manage projects, teams, and settings in Anyshift
## What Is a Project?
A project is an isolated workspace in Anyshift. Each project has its own integrations, knowledge graph, and team members. This separation ensures that data and access stay scoped to the right people.
## Creating a Project
Organization admins can create new projects from the **Settings** page. Each project starts with no integrations — you configure them after creation.
You can create multiple projects to separate environments, teams, or infrastructure stacks. See [Multiple Projects](/pages/product/project_management/multiproject) for details.
## Switching Between Projects
Use the project selector in the top navigation bar to switch between projects you have access to. Your current project determines which integrations, knowledge graph, and team you are working with.
## Project Settings
From the **Settings** page, project admins can:
* Rename the project
* Manage integrations (connect cloud providers, monitoring tools, etc.)
* Manage team members (invite users, assign roles)
Organization admins can additionally manage organization-wide settings like MFA enforcement and SSO.
## Learn More
Understand the three roles and what each can do.
Run multiple isolated projects within one organization.
Set up MFA and SSO for your organization.
# Roles & Permissions
Source: https://docs.anyshift.io/pages/product/project_management/roles
Understanding the three roles in Anyshift and what each can do
Anyshift uses role-based access control (RBAC) with three roles: **Organization Admin**, **Project Admin**, and **Member**.
## Role Overview
| Permission | Org Admin | Project Admin | Member |
| --------------------------------- | :-------: | :-----------: | :----: |
| Use Annie chat | ✓ | ✓ | ✓ |
| View project data | ✓ | ✓ | ✓ |
| Manage integrations | ✓ | ✓ | ✗ |
| Invite/remove project members | ✓ | ✓ | ✗ |
| Manage project settings | ✓ | ✓ | ✗ |
| Create projects | ✓ | ✗ | ✗ |
| Manage org admins | ✓ | ✗ | ✗ |
| Configure MFA & SSO | ✓ | ✗ | ✗ |
| Access all projects automatically | ✓ | ✗ | ✗ |
## Organization Admin
Organization admins have full control over the organization and all its projects. They are automatically a project admin on every project — no per-project assignment needed.
Org admins can:
* Create and delete projects
* Promote or demote other org admins
* Enforce MFA and configure SSO
* Manage members across all projects
An org admin cannot be removed from an individual project. To revoke their access, demote them at the organization level first.
## Project Admin
Project admins have read/write access to a specific project. They manage day-to-day operations like connecting integrations and inviting team members.
Project admins can:
* Configure integrations for their project
* Invite and remove project members
* Promote members to project admin
* Manage [Slack channel mappings and on-call registration](/pages/product/integration/slack#permissions--access-control)
## Member
Members have read-only access to the projects they are assigned to. They can use Annie to chat and explore the knowledge graph but cannot change project settings or integrations.
## How Role Assignment Works
* **Org admins** are assigned at the organization level and automatically have admin access to every project.
* **Project admins** and **members** are assigned per project by an org admin or project admin.
* A user can have different roles on different projects (e.g., admin on one, member on another).
# Propose Fix
Source: https://docs.anyshift.io/pages/product/propose_fix
Turn an RCA hypothesis or a chat answer into a pull request. Annie writes the change and opens it for review on GitHub.
## Overview
When Annie identifies a concrete code change in an investigation, that change can be promoted to a pull request with one click. Annie reads the relevant repository, drafts the diff, and opens the PR against the default branch with a summary of the reasoning and a link back to the conversation in Anyshift.
Propose Fix is available on:
* **RCA hypothesis cards** — when a hypothesis points to a specific code remediation, the card carries a Propose Fix button.
* **Chat answers** — when a chat reply describes a specific code change, one or more Propose Fix cards appear below the answer (one per proposed change).
The same coding agent and the same review experience apply to both surfaces.
## Requirements
Propose Fix requires **two** GitHub App installations on your organization. They are separate apps with distinct permission scopes, so the investigation and write-capable surfaces remain isolated.
`anyshift-app` — read-only access used for navigating code, reading PRs and issues, and following commit history during investigations. Installed via **Integrations → GitHub → Connect GitHub Organization**. Required for every Anyshift workspace.
`anyshift-agentic-app` — write-capable access used exclusively by Propose Fix to create branches, push files, and open pull requests. Installed via **Integrations → GitHub → Enable write mode**. **Required for Propose Fix.** Without it, the Propose Fix CTA does not appear and Annie will not attempt write actions.
In addition, the repository touched by the proposal must be **linked to the Anyshift project** that produced the RCA or chat answer. Unlinked repositories never surface a Propose Fix CTA, even when an investigation references their code.
## What clicking it does
The card switches to a "Working on it…" state. You can leave the page; the run continues server-side and the card reflects status when you return.
A dedicated coding agent reads the repository, locates the file and function the hypothesis or answer pointed to, and produces a minimal, focused diff. The agent runs in isolation from your investigation conversation, so the RCA or chat is unchanged.
The PR is opened by the **Anyshift Agentic App** against the repository's default branch. The PR body contains the originating context (RCA hypothesis or chat excerpt) and a link to the conversation in Anyshift.
The card is replaced inline with a link to the pull request. Clicking opens the PR in a new tab. A single proposal may produce more than one PR if the fix spans repositories; each PR gets its own link.
End-to-end latency runs from a few seconds to a couple of minutes depending on the size of the repository and the change.
## States the card can show
* **Idle** — a "Fix - Open PR" button. Click to trigger the run.
* **Running** — a "Working on it…" badge with a spinner while Annie produces the diff and opens the PR.
* **Success, PRs opened** — one or more pull request links. Clicking opens them in a new tab.
* **Success, no change needed** — the coding agent concluded that the repository did not actually require a change. No PR is opened.
* **Failed** — an error message and a **Retry** button. Retry starts a fresh run from the same proposal.
Clicking the trigger again while a run is already in flight is a no-op — the in-flight run is reused.
## Review and merge
The pull request goes through your normal review process: branch protections, required reviewers, CI checks, and merge policies all apply unchanged. Annie's PR is a regular PR.
The fix is a proposal, not a deployment. Nothing reaches production until a human merges. Treat the PR like any other diff: read the change, run CI, request adjustments in review.
If the PR needs adjustments, comment on it like you would for any teammate. Annie does not currently iterate on review comments automatically. If the proposed fix is wrong, close the PR and capture the correction as feedback to refine the next investigation.
## Re-running
* From a **failed** state, the card exposes a **Retry** button that triggers a fresh run from the same proposal.
* From a **success** state, there is no in-product re-run today. The PR link persists as the proposal's outcome.
A successfully opened PR remains linked to its originating hypothesis or chat answer indefinitely, preserving the postmortem trail (investigation → proposal → PR → commit).
## What appears in the PR
A concise title describing the change, followed by a short summary of why the change is being proposed. The summary is generated from the originating hypothesis or chat content, not boilerplate.
A direct link to the conversation in `app.anyshift.io`. Reviewers can open the full investigation to see the alert, the evidence, and the hypothesis or chat the fix is responding to.
A minimal change, scoped to the file or files the proposal pointed to. Annie does not bundle unrelated refactors into the same PR.
Commits and PRs are authored by the **Anyshift Agentic App**. The PR's author appears as the App. Reviewers and assignees are not set automatically; configure them via your repository's CODEOWNERS or PR templates if you want a default reviewer.
## Disabling Propose Fix
Propose Fix is gated on the presence of the **Anyshift Agentic App** installation. To suppress the CTA and prevent any pull request from being opened:
* **Across the entire organization:** uninstall `anyshift-agentic-app` from your GitHub organization. The investigation app (`anyshift-app`) stays installed and all read-only features (RCA, knowledge, navigation) continue working unchanged.
* **For a specific repository:** in the Agentic App's installation settings on GitHub, remove the repository from the selected list. Propose Fix CTAs for that repository disappear; other repositories keep the feature.
There is no per-project toggle inside the Anyshift product; the gate is the agentic-app installation itself.
## Related
How Annie produces the hypotheses Propose Fix acts on.
Install and permission the Anyshift GitHub Apps.
# Reports
Source: https://docs.anyshift.io/pages/product/reports
Save and schedule reusable production reports.
## Overview
A custom report turns a workflow you run often into a reusable template. Start from a built-in template or describe your own (the runbook plus the layout), and Annie generates a fresh report every time it runs, on demand or on a schedule.
You'll find them under [**Custom Reports**](https://app.anyshift.io/reports) in the sidebar. The automated [Proactive Findings](/pages/product/proactive_annie) live under their own **Proactive** entry.
A custom report's tone, framing, and structure come from the **report definition** itself — put any voice or style instructions in the runbook when you author it. [Personas](/pages/product/customization/personas) do not apply to custom reports; they set the voice of automated [Proactive Findings](/pages/product/proactive_annie) instead.
## Start from a template
Each template is a ready-to-run reporting prompt tuned for one operational workflow. Run it as-is, or duplicate it and adjust to your stack.
* **Daily AWS billing outliers:** catch cost spikes from forgotten resources.
* **Weekly PR velocity:** engineering throughput, week over week.
* **Kubernetes pod stability:** restarts, OOMs and evictions worth your morning.
* **Monthly incident digest:** themes, trends and open follow-ups.
* **Error budget burn:** which SLOs are burning faster than plan.
* **Terraform drift review:** human drift vs. provider noise, ranked.
* **Monthly GCP spend:** decomposed by project, SKU and team.
* **On-call handoff notes:** a three-minute read for the next on-call.
## Build your own
Iterate with Annie in a [conversation](/pages/product/annie_knowledge) until the output looks right, then save it as a report. Or duplicate a template above and adjust it to your stack.
## Run it
* **Generate now** runs Annie immediately and adds a fresh instance to the list.
* **Schedule** it and Annie delivers each run on its own: daily, weekly, monthly, or yearly.
The schedule picker previews the next few run times so you know exactly when each report will arrive, and the definition shows a "Next run in…" hint at a glance. Scheduled reports can also be delivered to [Slack](/pages/product/integration/slack). Each recipient can [pause custom report DMs for themselves](/pages/product/integration/slack#pause-report-dms-for-yourself) without affecting channel posts or other project members.
## Review past runs
Every report keeps its full history, newest first. Open any run to read the rendered report, **copy it as markdown**, or **download a PDF** for postmortems and stakeholders.
## Related
Automated Proactive Findings that surface issues and predict risks for you.
Iterate in a conversation, then save the result as a report.
Deliver scheduled reports straight to a channel.
# Root Cause Analysis
Source: https://docs.anyshift.io/pages/product/root_cause_analysis
When incidents occur, Annie automatically correlates alerts, logs, metrics, and infrastructure changes to pinpoint root causes and suggest actionable fixes.
## Automated incident investigation
Alerts fire. Annie investigates. Root cause and remediation land in the incident channel before the on-call engineer has finished joining the bridge.
The investigation correlates infrastructure changes, monitoring data, and dependencies across AWS, GCP, Kubernetes, Terraform, and your monitoring stack. No console-hopping. No tab-jumping.
## Slack channel registration
In your Slack incident channel, run:
```bash theme={null}
/register_annie_on_call @your_bot_name
```
**Example:** `/register_annie_on_call @Datadog`
When an alert fires in your channel, Annie automatically picks it up and starts the investigation.
Annie analyzes the alert, correlates with your infrastructure, and provides the root cause with actionable remediation steps.
Want to customize how Annie responds to specific messages? See [Annie Automation](/pages/product/customization/instructions).
## Alert ingestion sources
Annie investigates incidents originating from four channels:
Automatic RCA when incidents are created. Results posted as incident notes.
Webhook integration for automatic RCA. Results posted as comments.
Mention @Annie with incident details for on-demand investigation.
Trigger RCA from your IDE during development.
## How it works
Investigation runs against the versioned [knowledge graph](/pages/overview/knowledge_graph) of your stack, where every IAM update, Helm rollout, Terraform apply, and merged commit is a node. "What changed in the last 24 hours that touches the payment-service deployment chain?" resolves as a graph diff, not a manual hunt across CloudTrail, kubectl, and git logs. When an alert fires, Annie posts the result back to the incident in about 30 to 90 seconds.
## Postmortem-ready output
When Annie completes an RCA, you receive:
A concise summary suitable for stakeholder communication:
> "The checkout API latency spike was caused by DynamoDB read throttling after a 5x traffic increase from the marketing campaign. Immediate mitigation: increase read capacity to 500 RCU."
Chronological sequence leading to the incident:
* 09:55 - Marketing campaign email sent
* 10:02 - Traffic increases 5x
* 10:05 - DynamoDB throttling begins
* 10:07 - P99 latency exceeds threshold
* 10:08 - Alert fires
Technical details with evidence from your systems:
* What happened
* Why it happened
* Supporting evidence from logs, metrics, and configuration history
List of impacted infrastructure with the specific impact on each.
Actionable fixes organized by urgency:
* **Immediate:** Resolve the incident now
* **Short-term:** Prevent recurrence this sprint
* **Long-term:** Systemic improvements
For hypotheses that map to a concrete code change, the **Propose Fix** button on the hypothesis card opens a pull request with the diff. See [Propose Fix](/pages/product/propose_fix).
## Real-world examples
*"RDS connection timeout on prod-api service"*
> **Root Cause**: Security group `sg-prod-db` was modified at 14:32, removing the inbound rule for the application subnet (10.0.1.0/24).
>
> **Evidence**:
>
> * Security group change detected 15 minutes before alert
> * No changes to RDS instance itself
> * Application logs show "connection refused" starting at 14:35
*"Pod restarts exceeding threshold for payment-service"*
> **Root Cause**: Deployment `payment-service:v2.3.0` was deployed 1 hour ago and has a memory leak. Pods are being OOMKilled.
>
> **Evidence**:
>
> * New image deployed at 10:00
> * Memory usage increased from \~300Mi to 600Mi under load
> * Pod memory limit is 512Mi (see [Kubernetes resource limits](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/))
> * OOMKilled events in Kubernetes
*"P99 latency > 2s on checkout API"*
> **Root Cause**: DynamoDB table `checkout-sessions` is throttling due to exceeded read capacity. A marketing campaign at 10:00 AM increased traffic 5x.
>
> **Evidence**:
>
> * Traffic increased from 100 req/s to 500 req/s at 10:00
> * DynamoDB throttled requests spiked at 10:05
> * Provisioned RCU (100) is insufficient (see [DynamoDB provisioned throughput](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ProvisionedThroughput.html))
## Get Started
Sign up for Anyshift
See RCA in action
## Related
The flip side of RCA. Annie finds and predicts issues before an alert fires.
Ask follow-up questions about any incident in plain language.
The versioned graph Annie traverses to find "what changed".
Replay your stack's state at any point in the last 7 days.
# Change History
Source: https://docs.anyshift.io/pages/product/time_travel
See what changed, when it changed, and what happened before an incident.
## Overview
Annie maintains a **temporal record** of your entire infrastructure, enabling you to ask questions about the state of any resource at any point in time. This "time travel" capability is essential for:
* **Incident Investigation:** *"What changed before the outage?"*
* **Change Validation:** *"Did my Terraform apply work correctly?"*
* **Compliance & Auditing:** *"When was this security group modified?"*
* **Rollback Analysis:** *"What was the previous configuration?"*
**Default Retention: 7 Days**
Annie retains infrastructure history for 7 days by default. You can ask about any resource's state as it existed at any point in the last week.
## What You Can Ask Annie
### Track Recent Changes
Ask Annie what changed in your infrastructure:
* *"What changed in production in the last 24 hours?"*
* *"Show me infrastructure changes from yesterday"*
* *"What was modified in AWS this week?"*
* *"List all security group changes since Monday"*
* *"Show me the history of this RDS instance"*
* *"What happened to my prod-database in the last 3 days?"*
* *"When was this security group last modified?"*
* *"Who changed the IAM role permissions?"*
* *"What did our production VPC look like yesterday at 2pm?"*
* *"Show me the security group rules before the incident"*
* *"What resources existed in staging last week?"*
## Real-World Examples
Production database experiencing connection issues starting at 2:00 PM.
*"What changed in production between 1pm and 3pm today?"*
> I found 3 changes in that window:
>
> * **1:45 PM**: Security group `sg-prod-db` was modified - an inbound rule for subnet 10.0.1.0/24 was removed
> * **1:52 PM**: The prod-api service lost connectivity to the database
> * **2:00 PM**: PagerDuty alert fired
>
> **Root cause**: The security group change at 1:45 PM removed access from the application subnet.
Auditor asks when encryption settings were changed on a sensitive S3 bucket.
*"Show me the history of the sensitive-data-bucket"*
> Here's the change history for sensitive-data-bucket:
>
> * **June 15, 2023**: Bucket created with SSE-S3 encryption
> * **September 1, 2023**: Encryption changed to SSE-KMS with key arn:aws:kms:...
> * **December 15, 2023**: Key rotation policy enabled
>
> The bucket has been encrypted since creation.
You just ran `terraform apply` and want to verify the changes.
*"What changed in the last 30 minutes?"*
> I found 5 resources updated in the last 30 minutes:
>
> * EC2 instance `prod-api-1`: instance type changed from t3.medium to t3.large
> * EC2 instance `prod-api-2`: instance type changed from t3.medium to t3.large
> * Auto Scaling Group `prod-api-asg`: desired capacity changed from 2 to 4
> * Target Group `prod-api-tg`: 2 new targets registered
> * CloudWatch Alarm `prod-api-cpu`: threshold changed from 70% to 80%
>
> All changes match your Terraform configuration.
You suspect someone made manual changes in the AWS console.
*"What resources were modified outside of Terraform this week?"*
> I found 2 resources with manual changes not in your Terraform code:
>
> * Security group `sg-dev-debug`: Port 22 opened to 0.0.0.0/0 via AWS console on Tuesday
> * IAM role `dev-admin-role`: New policy attached manually on Wednesday
>
> Would you like me to show you the specific changes?
See [Drift Detection](/pages/iac/drift_detection) for more on finding the gap between declared and actual infrastructure.
## Best Practices
When investigating issues, ask about changes around the time symptoms first appeared.
If you know which resource is problematic, ask about its specific history.
Ask Annie to show you what a resource looked like before a specific event.
Ask Annie to identify changes made outside of your Infrastructure as Code.
## Get Started
Sign up for Anyshift
See Time Travel in action