terraform-provider-aws (Agent Skills)

GitHub

The AWS Provider enables Terraform to manage AWS resources.

AGENTS.md

<!-- Copyright IBM Corp. 2014, 2026 -->
<!-- SPDX-License-Identifier: MPL-2.0 -->

# AGENTS.md

This file provides guidance to AI coding agents when working with code in this repository.

## Repository Overview

This is the Go-based Terraform AWS Provider (`github.com/hashicorp/terraform-provider-aws`). It maps AWS API resources to Terraform resources, data sources, ephemeral resources and actions (collectively often referred to as just resources). The primary language is Go; HCL appears in acceptance test configurations and website documentation.

## Agent Registry

This project uses specialized personas for different tasks.

### Available Personas
- **`@contributor`**: [Contributor Persona](./.agents/contributor.md) - Contributes code in the form of bugfixes, enhancements to existing resources, and new resources. Makes clarifications and corrections to existing documentation.
- **`@maintainer`**: [Maintainer Persona](./.agents/maintainer.md) - Steward of the project, responsible for both internal and external quality. Reviews contributions. Maintains provider-level features, including new Terraform language constructs.
- **`@tcm`**: [TCM Persona](./.agents/tcm.md) - Triages incoming GitHub issues and PRs. Engages with community members to answer technical and process questions. Suggests workarounds and alternatives to reported bugs.

### Registry Rules
- Always use the requested persona for tasks.
- If no persona is specified, default to `@contributor`.
- A persona defines a role with a perspective and responsibilities.
- Personas may invoke skills.

## Skills

Skills are loaded from `./.agents/skills`. Each skill supplies step-by-step instructions, code patterns, and guardrails for a specific task.

| Skill | Task |
|---|---|
| [breaking-changes](./.agents/skills/breaking-changes/SKILL.md) | Review a PR for possible breaking changes. |
| [changelog](./.agents/skills/changelog/SKILL.md) | Add a `.changelog/<PR_NUMBER>.txt` entry from a PR URL, commit, and push (with confirmation). |
| [fixdocs](./.agents/skills/fixdocs/SKILL.md) | Fix end user documentation with `swissshepherd`. |
| [review-pr](./.agents/skills/review-pr/SKILL.md) | Review a Terraform AWS Provider PR. Router: holds cross-cutting principles and routes to the scoped `review-*` leaf skills below based on the files a PR changes. |
| [review-lifecycle](./.agents/skills/review-lifecycle/SKILL.md) | Review resource CRUD, errors, and AutoFlex (`internal/service/**/*.go`). |
| [review-schema](./.agents/skills/review-schema/SKILL.md) | Review Plugin Framework schema shape (`internal/service/**/*.go`). |
| [review-helpers](./.agents/skills/review-helpers/SKILL.md) | Review finders, waiters, sweepers, data sources, list resources (`internal/service/**/*.go`). |
| [review-identity](./.agents/skills/review-identity/SKILL.md) | Review Resource Identity annotations and import-ID handlers (`internal/service/**/*.go`). |
| [review-tags](./.agents/skills/review-tags/SKILL.md) | Review tag schema attributes, wiring, and the `@Tags` annotation (`internal/service/**/*.go`). |
| [review-generated](./.agents/skills/review-generated/SKILL.md) | Review generated code (`internal/service/**/*_gen.go`). |
| [review-tests](./.agents/skills/review-tests/SKILL.md) | Review acceptance/unit test basics (`internal/service/**/*_test.go`). |
| [review-tests-helpers](./.agents/skills/review-tests-helpers/SKILL.md) | Review Exists/Destroy, data source, list, and unit tests (`internal/service/**/*_test.go`). |
| [review-docs](./.agents/skills/review-docs/SKILL.md) | Review a PR's end user documentation updates (`website/docs/**/*.markdown`). |

## Stack
- Go 1.26+, AWS SDK for Go v2.
- Terraform Plugin Framework + Terraform Plugin SDKv2 ([muxed](https://developer.hashicorp.com/terraform/plugin/mux) provider).
- Code generators in `internal/generate/`.
- Build system: GNU Make (see `GNUmakefile`).
- Testing: Go standard `testing` package + [`terraform-plugin-testing` acceptance test framework](https://developer.hashicorp.com/terraform/plugin/testing/acceptance-tests).

## Code Structure (The important parts)

```
terraform-provider-aws/
├── .changelog/             # CHANGELOG entries
├── internal/
│   ├── acctest/            # Acceptance test helpers
│   ├── backoff/            # Low-level backoff loop implementation
│   ├── conns/              # Provider-level global state, including provider configuration
│   ├── enum/               # AWS SDK for Go v2 enumeration utilities
│   ├── errs/               # Go `error` utilities
│   │   ├── fwdiag/         # Terraform Plugin Framework `Diagnostic` utilities
│   │   └── sdkdiag/        # Terraform Plugin SDKv2 `Diagnostic` utilities
│   ├── flex/               # General and Terraform Plugin SDKv2-specific flatteners and expanders
│   ├── framework/          # Terraform Plugin Framework utilities
│   │   ├── flex/           # Flatteners and expanders, including AutoFlex
│   │   ├── types/          # Custom type implementations
│   │   └── validators/     # Validator implementations
│   ├── function/           # Provider functions
│   ├── generate/           # Code generators
│   ├── iter/               # Go iterator utilities
│   ├── json/               # JSON utilities
│   ├── maps/               # Go `map` utilities
│   ├── provider/           # Provider initialization and configuration
│   │   ├── framework/      # Terraform Plugin Framework-specific initialization and configuration plus interceptors
│   │   ├── interceptors/   # Common interceptor utilities
│   │   └── sdkv2/          # Terraform Plugin SDKv2-specific initialization and configuration plus interceptors
│   ├── reflect/            # Go reflection utilities
│   ├── retry/              # Generic operation retry functionality
│   │   └── state.go        # Resource wait-for-state functionality
│   ├── sdkv2/              # Terraform Plugin SDKv2 utilities
│   ├── service/*/          # Per-service resource implementations
│   │   ├── exports.go      # Functions and variables used by other Go packages
│   │   ├── exports_test.go # Functions and variables used by acceptance tests for this Go package
│   │   ├── generate.go     # Code generation instructions
│   │   └── sweep.go        # This service's resource sweepers
│   ├── slices/             # Go slice utilities
│   ├── smerr/              # Smarterr utilities
│   ├── sweep/              # Resource sweeper utilities
│   ├── tags/               # Resource tagging utilities
│   ├── types/              # Go types
│   ├── vcr/                # VCR testing utilities
│   └── verify/             # Terraform Plugin SDKv2-specific attribute validation
├── go.mod
├── go.sum
├── GNUmakefile             # Build and test commands
└── main.go                 # Entry point
```

## Important: Dual Framework

This provider uses TWO Terraform plugin frameworks simultaneously:
- **Terraform Plugin SDKv2** (older resources) — uses `schema.Resource`, `d.Set()`, `d.Get()`
- **Terraform Plugin Framework** (newer resources) — uses `resource.Resource`, plan modifiers, AutoFlex

When modifying an existing resource, use the SAME framework it already uses.
When creating a new resource, use the Terraform Plugin Framework.

## Conventions

### Non-negotiable Rules
- Verification is a hard exit criterion for every PR (see [Development workflow](#development-workflow)). Without it, the task is not done.
- Prefer the boring, obvious solution. Touch only what you're asked to touch.
- Every PR must build, pass tests, and be lint-free.
- Follow existing conventions for naming, style, and idioms.
- Follow current best practices and conventions for naming, style, idioms. Legacy patterns should be avoided.
- Reuse the repository's utility packages (in `internal/`, excluding `internal/generate/` and `internal/service/`) before writing new utility code. Add new dependencies only after exhausting these.

### Coding Conventions (Follow These)

#### Go language usage
- **GO USES TAB (`\t`) CHARACTERS TO INDENT**
- **Use elegant Go, modern (Go 1.26+) idioms** (e.g., `slices.Contains()`)
- **Go nuance**: Don't build single files, **build a package**

#### Error handling
- Use smarterr/smerr
- Use `retry.NotFound()` to check for missing resources during Read.
- Return early on error; don't accumulate diagnostics past the first fatal error.

### Common Patterns

#### Resource file naming
- `internal/service/{service}/{thing}.go` — thing resource implementation
- `internal/service/{service}/{thing}_test.go` — thing resource acceptance tests
- `internal/service/{service}/{thing}_data_source.go` — thing data source
- `website/docs/r/{service}_{thing}.html.markdown` — thing resource documentation
- `website/docs/d/{service}_{thing}.html.markdown` — thing data source documentation

#### Resource implementation pattern (Framework)
New resources use the Terraform Plugin Framework pattern:
- Implement `resource.Resource` interface
- Use AutoFlex for flattening/expanding where possible
- Use `retry.RetryContext` for eventual consistency

For example:
```go
func (r *thingResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
    // 1. Read model from state
    // 2. Call AWS API
    // 3. Handle NotFound → remove from state
    // 4. AutoFlex response into model
    // 5. Write model to state
}
```

## Development workflow

### Overview
- Substantive changes and correctness first, lint after: run `make quick-fix PKG=<service>` near the end, before raising PR. Avoid the tiny change → lint → tiny change → lint loop. `make fmt` is the cheap exception — run it freely.
- Scope most commands to the package changed — the provider is very large. CI is the provider-wide gate for build, lint, and semgrep.

### AI usage
When you help prepare a PR, disclose the AI's role in the description and add `🤖🤖🤖` to the title. See [`docs/ai-usage.md`](docs/ai-usage.md) for the full policy. **Humans are fully responsible for the code regardless of AI usage.**

### Running commands
- `make t` and `make testacc`: Run acceptance tests and create real AWS resources. Get explicit approval before running.
- `make …` (except acceptance tests), `go …`, and read-only commands (`awk`, `grep`, `ls`, `rg`) are safe to run without confirmation.

### Regenerate, test, and verify (scoped to your package)
- **Regenerate** after changing annotations or a service's `generate.go`: `make gen PKG=<service>`. Run the provider-wide `make gen` only after changing `names/data/names_data.hcl`, anything under `internal/generate/` — it affects every service and takes many minutes.
- **Test** with `make test PKG=<service>` (unit test) (`T=<pattern>` filters by name); for non-service changes, e.g., `go test ./internal/conns/...`.
- **Fix and verify** with `make quick-fix PKG=<service>` — the default final pass. It applies formatting, imports, lint, semgrep fixes, and `copyright-fix`, and fails if the build is broken (no separate build step needed).
- **Documentation**: run `make swissshepherd` to verify changes align with docs. Run `make swissshepherd-refresh` only once at the beginning of a session.

### Commits, CHANGELOG, and docs
- Keep each commit small, atomic, and single-purpose; the message describes the change.
- Add a `.changelog/` entry for new features, bug fixes, and enhancements.
- New features require new documentation; `./docs/end-user-documentation.md` is authoritative.

## Boundaries
- Never edit `CHANGELOG.md` directly — use `.changelog/` entries.
- Never edit generated files by hand — modify the generator or annotations, then run `make gen PKG=<service>` or `make gen` (provider level).
- Do not modify `go.mod`/`go.sum` without running `go mod tidy`.
- Do not add new external dependencies without explicit approval.
- The `website/` directory follows different conventions; see `docs/end-user-documentation.md`.