{"slug": "deploying-aws-devops-agent-using-terraform", "title": "Deploying AWS DevOps Agent using Terraform", "summary": "AWS DevOps Agent, an AI-powered operational service for investigating production incidents, can be deployed using Terraform. The service correlates telemetry and infrastructure changes to identify root causes and recommend improvements, with Agent Spaces defining access boundaries. Supported regions include us-east-1, eu-west-1, and others.", "body_md": "AWS DevOps Agent is an AI-powered operational service designed to investigate production incidents, correlate telemetry and infrastructure changes, identify likely root causes, and recommend preventive improvements.\n\nThe service can work with AWS resources, observability platforms, code repositories, CI/CD systems, runbooks, and ticketing systems.\n\nAWS DevOps Agent acts as an operational assistant for DevOps and Site Reliability Engineering teams.\n\nIt can:\n\nAWS defines an Agent Space as the logical boundary controlling what the agent can access. Each Agent Space has its own AWS account access, external integrations, operator permissions, investigation data, and chat history.\n\nAn Agent Space should normally align with an application, business service, platform, or on-call ownership boundary.\n\nAWS DevOps Agent can investigate resources across Regions after an AWS account is associated with the Agent Space. You do not need to create a separate Agent Space in every workload Region.\n\nHowever, the Agent Space itself must be created in a supported Region.\n\nAt the time of writing, supported Regions include:\n\n```\nus-east-1\nus-west-2\nca-central-1\nsa-east-1\nap-south-1\nap-southeast-1\nap-southeast-2\nap-northeast-1\neu-central-1\neu-west-1\neu-west-2\n```\n\nProduction operations are available in all supported Regions, while some preview capabilities can have more limited Regional availability.\n\nFor European workloads, `eu-west-1`\n\nor `eu-central-1`\n\nmay be appropriate depending on latency, data residency, and organizational requirements.\n\nBefore starting, ensure you have:\n\n**Check the installed tools**:\n\n1) terraform version\n\n```\nterraform version\nTerraform v1.15.8\n```\n\n2) AWS CLI version\n\n```\naws --version\naws-cli/2.24.0 Python/3.12.6 Windows/11 exe/AMD64\n```\n\n3) Verify AWS identity:\n\n```\naws sts get-caller-identity`\nExpected output:\n{\n  \"UserId\": \"AIDAXXXXXXXXXXXXXXXX\",\n  \"Account\": \"123456789876\",\n  \"Arn\": \"arn:aws:iam::123456789876:user/terraform-admin\"\n}\n```\n\nFor local testing, an AWS CLI profile can be used:\n\n`aws configure --profile devops-agent-admin`\n\nFor production CI/CD, use temporary credentials through OpenID Connect or an AWS role instead of storing long-lived access keys.\n\nA small environment, can use the following structure:\n\n```\naws-devops-agent-terraform/\n├── backend.tf\n├── versions.tf\n├── providers.tf\n├── variables.tf\n├── locals.tf\n├── data.tf\n├── iam-agent.tf\n├── iam-operator.tf\n├── devops-agent.tf\n├── associations.tf\n├── outputs.tf\n├── terraform.tfvars.example\n└── README.md\n```\n\nFor a larger environment, extract the deployment into a reusable module:\n\n```\naws-devops-agent-terraform/\n├── modules/\n│   └── devops-agent/\n│       ├── main.tf\n│       ├── iam.tf\n│       ├── variables.tf\n│       └── outputs.tf\n└── environments/\n    ├── production/\n    └── non-production/\n```\n\n**Step 1: Configure the Terraform versions**\n\nCreate versions.tf:\n\n```\nterraform {\n  required_version = \">= 1.6.0\"\n\n  required_providers {\n    aws = {\n      source  = \"hashicorp/aws\"\n      version = \"~> 6.0\"\n    }\n\n    awscc = {\n      source  = \"hashicorp/awscc\"\n      version = \"~> 1.0\"\n    }\n\n    time = {\n      source  = \"hashicorp/time\"\n      version = \"~> 0.13\"\n    }\n  }\n}\n```\n\nThe awscc provider is important because AWS DevOps Agent resources are exposed through AWS Cloud Control.\n\nThe time provider can be used to handle IAM propagation delays before creating the Agent Space.\n\n**Step 2: Configure the providers**\n\nCreate providers.tf:\n\n```\nprovider \"aws\" {\n  region  = var.aws_region\n  profile = var.aws_profile\n\n  default_tags {\n    tags = local.common_tags\n  }\n}\n\nprovider \"awscc\" {\n  region  = var.aws_region\n  profile = var.aws_profile\n}\n```\n\nFor local development, profile is acceptable. In CI/CD, remove the profile and let the provider obtain temporary credentials from the pipeline environment:\n\n```\nprovider \"aws\" {\n  region = var.aws_region\n\n  default_tags {\n    tags = local.common_tags\n  }\n}\n\nprovider \"awscc\" {\n  region = var.aws_region\n}\n```\n\nAvoid putting access keys directly inside the provider, as shown below:\n\n```\nprovider \"aws\" {\n  access_key = \"AKIA...\"\n  secret_key = \"...\"\n}\n```\n\n**Step 3: Define variables**\n\nCreate variables.tf:\n\n```\nvariable \"aws_region\" {\n  description = \"AWS Region in which the Agent Space will be created.\"\n  type        = string\n  default     = \"eu-west-1\"\n\n  validation {\n    condition = contains([\n      \"us-east-1\", \n      \"us-west-2\", \n      \"ca-central-1\", \n      \"sa-east-1\",\n      \"ap-south-1\", \n      \"ap-southeast-1\", \n      \"ap-southeast-2\", \n      \"ap-northeast-1\",\n      \"eu-central-1\", \n      \"eu-west-1\", \n      \"eu-west-2\"\n    ], var.aws_region)\n    error_message = \"The selected Region is not currently supported by AWS DevOps Agent.\"\n  }\n}\n\nvariable \"aws_profile\" {\n  description = \"Optional AWS CLI profile for local deployment.\"\n  type        = string\n  default     = null\n}\n\nvariable \"agent_space_name\" {\n  description = \"Name of the AWS DevOps Agent Space.\"\n  type        = string\n\n  validation {\n    condition     = length(trimspace(var.agent_space_name)) > 2\n    error_message = \"The Agent Space name must contain at least three characters.\"\n  }\n}\n\nvariable \"agent_space_description\" {\n  description = \"Description of the Agent Space and its operational boundary.\"\n  type        = string\n}\n\nvariable \"environment\" {\n  description = \"Deployment environment.\"\n  type        = string\n  default     = \"production\"\n\n  validation {\n    condition     = contains([\"development\", \"test\", \"staging\", \"production\"], var.environment)\n    error_message = \"Environment must be development, test, staging, or production.\"\n  }\n}\n\nvariable \"application_name\" {\n  description = \"Application or platform monitored by the Agent Space.\"\n  type        = string\n}\n\nvariable \"additional_tags\" {\n  description = \"Additional tags applied to supported resources.\"\n  type        = map(string)\n  default     = {}\n}\n```\n\n**Step 4: Create common tags**\n\nCreate locals.tf:\n\n```\nlocals {\n  common_tags = merge(\n    {\n      Application = var.application_name\n      Environment = var.environment\n      ManagedBy   = \"Terraform\"\n      Repository  = \"aws-devops-agent-terraform\"\n      Service     = \"AWS-DevOps-Agent\"\n    },\n    var.additional_tags\n  )\n}\n```\n\nTags help with:\n\n**Step 5: Retrieve the current AWS account**\n\nCreate data.tf:\n\n```\ndata \"aws_caller_identity\" \"current\" {}\n\ndata \"aws_partition\" \"current\" {}\n\ndata \"aws_region\" \"current\" {}\n```\n\nThese data sources prevent hardcoding the AWS account ID, partition, and Region.\n\n**Step 6: Create the DevOps Agent IAM role**\n\nAWS DevOps Agent needs an IAM role that the service can assume.\n\nCreate iam-agent.tf:\n\n```\ndata \"aws_iam_policy_document\" \"devops_agent_assume_role\" {\n  statement {\n    sid     = \"AllowAWSDevOpsAgent\"\n    effect  = \"Allow\"\n    actions = [\"sts:AssumeRole\"]\n\n    principals {\n      type        = \"Service\"\n      identifiers = [\"aidevops.amazonaws.com\"]\n    }\n\n    condition {\n      test     = \"StringEquals\"\n      variable = \"aws:SourceAccount\"\n      values   = [data.aws_caller_identity.current.account_id]\n    }\n  }\n}\n\nresource \"aws_iam_role\" \"devops_agent\" {\n  name_prefix        = \"DevOpsAgentRole-AgentSpace-\"\n  description        = \"Role assumed by AWS DevOps Agent for ${var.application_name}\"\n  assume_role_policy = data.aws_iam_policy_document.devops_agent_assume_role.json\n\n  tags = local.common_tags\n}\n\n# Attach the AWS-managed DevOps Agent access policy\nresource \"aws_iam_role_policy_attachment\" \"devops_agent_access\" {\n  role       = aws_iam_role.devops_agent.name\n  policy_arn = \"arn:${data.aws_partition.current.partition}:iam::aws:policy/AIDevOpsAgentAccessPolicy\"\n}\n\n# AWS DevOps Agent can also require permission to create or use the AWS Resource Explorer service-linked role.\n# Create a narrowly scoped inline policy:\ndata \"aws_iam_policy_document\" \"resource_explorer_service_linked_role\" {\n  statement {\n    sid    = \"AllowResourceExplorerServiceLinkedRole\"\n    effect = \"Allow\"\n\n    actions = [\n      \"iam:CreateServiceLinkedRole\"\n    ]\n\n    resources = [\"*\"]\n\n    condition {\n      test     = \"StringEquals\"\n      variable = \"iam:AWSServiceName\"\n      values   = [\"resource-explorer-2.amazonaws.com\"]\n    }\n  }\n}\n\nresource \"aws_iam_role_policy\" \"resource_explorer_service_linked_role\" {\n  name   = \"AllowResourceExplorerServiceLinkedRole\"\n  role   = aws_iam_role.devops_agent.id\n  policy = data.aws_iam_policy_document.resource_explorer_service_linked_role.json\n}\n```\n\nCheck the current AWS-managed policy names in the official AWS documentation before deployment. Service policies can evolve as capabilities are added.\n\n**Step 7: Create the operator web application role**\n\nThe operator role controls what engineers can do through the AWS DevOps Agent web application.\n\nCreate iam-operator.tf:\n\n```\ndata \"aws_iam_policy_document\" \"operator_assume_role\" {\n  statement {\n    sid     = \"AllowAWSDevOpsAgentOperatorApp\"\n    effect  = \"Allow\"\n    actions = [\"sts:AssumeRole\"]\n\n    principals {\n      type        = \"Service\"\n      identifiers = [\"aidevops.amazonaws.com\"]\n    }\n\n    condition {\n      test     = \"StringEquals\"\n      variable = \"aws:SourceAccount\"\n      values   = [data.aws_caller_identity.current.account_id]\n    }\n  }\n}\n\nresource \"aws_iam_role\" \"operator\" {\n  name_prefix        = \"DevOpsAgentRole-WebappAdmin-\"\n  description        = \"Operator web application role for ${var.application_name}\"\n  assume_role_policy = data.aws_iam_policy_document.operator_assume_role.json\n\n  tags = local.common_tags\n}\n\nresource \"aws_iam_role_policy_attachment\" \"operator_access\" {\n  role       = aws_iam_role.operator.name\n  policy_arn = \"arn:${data.aws_partition.current.partition}:iam::aws:policy/AIDevOpsOperatorAppAccessPolicy\"\n}\n```\n\nSeparating the agent role from the operator role is important:\n\nDo not combine these responsibilities into a single role.\n\n**Step 8: Handle IAM propagation**\n\nIAM is eventually consistent. The DevOps Agent service validates the role trust policies while the Agent Space is being created.\n\nAdd a small delay:\n\n```\nresource \"time_sleep\" \"wait_for_iam_propagation\" {\n  create_duration = \"30s\"\n\n  depends_on = [\n    aws_iam_role_policy_attachment.devops_agent_access,\n    aws_iam_role_policy_attachment.operator_access,\n    aws_iam_role_policy.resource_explorer_service_linked_role\n  ]\n}\n```\n\nThe official AWS Terraform example also accounts for IAM propagation. If role validation still fails, waiting briefly and rerunning terraform apply can allow Terraform to continue from the existing IAM resources.\n\n**Step 9: Create the Agent Space**\n\nCreate devops-agent.tf:\n\n```\nresource \"awscc_devopsagent_agent_space\" \"this\" {\n  name        = var.agent_space_name\n  description = var.agent_space_description\n\n  operator_app = {\n    enabled  = true\n    role_arn = aws_iam_role.operator.arn\n  }\n\n  depends_on = [\n    time_sleep.wait_for_iam_propagation\n  ]\n}\n```\n\nThe exact resource schema can change as the AWS Cloud Control resource evolves. Validate the current arguments with:\n\n`terraform providers schema -json`\n\nYou can also inspect the resource documentation:\n\n```\nterraform init\nterraform providers\n```\n\n**Step 10: Associate the monitoring account**\n\nThe account association connects the current AWS account to the Agent Space.\n\nCreate associations.tf:\n\n```\nresource \"awscc_devopsagent_association\" \"monitoring_account\" {\n  agent_space_id = awscc_devopsagent_agent_space.this.agent_space_id\n\n  association_type = \"AWS\"\n\n  configuration = {\n    account_id = data.aws_caller_identity.current.account_id\n    role_arn   = aws_iam_role.devops_agent.arn\n    source_type = \"MONITOR\"\n  }\n\n  depends_on = [\n    awscc_devopsagent_agent_space.this\n  ]\n}\n```\n\nBecause AWS Cloud Control schemas can differ between provider releases, compare the property names with the current Terraform Registry schema before publishing or applying the configuration.\n\nThe official AWS sample is the safest baseline for the exact `awscc_devopsagent_association`\n\nconfiguration. AWS confirms that this association links the monitoring account to the Agent Space.\n\n**Step 11: Define outputs**\n\nCreate outputs.tf:\n\n```\noutput \"agent_space_id\" {\n  description = \"AWS DevOps Agent Space ID.\"\n  value       = awscc_devopsagent_agent_space.this.agent_space_id\n}\n\noutput \"agent_space_arn\" {\n  description = \"AWS DevOps Agent Space ARN.\"\n  value       = awscc_devopsagent_agent_space.this.agent_space_arn\n}\n\noutput \"agent_space_name\" {\n  description = \"AWS DevOps Agent Space name.\"\n  value       = var.agent_space_name\n}\n\noutput \"devops_agent_role_arn\" {\n  description = \"IAM role assumed by AWS DevOps Agent.\"\n  value       = aws_iam_role.devops_agent.arn\n}\n\noutput \"operator_role_arn\" {\n  description = \"Operator web application IAM role.\"\n  value       = aws_iam_role.operator.arn\n}\n\noutput \"monitoring_account_id\" {\n  description = \"AWS monitoring account ID.\"\n  value       = data.aws_caller_identity.current.account_id\n}\n```\n\n**Step 12: Configure the environment**\n\nCreate terraform.tfvars.example:\n\n```\naws_region = \"eu-west-1\"\naws_profile = \"devops-agent-admin\"\n\nagent_space_name = \"payments-production\"\nagent_space_description = \"AWS DevOps Agent Space for the production payments platform\"\n\napplication_name = \"payments-platform\"\nenvironment      = \"production\"\n\nadditional_tags = {\n  Owner       = \"Platform-Engineering\"\n  CostCenter  = \"CC-1234\"\n  Criticality = \"High\"\n}\n```\n\nCopy the file:\n\n`cp terraform.tfvars.example terraform.tfvars`\n\nNever commit `terraform.tfvars`\n\nwhen it contains account-specific or sensitive data.\n\nAdd it to `.gitignore`\n\n:\n\n```\n.terraform/\n*.tfstate\n*.tfstate.*\n*.tfplan\nterraform.tfvars\ncrash.log\noverride.tf\noverride.tf.json\n*_override.tf\n*_override.tf.json\n```\n\nCommit `.terraform.lock.hcl`\n\nso that the same provider versions are used across development and CI/CD environments.\n\n**Step 13: Deploy the Agent Space**\n\nFormat the code:\n\n```\nterraform fmt -recursive\n\nInitialize Terraform:\n\nterraform init\n```\n\nValidate the configuration:\n\n```\nterraform validate\n```\n\nCreate a saved plan:\n\n```\nterraform plan \\\n  -out=tfplan\n```\n\nReview the plan carefully and apply it:\n\n```\nterraform apply tfplan\n```\n\nAfter deployment, inspect the outputs:\n\n```\nterraform output\n```\n\nExample:\n\n```\nagent_space_id     = \"abc123\"\nagent_space_arn    = \"arn:aws:aidevops:eu-west-1:123456789876:agentspace/abc123\"\nagent_space_name   = \"payments-production\"\noperator_role_arn  = \"arn:aws:iam::123456789876:role/DevOpsAgentRole-WebappAdmin-.\n```\n\n**Step 14: Verify the deployment**\n\nUse the AWS CLI:\n\n```\naws devops-agent get-agent-space \\\n  --agent-space-id \"$(terraform output -raw agent_space_id)\" \\\n  --region \"$(terraform output -raw aws_region 2>/dev/null || echo eu-west-1)\"\n```\n\nAlternatively:\n\n```\nAGENT_SPACE_ID=$(terraform output -raw agent_space_id)\n\naws devops-agent get-agent-space \\\n  --agent-space-id \"$AGENT_SPACE_ID\" \\\n  --region eu-west-1\n```\n\nYou can also verify that the IAM roles exist:\n\n```\naws iam get-role \\\n  --role-name \"$(terraform output -raw devops_agent_role_arn | awk -F/ '{print $NF}')\"\n```\n\nThen open the AWS DevOps Agent console and confirm:\n\n**1) Use a remote Terraform backend**\n\nDo not store production Terraform state only on an engineer’s laptop.\n\nExample S3 backend:\n\n```\nterraform {\n  backend \"s3\" {\n    bucket       = \"company-terraform-state-prod\"\n    key          = \"platform/aws-devops-agent/terraform.tfstate\"\n    region       = \"eu-west-1\"\n    encrypt      = true\n    use_lockfile = true\n  }\n}\n```\n\nThe backend bucket should have:\n\nBootstrap the backend separately because Terraform cannot use a backend that does not yet exist.\n\n**2) Protect observability data**\n\nThe agent can process logs, metrics, traces, ticket metadata, resource tags, and other operational information.\n\nDo not place:\n\ninside logs, tags, or incident descriptions.\n\nAWS notes that personally identifiable information is not automatically removed when data is summarized. Sensitive information should therefore be redacted before it enters observability systems.\n\n**1) Resource type not found**\n\nExample:\n\n```\nError: Invalid resource type\n\nThe provider hashicorp/aws does not support resource type\n\"aws_devopsagent_agent_space\".\n```\n\nCause:\n\nAWS DevOps Agent resources use the AWS Cloud Control provider.\n\nSolution:\n\n```\nrequired_providers {\n  awscc = {\n    source  = \"hashicorp/awscc\"\n    version = \"~> 1.0\"\n  }\n}\n```\n\nUse:\n\n```\nawscc_devopsagent_agent_space\nawscc_devopsagent_association\n```\n\nThe official AWS documentation requires the awscc provider for these resources.\n\n**2) IAM trust policy validation failure**\n\nExample:\n\n`The operator role trust policy is invalid`\n\nPossible causes:\n\nResolution:\n\n**3) Access denied while creating the Agent Space**\n\nCheck the caller identity:\n\n```\naws sts get-caller-identity\n```\n\nThen verify the deployment principal can:\n\nAlso check whether an SCP blocks:\n\n```\naidevops:*\niam:CreateServiceLinkedRole\niam:PassRole\n```\n\nDo not grant unrestricted administrator access permanently merely to bypass a policy problem.\n\nTo remove the environment:\n\n```\nterraform plan -destroy -out=destroy.tfplan\nterraform apply destroy.tfplan\n```\n\nOr:\n\n```\nterraform destroy\n```\n\nDestroying an Agent Space can permanently remove its investigation history, recommendations, and associated data. Therefore, review retention requirements before deletion.", "url": "https://wpnews.pro/news/deploying-aws-devops-agent-using-terraform", "canonical_source": "https://dev.to/haythammostafa/deploying-aws-devops-agent-using-terraform-3l12", "published_at": "2026-07-26 16:12:33+00:00", "updated_at": "2026-07-26 17:01:20.737425+00:00", "lang": "en", "topics": ["artificial-intelligence", "ai-products", "developer-tools", "ai-infrastructure"], "entities": ["AWS", "Terraform", "AWS DevOps Agent"], "alternates": {"html": "https://wpnews.pro/news/deploying-aws-devops-agent-using-terraform", "markdown": "https://wpnews.pro/news/deploying-aws-devops-agent-using-terraform.md", "text": "https://wpnews.pro/news/deploying-aws-devops-agent-using-terraform.txt", "jsonld": "https://wpnews.pro/news/deploying-aws-devops-agent-using-terraform.jsonld"}}