Skip to content

AWS skill

The AWS skill lets engineer9 answer infrastructure questions from Slack: health snapshots across EC2, CloudWatch alarms, load balancers, metric trends, and cost breakdowns. It can also start, stop, or reboot EC2 instances after a human approves.

  1. Create a dedicated IAM user for engineer9 in your AWS account. Don’t reuse a shared or personal user; a dedicated user lets you revoke engineer9’s access in isolation.
  2. Attach the access policy below to that user.
  3. Create an access key for the user and enter the key ID and secret in your agent settings on the dashboard.

engineer9 stores your credentials encrypted at rest with AES-256-GCM, using an encryption key derived per workspace (Argon2id, random per-credential salt). They are decrypted when your agent needs them to call AWS.

The skill operates in your configured default region (us-east-1 if unset). Cost Explorer queries run against us-east-1 no matter what you configure; it’s a global service, and the reported costs cover your whole account either way.

engineer9 needs two tiers of access. Most teams should grant only the first.

This covers all query tools: infrastructure summaries, alarms, metrics, instance detail, and costs.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Engineer9ReadOnly",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"cloudwatch:DescribeAlarms",
"cloudwatch:GetMetricStatistics",
"elasticloadbalancing:DescribeLoadBalancers",
"ce:GetCostAndUsage"
],
"Resource": "*"
}
]
}

What each action enables:

ActionEnablesWorth knowing
ec2:DescribeInstancesInstance listings, health summaries, per-instance detailReturns instance metadata including attached IAM roles, security group names, and IP addresses. engineer9 processes this data and passes it to the LLM to generate responses. Don’t grant it if your security policy prohibits sending infrastructure topology to third-party services.
cloudwatch:DescribeAlarmsAlarm status in summaries and alarm queries
cloudwatch:GetMetricStatisticsMetric trends (CPU, latency, etc.)
elasticloadbalancing:DescribeLoadBalancersLoad balancer state in health summaries
ce:GetCostAndUsageCost breakdowns by servicePer-service spend data enters LLM context when cost tools run. If your organization restricts sharing financial data with third-party services, omit this action; cost tools report an error and everything else keeps working.

The read statement uses Resource: "*" because the skill queries account-wide state. These are all read-only Describe/Get actions; none of them can modify anything.

When an AWS call fails, engineer9 posts the error message back to the Slack channel that made the request, and AWS error messages can include ARNs and your account ID. Pick the channels engineer9 operates in with that in mind.

Grant this second statement only if you want engineer9 to start, stop, or reboot EC2 instances. The recommended form scopes it to instances you’ve tagged:

{
"Sid": "Engineer9InstanceControl",
"Effect": "Allow",
"Action": [
"ec2:StartInstances",
"ec2:StopInstances",
"ec2:RebootInstances"
],
"Resource": "arn:aws:ec2:<your-region>:<your-account-id>:instance/*",
"Condition": {
"StringEquals": { "aws:ResourceTag/engineer9-managed": "true" }
}
}

This is a statement fragment, not a standalone policy. Pasting it alone into the IAM console fails validation; add it to the Statement array of the baseline policy above, so one policy document carries both statements.

Replace <your-account-id> with your 12-digit AWS account ID (visible in the AWS console account menu, top right), and <your-region> with the region your instances run in. A * region works but widens the grant: the model picks the query region at request time, so a wildcard-region ARN permits state changes in every region your account uses. Pin it unless you need cross-region control. Tag the instances engineer9 may manage with engineer9-managed = true. If you’d rather allow all instances, replace the Resource value with "*" and drop the Condition; that grants account-wide control of the most destructive permission in this policy.

The policy excludes ec2:TerminateInstances on purpose: engineer9 cannot permanently delete instances, and you shouldn’t add that action.

Two things to know about this statement:

  • It requires the read-only baseline alongside it. Before changing an instance’s state, engineer9 looks the instance up via ec2:DescribeInstances; granting only the instance-control statement means state changes fail at that lookup.
  • The tag condition limits state changes, not visibility. Untagged instances can still be read and summarized through the baseline’s ec2:DescribeInstances. The tag won’t hide instances from engineer9.

About the approval gate: every instance state change requires human approval in Slack before it runs. engineer9 posts the request to the owner of the relevant area and blocks until someone approves, denies, or the request expires. When no clear owner exists, the request routes to a workspace admin and the requester; either can approve, so the person who asked for the change may approve it themselves. The gate is a procedural control, not a technical one: it lives in engineer9’s product layer, not in your AWS account. The IAM scoping above is the independent technical control; it limits what the credential can do even if an approval goes wrong. Use both.

ToolDescription
aws__get_infrastructure_summaryFull health snapshot: EC2 instances by state, active alarms, load balancers, and month-to-date cost in one call
aws__get_alarmsCloudWatch alarms filtered by state (ALARM, OK, …) or name prefix
aws__get_metricsCloudWatch metric statistics with trend direction (e.g. CPUUtilization over the last hour)
aws__get_instance_detailSingle-instance detail: state, type, IPs, security groups, tags, IAM role, volumes, current CPU
aws__get_costsCost and usage breakdown by service for a date range
aws__change_instance_stateStart, stop, or reboot an instance; always requires human approval
@engineer9 give me an infra health summary
@engineer9 which CloudWatch alarms are firing right now?
@engineer9 what did we spend on AWS this month, by service?
@engineer9 restart i-0abc123def456
→ engineer9 posts an approval request and waits for a human before acting