npx skills add ...
npx skills add hashicorp/terraform-agent-kit --skill provider-actions
Implement Terraform Provider actions using the Plugin Framework. Use when developing imperative operations that execute at lifecycle events (before/after create, update, destroy).
This repo is now called hashicorp/agent-skills. Both names install the same content, but the install count here only covers this one.
npx skills add hashicorp/terraform-agent-kit --skill provider-actions
Terraform Actions enable imperative operations during the Terraform lifecycle. Actions are experimental features that allow performing provider operations at specific lifecycle events (before/after create, update, destroy).
References:
When adding the first action to a provider that has never had one, several one-time scaffolding steps are required:
ProviderWithActions — add an Actions() method to the provider that returns []func() action.Action.ActionData in Configure — the provider's Configure method must set resp.ActionData = v alongside the existing ResourceData, DataSourceData, and EphemeralResourceData assignments.ActionWithConfigure base type — if the provider uses embedded base types (e.g. ResourceWithConfigure), create an equivalent ActionWithConfigure type implementing action.ConfigureRequest / action.ConfigureResponse.namespace) via helper functions, action-schema variants are needed since action/schema types differ from resource/schema types.Most providers keep actions alongside resources in the provider package:
(Large multi-service providers use internal/service/<service>/ packages
instead — follow the target repository's layout.)
Documentation lives with the other generated docs:
(Some older, large providers hand-write
website/docs/actions/<name>.html.markdown instead — match the repo.)
Actions use the Terraform Plugin Framework with a standard schema pattern:
Pay special attention to the schema definition - common issues after a first draft:
Type Mismatches
types.String/types.Int64 and schemas use
types.StringType from
github.com/hashicorp/terraform-plugin-framework/types — don't mix in
types from other packagesfwtypes); inside such a repo,
follow its convention consistently instead of the plain typesList/Map Element Types
Computed vs Optional
Optional: true and Computed: trueComputed unless they have defaultsValidator Imports
Region/Provider Attribute (multi-region providers, e.g. AWS)
Nested Attributes
Before submitting, verify:
go build to catch type mismatchesThe Invoke method contains the action logic:
resp.SendProgress(action.InvokeProgressEvent{...}) for real-time updatescontext.WithTimeout() for API callsresp.Diagnostics.AddError()Example error handling:
a.client), shared with
resources and data sourcesFor operations that require waiting for completion, poll on a ticker under
a context deadline, reporting progress as you go. (Alternatively use
retry.StateChangeConf from
github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry, the same waiter
primitive resources use.)
Actions are invoked via action_trigger lifecycle blocks in Terraform configurations. A standalone action block without a corresponding trigger is declared but never executed.
Action parameters must be wrapped in a config {} block. Trigger references use the action. prefix, and actions is a list. Events are bare identifiers, not quoted strings.
Supported events (as of Terraform 1.14):
before_create - Before resource creationafter_create - After resource creationbefore_update - Before resource updateafter_update - After resource updateNot supported (as of Terraform 1.14; check current release notes):
before_destroy - Not available (will cause validation error)after_destroy - Not available (will cause validation error)Actions invoked in tests can leave real resources behind; register sweepers
(list → filter test-prefixed names → delete) so leaked resources are
cleanable. Sweepers are not action-specific — use the
provider-test-patterns skill (if available) for the sweep function
pattern, registration, TestMain, and dependency ordering.
terraform_data as a No-Op Triggerterraform_data can serve as a no-op trigger resource for action tests that don't need real infrastructure. This is valuable for error-case and validation tests:
PostApplyFunc to Verify Side EffectsActions don't produce state that can be checked with resource.TestCheckResourceAttr. Use PostApplyFunc on resource.TestStep to query the API after apply and confirm the action produced the expected side effect:
Service-Specific Prerequisites
Error Pattern Matching
regexp.MustCompile(\(?s)Error Title.*key phrase`)`Test Patterns Not Applicable to Actions
Compile-check first, then run the focused acceptance test:
Use the run-acceptance-tests skill (if available) for environment variable
setup, debugging failing tests, and sweeper runs.
Generate action documentation with tfplugindocs where the provider uses
it (use the provider-docs skill, if available, for that workflow). Each
action documentation page must include:
Front Matter (hand-written legacy layouts only)
Header with Warnings
Example Usage
terraform_dataArgument Reference
Documentation Linting (optional tooling)
terrafmt, run terrafmt fmt before submission and
verify with terrafmt diffSome providers (e.g. terraform-provider-aws) track release notes with
go-changelog: one file per PR
in a .changelog/ directory. Check the target repo's CONTRIBUTING guide;
skip this if the repo doesn't use it.
Content format:
Before submitting your action implementation:
go build -o /dev/null .go test -c -o /dev/null ./internal/providergofmt (or the repo's make fmt)terraform-provider-tfe (action_query_run.go, action_query_run_test.go), terraform-provider-vault (action_rotate_root.go)